summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/Kconfig9
-rw-r--r--arch/alpha/Kconfig.debug9
-rw-r--r--arch/alpha/defconfig1
-rw-r--r--arch/alpha/kernel/core_irongate.c3
-rw-r--r--arch/alpha/kernel/osf_sys.c7
-rw-r--r--arch/alpha/kernel/pci-noop.c4
-rw-r--r--arch/alpha/kernel/pci_iommu.c24
-rw-r--r--arch/alpha/kernel/process.c63
-rw-r--r--arch/alpha/kernel/setup.c9
-rw-r--r--arch/alpha/kernel/smp.c4
-rw-r--r--arch/alpha/kernel/systbls.S2
-rw-r--r--arch/alpha/kernel/time.c15
-rw-r--r--arch/alpha/mm/numa.c5
-rw-r--r--arch/arm/Kconfig25
-rw-r--r--arch/arm/configs/omap_h2_1610_defconfig201
-rw-r--r--arch/arm/configs/omap_osk_5912_defconfig110
-rw-r--r--arch/arm/configs/orion_defconfig93
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/process.c30
-rw-r--r--arch/arm/kernel/setup.c2
-rw-r--r--arch/arm/kernel/smp.c2
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c1
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c1
-rw-r--r--arch/arm/mach-at91/clock.c2
-rw-r--r--arch/arm/mach-davinci/clock.c4
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-setup.c4
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c6
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-setup.c8
-rw-r--r--arch/arm/mach-omap1/Makefile6
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c7
-rw-r--r--arch/arm/mach-omap1/board-fsample.c6
-rw-r--r--arch/arm/mach-omap1/board-generic.c24
-rw-r--r--arch/arm/mach-omap1/board-h2-mmc.c110
-rw-r--r--arch/arm/mach-omap1/board-h2.c103
-rw-r--r--arch/arm/mach-omap1/board-h3-mmc.c114
-rw-r--r--arch/arm/mach-omap1/board-h3.c75
-rw-r--r--arch/arm/mach-omap1/board-innovator.c19
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c3
-rw-r--r--arch/arm/mach-omap1/board-osk.c25
-rw-r--r--arch/arm/mach-omap1/board-palmte.c84
-rw-r--r--arch/arm/mach-omap1/board-palmtt.c15
-rw-r--r--arch/arm/mach-omap1/board-palmz71.c3
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c8
-rw-r--r--arch/arm/mach-omap1/board-sx1-mmc.c124
-rw-r--r--arch/arm/mach-omap1/board-sx1.c64
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c4
-rw-r--r--arch/arm/mach-omap1/clock.c7
-rw-r--r--arch/arm/mach-omap1/leds-osk.c4
-rw-r--r--arch/arm/mach-omap1/mailbox.c14
-rw-r--r--arch/arm/mach-omap1/pm.c27
-rw-r--r--arch/arm/mach-omap1/sleep.S161
-rw-r--r--arch/arm/mach-orion/addr-map.c14
-rw-r--r--arch/arm/mach-orion/common.c84
-rw-r--r--arch/arm/mach-orion/common.h8
-rw-r--r--arch/arm/mach-orion/db88f5281-setup.c4
-rw-r--r--arch/arm/mach-orion/dns323-setup.c8
-rw-r--r--arch/arm/mach-orion/kurobox_pro-setup.c17
-rw-r--r--arch/arm/mach-orion/pci.c10
-rw-r--r--arch/arm/mach-orion/rd88f5182-setup.c17
-rw-r--r--arch/arm/mach-orion/ts209-setup.c20
-rw-r--r--arch/arm/mach-pxa/Makefile3
-rw-r--r--arch/arm/mach-pxa/generic.c93
-rw-r--r--arch/arm/mach-pxa/generic.h1
-rw-r--r--arch/arm/mach-pxa/gpio.c197
-rw-r--r--arch/arm/mach-pxa/irq.c2
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c10
-rw-r--r--arch/arm/mach-pxa/tosa.c43
-rw-r--r--arch/arm/mach-rpc/riscpc.c2
-rw-r--r--arch/arm/mm/init.c4
-rw-r--r--arch/arm/mm/ioremap.c2
-rw-r--r--arch/arm/mm/mmu.c17
-rw-r--r--arch/arm/mm/nommu.c9
-rw-r--r--arch/arm/mm/pgd.c8
-rw-r--r--arch/arm/plat-omap/Makefile1
-rw-r--r--arch/arm/plat-omap/dma.c844
-rw-r--r--arch/arm/plat-omap/dmtimer.c118
-rw-r--r--arch/arm/plat-omap/fb.c2
-rw-r--r--arch/arm/plat-omap/gpio.c256
-rw-r--r--arch/arm/plat-omap/i2c.c148
-rw-r--r--arch/arm/plat-omap/mcbsp.c11
-rw-r--r--arch/avr32/Kconfig2
-rw-r--r--arch/avr32/kernel/ocd.c18
-rw-r--r--arch/avr32/kernel/setup.c6
-rw-r--r--arch/avr32/kernel/syscall_table.S2
-rw-r--r--arch/avr32/lib/delay.c4
-rw-r--r--arch/avr32/mach-at32ap/at32ap700x.c54
-rw-r--r--arch/avr32/mach-at32ap/pio.c172
-rw-r--r--arch/avr32/mach-at32ap/pio.h2
-rw-r--r--arch/blackfin/Kconfig50
-rw-r--r--arch/blackfin/Kconfig.debug2
-rw-r--r--arch/blackfin/Makefile1
-rw-r--r--arch/blackfin/configs/BF533-STAMP_defconfig16
-rw-r--r--arch/blackfin/kernel/bfin_dma_5xx.c10
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c20
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbinit.c4
-rw-r--r--arch/blackfin/kernel/init_task.c2
-rw-r--r--arch/blackfin/kernel/process.c1
-rw-r--r--arch/blackfin/kernel/setup.c585
-rw-r--r--arch/blackfin/kernel/time.c8
-rw-r--r--arch/blackfin/kernel/traps.c14
-rw-r--r--arch/blackfin/kernel/vmlinux.lds.S47
-rw-r--r--arch/blackfin/mach-bf527/boards/ezkit.c21
-rw-r--r--arch/blackfin/mach-bf533/boards/H8606.c2
-rw-r--r--arch/blackfin/mach-bf533/boards/cm_bf533.c2
-rw-r--r--arch/blackfin/mach-bf533/boards/ezkit.c20
-rw-r--r--arch/blackfin/mach-bf533/boards/stamp.c24
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537.c2
-rw-r--r--arch/blackfin/mach-bf537/boards/generic_board.c2
-rw-r--r--arch/blackfin/mach-bf537/boards/minotaur.c2
-rw-r--r--arch/blackfin/mach-bf537/boards/stamp.c18
-rw-r--r--arch/blackfin/mach-bf548/boards/ezkit.c22
-rw-r--r--arch/blackfin/mach-bf548/dma.c4
-rw-r--r--arch/blackfin/mach-bf561/boards/cm_bf561.c2
-rw-r--r--arch/blackfin/mach-bf561/boards/ezkit.c89
-rw-r--r--arch/blackfin/mach-common/Makefile4
-rw-r--r--arch/blackfin/mach-common/dpmc.S32
-rw-r--r--arch/blackfin/mach-common/entry.S14
-rw-r--r--arch/blackfin/mach-common/ints-priority-dc.c484
-rw-r--r--arch/blackfin/mach-common/ints-priority.c (renamed from arch/blackfin/mach-common/ints-priority-sc.c)271
-rw-r--r--arch/blackfin/mach-common/pm.c44
-rw-r--r--arch/blackfin/mm/init.c12
-rw-r--r--arch/cris/Kconfig548
-rw-r--r--arch/cris/Makefile139
-rw-r--r--arch/cris/arch-v10/Kconfig71
-rw-r--r--arch/cris/arch-v10/boot/Makefile24
-rw-r--r--arch/cris/arch-v10/boot/compressed/Makefile48
-rw-r--r--arch/cris/arch-v10/boot/compressed/misc.c6
-rw-r--r--arch/cris/arch-v10/boot/rescue/Makefile56
-rw-r--r--arch/cris/arch-v10/boot/rescue/head.S129
-rw-r--r--arch/cris/arch-v10/boot/rescue/kimagerescue.S58
-rw-r--r--arch/cris/arch-v10/boot/rescue/testrescue.S12
-rw-r--r--arch/cris/arch-v10/drivers/Kconfig185
-rw-r--r--arch/cris/arch-v10/drivers/Makefile12
-rw-r--r--arch/cris/arch-v10/drivers/axisflashmap.c181
-rw-r--r--arch/cris/arch-v10/drivers/ds1302.c4
-rw-r--r--arch/cris/arch-v10/drivers/eeprom.c75
-rw-r--r--arch/cris/arch-v10/drivers/gpio.c634
-rw-r--r--arch/cris/arch-v10/drivers/i2c.c81
-rw-r--r--arch/cris/arch-v10/drivers/pcf8563.c393
-rw-r--r--arch/cris/arch-v10/drivers/sync_serial.c1441
-rw-r--r--arch/cris/arch-v10/kernel/debugport.c134
-rw-r--r--arch/cris/arch-v10/kernel/dma.c3
-rw-r--r--arch/cris/arch-v10/kernel/entry.S249
-rw-r--r--arch/cris/arch-v10/kernel/fasttimer.c35
-rw-r--r--arch/cris/arch-v10/kernel/head.S221
-rw-r--r--arch/cris/arch-v10/kernel/io_interface_mux.c515
-rw-r--r--arch/cris/arch-v10/kernel/irq.c7
-rw-r--r--arch/cris/arch-v10/kernel/kgdb.c58
-rw-r--r--arch/cris/arch-v10/kernel/process.c3
-rw-r--r--arch/cris/arch-v10/kernel/ptrace.c1
-rw-r--r--arch/cris/arch-v10/kernel/shadows.c3
-rw-r--r--arch/cris/arch-v10/kernel/traps.c198
-rw-r--r--arch/cris/arch-v10/lib/checksum.S8
-rw-r--r--arch/cris/arch-v10/lib/checksumcopy.S8
-rw-r--r--arch/cris/arch-v10/lib/dram_init.S58
-rw-r--r--arch/cris/arch-v10/lib/memset.c397
-rw-r--r--arch/cris/arch-v10/lib/old_checksum.c3
-rw-r--r--arch/cris/arch-v10/mm/fault.c13
-rw-r--r--arch/cris/arch-v10/mm/tlb.c58
-rw-r--r--arch/cris/arch-v32/Kconfig131
-rw-r--r--arch/cris/arch-v32/boot/Makefile23
-rw-r--r--arch/cris/arch-v32/boot/compressed/Makefile45
-rw-r--r--arch/cris/arch-v32/boot/compressed/README1
-rw-r--r--arch/cris/arch-v32/boot/compressed/head.S137
-rw-r--r--arch/cris/arch-v32/boot/compressed/misc.c72
-rw-r--r--arch/cris/arch-v32/boot/rescue/Makefile41
-rw-r--r--arch/cris/arch-v32/boot/rescue/head.S42
-rw-r--r--arch/cris/arch-v32/boot/rescue/rescue.ld37
-rw-r--r--arch/cris/arch-v32/drivers/Kconfig715
-rw-r--r--arch/cris/arch-v32/drivers/Makefile5
-rw-r--r--arch/cris/arch-v32/drivers/axisflashmap.c488
-rw-r--r--arch/cris/arch-v32/drivers/cryptocop.c104
-rw-r--r--arch/cris/arch-v32/drivers/i2c.c206
-rw-r--r--arch/cris/arch-v32/drivers/i2c.h2
-rw-r--r--arch/cris/arch-v32/drivers/iop_fw_load.c16
-rw-r--r--arch/cris/arch-v32/drivers/mach-a3/Makefile6
-rw-r--r--arch/cris/arch-v32/drivers/mach-a3/gpio.c984
-rw-r--r--arch/cris/arch-v32/drivers/mach-a3/nandflash.c180
-rw-r--r--arch/cris/arch-v32/drivers/mach-fs/Makefile6
-rw-r--r--arch/cris/arch-v32/drivers/mach-fs/gpio.c (renamed from arch/cris/arch-v32/drivers/gpio.c)612
-rw-r--r--arch/cris/arch-v32/drivers/mach-fs/nandflash.c (renamed from arch/cris/arch-v32/drivers/nandflash.c)122
-rw-r--r--arch/cris/arch-v32/drivers/pcf8563.c296
-rw-r--r--arch/cris/arch-v32/drivers/pci/dma.c4
-rw-r--r--arch/cris/arch-v32/drivers/sync_serial.c938
-rw-r--r--arch/cris/arch-v32/kernel/Makefile5
-rw-r--r--arch/cris/arch-v32/kernel/arbiter.c296
-rw-r--r--arch/cris/arch-v32/kernel/crisksyms.c7
-rw-r--r--arch/cris/arch-v32/kernel/debugport.c342
-rw-r--r--arch/cris/arch-v32/kernel/entry.S83
-rw-r--r--arch/cris/arch-v32/kernel/fasttimer.c535
-rw-r--r--arch/cris/arch-v32/kernel/head.S204
-rw-r--r--arch/cris/arch-v32/kernel/io.c153
-rw-r--r--arch/cris/arch-v32/kernel/irq.c274
-rw-r--r--arch/cris/arch-v32/kernel/kgdb.c12
-rw-r--r--arch/cris/arch-v32/kernel/process.c14
-rw-r--r--arch/cris/arch-v32/kernel/ptrace.c10
-rw-r--r--arch/cris/arch-v32/kernel/signal.c144
-rw-r--r--arch/cris/arch-v32/kernel/smp.c31
-rw-r--r--arch/cris/arch-v32/kernel/time.c237
-rw-r--r--arch/cris/arch-v32/kernel/traps.c192
-rw-r--r--arch/cris/arch-v32/kernel/vcs_hook.c96
-rw-r--r--arch/cris/arch-v32/lib/Makefile3
-rw-r--r--arch/cris/arch-v32/lib/checksum.S72
-rw-r--r--arch/cris/arch-v32/lib/checksumcopy.S69
-rw-r--r--arch/cris/arch-v32/lib/delay.c28
-rw-r--r--arch/cris/arch-v32/lib/memset.c398
-rw-r--r--arch/cris/arch-v32/lib/spinlock.S10
-rw-r--r--arch/cris/arch-v32/mach-a3/Kconfig110
-rw-r--r--arch/cris/arch-v32/mach-a3/Makefile11
-rw-r--r--arch/cris/arch-v32/mach-a3/arbiter.c634
-rw-r--r--arch/cris/arch-v32/mach-a3/cpufreq.c153
-rw-r--r--arch/cris/arch-v32/mach-a3/dma.c185
-rw-r--r--arch/cris/arch-v32/mach-a3/dram_init.S104
-rw-r--r--arch/cris/arch-v32/mach-a3/hw_settings.S51
-rw-r--r--arch/cris/arch-v32/mach-a3/io.c149
-rw-r--r--arch/cris/arch-v32/mach-a3/pinmux.c386
-rw-r--r--arch/cris/arch-v32/mach-a3/vcs_hook.c103
-rw-r--r--arch/cris/arch-v32/mach-a3/vcs_hook.h58
-rw-r--r--arch/cris/arch-v32/mach-fs/Kconfig216
-rw-r--r--arch/cris/arch-v32/mach-fs/Makefile11
-rw-r--r--arch/cris/arch-v32/mach-fs/arbiter.c404
-rw-r--r--arch/cris/arch-v32/mach-fs/cpufreq.c146
-rw-r--r--arch/cris/arch-v32/mach-fs/dma.c (renamed from arch/cris/arch-v32/kernel/dma.c)46
-rw-r--r--arch/cris/arch-v32/mach-fs/dram_init.S (renamed from arch/cris/arch-v32/lib/dram_init.S)23
-rw-r--r--arch/cris/arch-v32/mach-fs/hw_settings.S (renamed from arch/cris/arch-v32/lib/hw_settings.S)12
-rw-r--r--arch/cris/arch-v32/mach-fs/io.c191
-rw-r--r--arch/cris/arch-v32/mach-fs/pinmux.c309
-rw-r--r--arch/cris/arch-v32/mach-fs/vcs_hook.c100
-rw-r--r--arch/cris/arch-v32/mach-fs/vcs_hook.h (renamed from arch/cris/arch-v32/kernel/vcs_hook.h)8
-rw-r--r--arch/cris/arch-v32/mm/Makefile3
-rw-r--r--arch/cris/arch-v32/mm/init.c8
-rw-r--r--arch/cris/arch-v32/mm/intmem.c48
-rw-r--r--arch/cris/arch-v32/mm/l2cache.c29
-rw-r--r--arch/cris/arch-v32/mm/mmu.S93
-rw-r--r--arch/cris/arch-v32/mm/tlb.c56
-rw-r--r--arch/cris/arch-v32/vmlinux.lds.S74
-rw-r--r--arch/cris/artpec_3_defconfig582
-rw-r--r--arch/cris/defconfig795
-rw-r--r--arch/cris/etraxfs_defconfig585
-rw-r--r--arch/cris/kernel/module.c14
-rw-r--r--arch/cris/kernel/process.c103
-rw-r--r--arch/cris/kernel/ptrace.c58
-rw-r--r--arch/cris/kernel/semaphore.c1
-rw-r--r--arch/cris/kernel/setup.c31
-rw-r--r--arch/cris/kernel/time.c13
-rw-r--r--arch/cris/kernel/traps.c226
-rw-r--r--arch/cris/mm/fault.c169
-rw-r--r--arch/cris/mm/init.c111
-rw-r--r--arch/frv/Kconfig14
-rw-r--r--arch/frv/kernel/entry.S2
-rw-r--r--arch/frv/kernel/setup.c20
-rw-r--r--arch/frv/kernel/time.c6
-rw-r--r--arch/frv/kernel/vmlinux.lds.S6
-rw-r--r--arch/frv/mm/mmu-context.c2
-rw-r--r--arch/frv/mm/pgalloc.c10
-rw-r--r--arch/h8300/Kconfig8
-rw-r--r--arch/h8300/kernel/irq.c1
-rw-r--r--arch/h8300/kernel/setup.c4
-rw-r--r--arch/ia64/Kconfig8
-rw-r--r--arch/ia64/hp/common/sba_iommu.c10
-rw-r--r--arch/ia64/ia32/ia32_support.c5
-rw-r--r--arch/ia64/kernel/acpi-processor.c6
-rw-r--r--arch/ia64/kernel/acpi.c32
-rw-r--r--arch/ia64/kernel/efi.c502
-rw-r--r--arch/ia64/kernel/entry.S7
-rw-r--r--arch/ia64/kernel/fsyscall_gtod_data.h4
-rw-r--r--arch/ia64/kernel/ia64_ksyms.c3
-rw-r--r--arch/ia64/kernel/kprobes.c7
-rw-r--r--arch/ia64/kernel/machine_kexec.c7
-rw-r--r--arch/ia64/kernel/mca.c121
-rw-r--r--arch/ia64/kernel/mca_asm.S46
-rw-r--r--arch/ia64/kernel/mca_drv.c2
-rw-r--r--arch/ia64/kernel/mca_drv.h2
-rw-r--r--arch/ia64/kernel/mca_drv_asm.S2
-rw-r--r--arch/ia64/kernel/perfmon.c27
-rw-r--r--arch/ia64/kernel/process.c59
-rw-r--r--arch/ia64/kernel/ptrace.c139
-rw-r--r--arch/ia64/kernel/sal.c14
-rw-r--r--arch/ia64/kernel/setup.c2
-rw-r--r--arch/ia64/kernel/smpboot.c14
-rw-r--r--arch/ia64/kernel/time.c14
-rw-r--r--arch/ia64/kernel/traps.c35
-rw-r--r--arch/ia64/kernel/unaligned.c13
-rw-r--r--arch/ia64/mm/contig.c2
-rw-r--r--arch/ia64/mm/discontig.c4
-rw-r--r--arch/ia64/mm/fault.c8
-rw-r--r--arch/ia64/pci/pci.c25
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c2
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c11
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c6
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c16
-rw-r--r--arch/m32r/Kconfig8
-rw-r--r--arch/m32r/boot/compressed/m32r_sio.c4
-rw-r--r--arch/m32r/kernel/setup.c13
-rw-r--r--arch/m32r/kernel/smpboot.c1
-rw-r--r--arch/m32r/kernel/syscall_table.S2
-rw-r--r--arch/m32r/mm/discontig.c5
-rw-r--r--arch/m68k/Kconfig22
-rw-r--r--arch/m68k/Makefile11
-rw-r--r--arch/m68k/amiga/Makefile2
-rw-r--r--arch/m68k/amiga/amiga_ksyms.c33
-rw-r--r--arch/m68k/amiga/amisound.c5
-rw-r--r--arch/m68k/amiga/chipram.c9
-rw-r--r--arch/m68k/amiga/cia.c2
-rw-r--r--arch/m68k/amiga/config.c12
-rw-r--r--arch/m68k/amiga/pcmcia.c9
-rw-r--r--arch/m68k/atari/Makefile2
-rw-r--r--arch/m68k/atari/ataints.c3
-rw-r--r--arch/m68k/atari/atari_ksyms.c35
-rw-r--r--arch/m68k/atari/atasound.c2
-rw-r--r--arch/m68k/atari/config.c11
-rw-r--r--arch/m68k/atari/debug.c6
-rw-r--r--arch/m68k/atari/hades-pci.c54
-rw-r--r--arch/m68k/atari/stdma.c5
-rw-r--r--arch/m68k/atari/stram.c5
-rw-r--r--arch/m68k/configs/mac_defconfig1
-rw-r--r--arch/m68k/hp300/Makefile2
-rw-r--r--arch/m68k/hp300/ksyms.c9
-rw-r--r--arch/m68k/kernel/entry.S2
-rw-r--r--arch/m68k/kernel/process.c48
-rw-r--r--arch/m68k/kernel/setup.c5
-rw-r--r--arch/m68k/kernel/traps.c1
-rw-r--r--arch/m68k/mac/Makefile2
-rw-r--r--arch/m68k/mac/config.c2
-rw-r--r--arch/m68k/mac/mac_ksyms.c8
-rw-r--r--arch/m68k/mac/via.c5
-rw-r--r--arch/m68k/mvme16x/Makefile2
-rw-r--r--arch/m68k/mvme16x/config.c2
-rw-r--r--arch/m68k/mvme16x/mvme16x_ksyms.c6
-rw-r--r--arch/m68knommu/Kconfig9
-rw-r--r--arch/m68knommu/Kconfig.debug7
-rw-r--r--arch/m68knommu/defconfig1
-rw-r--r--arch/m68knommu/kernel/m68k_ksyms.c11
-rw-r--r--arch/m68knommu/kernel/setup.c7
-rw-r--r--arch/m68knommu/kernel/syscalltable.S2
-rw-r--r--arch/m68knommu/kernel/time.c12
-rw-r--r--arch/m68knommu/lib/memcpy.c1
-rw-r--r--arch/m68knommu/platform/5206/Makefile4
-rw-r--r--arch/m68knommu/platform/5206e/Makefile4
-rw-r--r--arch/m68knommu/platform/520x/Makefile4
-rw-r--r--arch/m68knommu/platform/523x/Makefile4
-rw-r--r--arch/m68knommu/platform/5249/Makefile4
-rw-r--r--arch/m68knommu/platform/5272/Makefile4
-rw-r--r--arch/m68knommu/platform/527x/Makefile4
-rw-r--r--arch/m68knommu/platform/528x/Makefile4
-rw-r--r--arch/m68knommu/platform/5307/Makefile4
-rw-r--r--arch/m68knommu/platform/532x/Makefile4
-rw-r--r--arch/m68knommu/platform/5407/Makefile4
-rw-r--r--arch/m68knommu/platform/coldfire/Makefile4
-rw-r--r--arch/m68knommu/platform/coldfire/entry.S9
-rw-r--r--arch/m68knommu/platform/coldfire/timers.c17
-rw-r--r--arch/mips/Kconfig1
-rw-r--r--arch/mips/au1000/common/gpio.c1
-rw-r--r--arch/mips/kernel/i8259.c4
-rw-r--r--arch/mips/kernel/irixelf.c14
-rw-r--r--arch/mips/kernel/irixsig.c16
-rw-r--r--arch/mips/kernel/irq.c5
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-rw-r--r--arch/mips/kernel/scall64-64.S2
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/mips/kernel/setup.c4
-rw-r--r--arch/mips/kernel/smp.c1
-rw-r--r--arch/mips/kernel/sysirix.c26
-rw-r--r--arch/mips/sgi-ip27/ip27-memory.c3
-rw-r--r--arch/mn10300/Kconfig381
-rw-r--r--arch/mn10300/Kconfig.debug135
-rw-r--r--arch/mn10300/Makefile135
-rw-r--r--arch/mn10300/boot/.gitignore1
-rw-r--r--arch/mn10300/boot/Makefile28
-rw-r--r--arch/mn10300/boot/compressed/Makefile22
-rw-r--r--arch/mn10300/boot/compressed/head.S86
-rw-r--r--arch/mn10300/boot/compressed/misc.c429
-rw-r--r--arch/mn10300/boot/compressed/misc.h18
-rw-r--r--arch/mn10300/boot/compressed/vmlinux.lds9
-rw-r--r--arch/mn10300/boot/install.sh67
-rw-r--r--arch/mn10300/boot/tools/build.c190
-rw-r--r--arch/mn10300/configs/asb2303_defconfig558
-rw-r--r--arch/mn10300/kernel/Makefile27
-rw-r--r--arch/mn10300/kernel/asm-offsets.c108
-rw-r--r--arch/mn10300/kernel/entry.S721
-rw-r--r--arch/mn10300/kernel/fpu-low.S197
-rw-r--r--arch/mn10300/kernel/fpu.c223
-rw-r--r--arch/mn10300/kernel/gdb-cache.S105
-rw-r--r--arch/mn10300/kernel/gdb-io-serial-low.S90
-rw-r--r--arch/mn10300/kernel/gdb-io-serial.c155
-rw-r--r--arch/mn10300/kernel/gdb-io-ttysm-low.S93
-rw-r--r--arch/mn10300/kernel/gdb-io-ttysm.c299
-rw-r--r--arch/mn10300/kernel/gdb-low.S115
-rw-r--r--arch/mn10300/kernel/gdb-stub.c1947
-rw-r--r--arch/mn10300/kernel/head.S255
-rw-r--r--arch/mn10300/kernel/init_task.c45
-rw-r--r--arch/mn10300/kernel/internal.h20
-rw-r--r--arch/mn10300/kernel/io.c30
-rw-r--r--arch/mn10300/kernel/irq.c235
-rw-r--r--arch/mn10300/kernel/kernel_execve.S37
-rw-r--r--arch/mn10300/kernel/kprobes.c653
-rw-r--r--arch/mn10300/kernel/kthread.S31
-rw-r--r--arch/mn10300/kernel/mn10300-debug.c58
-rw-r--r--arch/mn10300/kernel/mn10300-serial-low.S191
-rw-r--r--arch/mn10300/kernel/mn10300-serial.c1480
-rw-r--r--arch/mn10300/kernel/mn10300-serial.h126
-rw-r--r--arch/mn10300/kernel/mn10300-watchdog-low.S59
-rw-r--r--arch/mn10300/kernel/mn10300-watchdog.c183
-rw-r--r--arch/mn10300/kernel/mn10300_ksyms.c37
-rw-r--r--arch/mn10300/kernel/module.c206
-rw-r--r--arch/mn10300/kernel/process.c297
-rw-r--r--arch/mn10300/kernel/profile-low.S72
-rw-r--r--arch/mn10300/kernel/profile.c51
-rw-r--r--arch/mn10300/kernel/ptrace.c379
-rw-r--r--arch/mn10300/kernel/rtc.c173
-rw-r--r--arch/mn10300/kernel/semaphore.c149
-rw-r--r--arch/mn10300/kernel/setup.c298
-rw-r--r--arch/mn10300/kernel/sigframe.h33
-rw-r--r--arch/mn10300/kernel/signal.c564
-rw-r--r--arch/mn10300/kernel/switch_to.S71
-rw-r--r--arch/mn10300/kernel/sys_mn10300.c193
-rw-r--r--arch/mn10300/kernel/time.c129
-rw-r--r--arch/mn10300/kernel/traps.c619
-rw-r--r--arch/mn10300/kernel/vmlinux.lds.S159
-rw-r--r--arch/mn10300/lib/Makefile7
-rw-r--r--arch/mn10300/lib/__ashldi3.S51
-rw-r--r--arch/mn10300/lib/__ashrdi3.S52
-rw-r--r--arch/mn10300/lib/__lshrdi3.S52
-rw-r--r--arch/mn10300/lib/ashrdi3.c61
-rw-r--r--arch/mn10300/lib/bitops.c51
-rw-r--r--arch/mn10300/lib/checksum.c99
-rw-r--r--arch/mn10300/lib/delay.c50
-rw-r--r--arch/mn10300/lib/do_csum.S162
-rw-r--r--arch/mn10300/lib/internal.h15
-rw-r--r--arch/mn10300/lib/lshrdi3.c60
-rw-r--r--arch/mn10300/lib/memcpy.S135
-rw-r--r--arch/mn10300/lib/memmove.S160
-rw-r--r--arch/mn10300/lib/memset.S121
-rw-r--r--arch/mn10300/lib/negdi2.c57
-rw-r--r--arch/mn10300/lib/usercopy.c166
-rw-r--r--arch/mn10300/mm/Makefile14
-rw-r--r--arch/mn10300/mm/cache-flush-mn10300.S192
-rw-r--r--arch/mn10300/mm/cache-mn10300.S289
-rw-r--r--arch/mn10300/mm/cache.c121
-rw-r--r--arch/mn10300/mm/dma-alloc.c56
-rw-r--r--arch/mn10300/mm/extable.c26
-rw-r--r--arch/mn10300/mm/fault.c405
-rw-r--r--arch/mn10300/mm/init.c160
-rw-r--r--arch/mn10300/mm/misalignment.c661
-rw-r--r--arch/mn10300/mm/mmu-context.c80
-rw-r--r--arch/mn10300/mm/pgtable.c197
-rw-r--r--arch/mn10300/mm/tlb-mn10300.S207
-rw-r--r--arch/mn10300/oprofile/Kconfig23
-rw-r--r--arch/mn10300/oprofile/Makefile13
-rw-r--r--arch/mn10300/oprofile/op_model_null.c22
-rw-r--r--arch/mn10300/proc-mn103e010/Makefile5
-rw-r--r--arch/mn10300/proc-mn103e010/proc-init.c75
-rw-r--r--arch/mn10300/unit-asb2303/Makefile6
-rw-r--r--arch/mn10300/unit-asb2303/flash.c100
-rw-r--r--arch/mn10300/unit-asb2303/leds.c52
-rw-r--r--arch/mn10300/unit-asb2303/smc91111.c52
-rw-r--r--arch/mn10300/unit-asb2303/unit-init.c60
-rw-r--r--arch/mn10300/unit-asb2305/Makefile8
-rw-r--r--arch/mn10300/unit-asb2305/leds.c124
-rw-r--r--arch/mn10300/unit-asb2305/pci-asb2305.c303
-rw-r--r--arch/mn10300/unit-asb2305/pci-asb2305.h82
-rw-r--r--arch/mn10300/unit-asb2305/pci-iomap.c31
-rw-r--r--arch/mn10300/unit-asb2305/pci-irq.c51
-rw-r--r--arch/mn10300/unit-asb2305/pci.c545
-rw-r--r--arch/mn10300/unit-asb2305/unit-init.c61
-rw-r--r--arch/parisc/Kconfig4
-rw-r--r--arch/parisc/Kconfig.debug9
-rw-r--r--arch/parisc/configs/a500_defconfig1
-rw-r--r--arch/parisc/hpux/sys_hpux.c4
-rw-r--r--arch/parisc/kernel/setup.c2
-rw-r--r--arch/parisc/mm/init.c14
-rw-r--r--arch/powerpc/Kconfig36
-rw-r--r--arch/powerpc/Makefile9
-rw-r--r--arch/powerpc/boot/Makefile128
-rw-r--r--arch/powerpc/boot/cuboot-mpc7448hpc2.c (renamed from arch/powerpc/boot/cuboot-hpc2.c)0
-rw-r--r--arch/powerpc/boot/dts/adder875-redboot.dts1
-rw-r--r--arch/powerpc/boot/dts/adder875-uboot.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc5121ads.dts122
-rw-r--r--arch/powerpc/boot/dts/mpc8313erdb.dts4
-rw-r--r--arch/powerpc/boot/dts/mpc8315erdb.dts2
-rw-r--r--arch/powerpc/boot/dts/mpc834x_mds.dts2
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds.dts12
-rw-r--r--arch/powerpc/boot/dts/mpc885ads.dts1
-rw-r--r--arch/powerpc/boot/dts/sequoia.dts8
-rw-r--r--arch/powerpc/boot/dts/storcenter.dts12
-rw-r--r--arch/powerpc/boot/ps3-hvcall.S2
-rwxr-xr-xarch/powerpc/boot/wrapper23
-rw-r--r--arch/powerpc/configs/mpc83xx_defconfig10
-rw-r--r--arch/powerpc/kernel/Makefile6
-rw-r--r--arch/powerpc/kernel/asm-offsets.c3
-rw-r--r--arch/powerpc/kernel/binfmt_elf32.c69
-rw-r--r--arch/powerpc/kernel/cputable.c10
-rw-r--r--arch/powerpc/kernel/dma_64.c8
-rw-r--r--arch/powerpc/kernel/iommu.c93
-rw-r--r--arch/powerpc/kernel/legacy_serial.c3
-rw-r--r--arch/powerpc/kernel/pmc.c2
-rw-r--r--arch/powerpc/kernel/process.c2
-rw-r--r--arch/powerpc/kernel/ptrace.c727
-rw-r--r--arch/powerpc/kernel/ptrace32.c161
-rw-r--r--arch/powerpc/kernel/time.c12
-rw-r--r--arch/powerpc/kernel/traps.c2
-rw-r--r--arch/powerpc/kernel/vdso.c12
-rw-r--r--arch/powerpc/kernel/vio.c2
-rw-r--r--arch/powerpc/mm/mem.c48
-rw-r--r--arch/powerpc/mm/numa.c68
-rw-r--r--arch/powerpc/mm/pgtable_32.c18
-rw-r--r--arch/powerpc/oprofile/Makefile2
-rw-r--r--arch/powerpc/oprofile/cell/spu_task_sync.c15
-rw-r--r--arch/powerpc/oprofile/common.c6
-rw-r--r--arch/powerpc/oprofile/op_model_fsl_emb.c (renamed from arch/powerpc/oprofile/op_model_fsl_booke.c)28
-rw-r--r--arch/powerpc/platforms/40x/Kconfig1
-rw-r--r--arch/powerpc/platforms/40x/virtex.c2
-rw-r--r--arch/powerpc/platforms/40x/walnut.c1
-rw-r--r--arch/powerpc/platforms/44x/warp.c2
-rw-r--r--arch/powerpc/platforms/512x/Kconfig19
-rw-r--r--arch/powerpc/platforms/512x/Makefile4
-rw-r--r--arch/powerpc/platforms/512x/mpc5121_ads.c104
-rw-r--r--arch/powerpc/platforms/52xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/82xx/mpc8272_ads.c3
-rw-r--r--arch/powerpc/platforms/82xx/pq2fads.c3
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_rdb.c2
-rw-r--r--arch/powerpc/platforms/83xx/mpc83xx.h2
-rw-r--r--arch/powerpc/platforms/83xx/usb.c17
-rw-r--r--arch/powerpc/platforms/8xx/adder875.c6
-rw-r--r--arch/powerpc/platforms/8xx/ep88xc.c1
-rw-r--r--arch/powerpc/platforms/Kconfig4
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype14
-rw-r--r--arch/powerpc/platforms/Makefile1
-rw-r--r--arch/powerpc/platforms/cell/Kconfig7
-rw-r--r--arch/powerpc/platforms/cell/axon_msi.c99
-rw-r--r--arch/powerpc/platforms/cell/iommu.c48
-rw-r--r--arch/powerpc/platforms/cell/ras.c11
-rw-r--r--arch/powerpc/platforms/cell/setup.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/Makefile2
-rw-r--r--arch/powerpc/platforms/cell/spufs/backing_ops.c6
-rw-r--r--arch/powerpc/platforms/cell/spufs/fault.c12
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c63
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c50
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c28
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c28
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h10
-rw-r--r--arch/powerpc/platforms/cell/spufs/sputrace.c241
-rw-r--r--arch/powerpc/platforms/cell/spufs/syscalls.c2
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig4
-rw-r--r--arch/powerpc/platforms/embedded6xx/storcenter.c25
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c4
-rw-r--r--arch/powerpc/platforms/iseries/vio.c2
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_32.c2
-rw-r--r--arch/powerpc/platforms/powermac/feature.c11
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c2
-rw-r--r--arch/powerpc/platforms/pseries/kexec.c2
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c1
-rw-r--r--arch/powerpc/platforms/pseries/xics.c118
-rw-r--r--arch/powerpc/platforms/pseries/xics.h3
-rw-r--r--arch/powerpc/sysdev/dcr.c5
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c2
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.c10
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c10
-rw-r--r--arch/ppc/8260_io/enet.c2
-rw-r--r--arch/ppc/8260_io/fcc_enet.c2
-rw-r--r--arch/ppc/Kconfig1
-rw-r--r--arch/ppc/kernel/setup.c2
-rw-r--r--arch/ppc/kernel/vmlinux.lds.S5
-rw-r--r--arch/ppc/mm/pgtable.c13
-rw-r--r--arch/ppc/platforms/prep_setup.c81
-rw-r--r--arch/s390/Kconfig8
-rw-r--r--arch/s390/Kconfig.debug8
-rw-r--r--arch/s390/defconfig87
-rw-r--r--arch/s390/kernel/binfmt_elf32.c11
-rw-r--r--arch/s390/kernel/compat_wrapper.S28
-rw-r--r--arch/s390/kernel/entry.S7
-rw-r--r--arch/s390/kernel/entry64.S7
-rw-r--r--arch/s390/kernel/ipl.c27
-rw-r--r--arch/s390/kernel/process.c1
-rw-r--r--arch/s390/kernel/setup.c26
-rw-r--r--arch/s390/kernel/smp.c13
-rw-r--r--arch/s390/kernel/stacktrace.c31
-rw-r--r--arch/s390/kernel/syscalls.S5
-rw-r--r--arch/s390/kernel/traps.c32
-rw-r--r--arch/s390/kernel/vmlinux.lds.S2
-rw-r--r--arch/s390/mm/fault.c40
-rw-r--r--arch/s390/mm/init.c28
-rw-r--r--arch/s390/mm/mmap.c65
-rw-r--r--arch/s390/mm/pgtable.c174
-rw-r--r--arch/s390/mm/vmem.c33
-rw-r--r--arch/sh/Kconfig23
-rw-r--r--arch/sh/Kconfig.cpu4
-rw-r--r--arch/sh/Kconfig.debug3
-rw-r--r--arch/sh/Makefile1
-rw-r--r--arch/sh/boards/landisk/setup.c2
-rw-r--r--arch/sh/boards/lboxre2/setup.c2
-rw-r--r--arch/sh/boards/renesas/migor/Makefile1
-rw-r--r--arch/sh/boards/renesas/migor/setup.c61
-rw-r--r--arch/sh/boards/renesas/r7780rp/setup.c49
-rw-r--r--arch/sh/boards/renesas/rts7751r2d/setup.c47
-rw-r--r--arch/sh/boards/renesas/sdk7780/Kconfig7
-rw-r--r--arch/sh/boards/renesas/sdk7780/setup.c2
-rw-r--r--arch/sh/boards/se/7722/setup.c2
-rw-r--r--arch/sh/cchips/hd6446x/hd64465/setup.c47
-rw-r--r--arch/sh/configs/migor_defconfig824
-rw-r--r--arch/sh/configs/rts7751r2d1_defconfig340
-rw-r--r--arch/sh/configs/rts7751r2dplus_defconfig340
-rw-r--r--arch/sh/configs/se7705_defconfig1
-rw-r--r--arch/sh/drivers/dma/dma-api.c2
-rw-r--r--arch/sh/drivers/pci/fixups-lboxre2.c4
-rw-r--r--arch/sh/drivers/pci/fixups-rts7751r2d.c4
-rw-r--r--arch/sh/drivers/pci/ops-dreamcast.c44
-rw-r--r--arch/sh/drivers/pci/ops-rts7751r2d.c3
-rw-r--r--arch/sh/drivers/pci/pci-sh4.h4
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.c16
-rw-r--r--arch/sh/drivers/pci/pci-sh7780.c2
-rw-r--r--arch/sh/kernel/Makefile_321
-rw-r--r--arch/sh/kernel/Makefile_641
-rw-r--r--arch/sh/kernel/cpu/irq/Makefile1
-rw-r--r--arch/sh/kernel/cpu/irq/intc-sh5.c27
-rw-r--r--arch/sh/kernel/cpu/irq/maskreg.c93
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c8
-rw-r--r--arch/sh/kernel/cpu/sh4/sq.c2
-rw-r--r--arch/sh/kernel/cpu/sh4a/Makefile2
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7722.c10
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7366.c177
-rw-r--r--arch/sh/kernel/cpu/sh5/probe.c61
-rw-r--r--arch/sh/kernel/io.c8
-rw-r--r--arch/sh/kernel/io_generic.c24
-rw-r--r--arch/sh/kernel/io_trapped.c276
-rw-r--r--arch/sh/kernel/irq.c3
-rw-r--r--arch/sh/kernel/process_64.c9
-rw-r--r--arch/sh/kernel/ptrace_32.c4
-rw-r--r--arch/sh/kernel/setup.c37
-rw-r--r--arch/sh/kernel/syscalls_32.S4
-rw-r--r--arch/sh/kernel/syscalls_64.S4
-rw-r--r--arch/sh/kernel/time_32.c19
-rw-r--r--arch/sh/kernel/time_64.c31
-rw-r--r--arch/sh/kernel/timers/timer-cmt.c9
-rw-r--r--arch/sh/kernel/timers/timer-mtu2.c3
-rw-r--r--arch/sh/kernel/traps_32.c164
-rw-r--r--arch/sh/kernel/traps_64.c4
-rw-r--r--arch/sh/kernel/vmlinux_64.lds.S2
-rw-r--r--arch/sh/mm/cache-sh5.c1019
-rw-r--r--arch/sh/mm/consistent.c32
-rw-r--r--arch/sh/mm/fault_32.c11
-rw-r--r--arch/sh/mm/init.c2
-rw-r--r--arch/sh/mm/numa.c4
-rw-r--r--arch/sh/tools/mach-types2
-rw-r--r--arch/sparc/Kconfig8
-rw-r--r--arch/sparc/kernel/entry.S17
-rw-r--r--arch/sparc/kernel/errtbls.c144
-rw-r--r--arch/sparc/kernel/of_device.c27
-rw-r--r--arch/sparc/kernel/pcic.c2
-rw-r--r--arch/sparc/kernel/process.c33
-rw-r--r--arch/sparc/kernel/ptrace.c813
-rw-r--r--arch/sparc/kernel/setup.c1
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c3
-rw-r--r--arch/sparc/kernel/sun4d_smp.c4
-rw-r--r--arch/sparc/kernel/sun4m_smp.c5
-rw-r--r--arch/sparc/kernel/systbls.S6
-rw-r--r--arch/sparc/kernel/time.c7
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S4
-rw-r--r--arch/sparc/mm/init.c6
-rw-r--r--arch/sparc/mm/loadmmu.c1
-rw-r--r--arch/sparc/mm/srmmu.c11
-rw-r--r--arch/sparc/mm/sun4c.c14
-rw-r--r--arch/sparc64/Kconfig18
-rw-r--r--arch/sparc64/defconfig83
-rw-r--r--arch/sparc64/kernel/Makefile3
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c3
-rw-r--r--arch/sparc64/kernel/binfmt_elf32.c159
-rw-r--r--arch/sparc64/kernel/entry.S4
-rw-r--r--arch/sparc64/kernel/head.S25
-rw-r--r--arch/sparc64/kernel/iommu.c452
-rw-r--r--arch/sparc64/kernel/iommu_common.c244
-rw-r--r--arch/sparc64/kernel/iommu_common.h56
-rw-r--r--arch/sparc64/kernel/irq.c2
-rw-r--r--arch/sparc64/kernel/kprobes.c113
-rw-r--r--arch/sparc64/kernel/of_device.c26
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c388
-rw-r--r--arch/sparc64/kernel/process.c12
-rw-r--r--arch/sparc64/kernel/ptrace.c1197
-rw-r--r--arch/sparc64/kernel/setup.c1
-rw-r--r--arch/sparc64/kernel/smp.c2
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c2
-rw-r--r--arch/sparc64/kernel/sys_sparc.c1
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c1
-rw-r--r--arch/sparc64/kernel/systbls.S11
-rw-r--r--arch/sparc64/kernel/time.c5
-rw-r--r--arch/sparc64/mm/init.c8
-rw-r--r--arch/sparc64/prom/init.c3
-rw-r--r--arch/sparc64/solaris/fs.c14
-rw-r--r--arch/sparc64/solaris/misc.c4
-rw-r--r--arch/sparc64/solaris/timod.c6
-rw-r--r--arch/um/Kconfig37
-rw-r--r--arch/um/Kconfig.char2
-rw-r--r--arch/um/Kconfig.debug6
-rw-r--r--arch/um/Kconfig.i38639
-rw-r--r--arch/um/Kconfig.net12
-rw-r--r--arch/um/Kconfig.x86_646
-rw-r--r--arch/um/Makefile23
-rw-r--r--arch/um/Makefile-tt5
-rw-r--r--arch/um/defconfig9
-rw-r--r--arch/um/drivers/line.c28
-rw-r--r--arch/um/drivers/mconsole_kern.c61
-rw-r--r--arch/um/drivers/mconsole_user.c5
-rw-r--r--arch/um/drivers/net_kern.c16
-rw-r--r--arch/um/drivers/net_user.c2
-rw-r--r--arch/um/drivers/port_kern.c7
-rw-r--r--arch/um/drivers/random.c1
-rw-r--r--arch/um/drivers/slip_user.c2
-rw-r--r--arch/um/drivers/slirp_user.c2
-rw-r--r--arch/um/drivers/ssl.c1
-rw-r--r--arch/um/drivers/stdio_console.c1
-rw-r--r--arch/um/drivers/ubd_kern.c30
-rw-r--r--arch/um/drivers/ubd_user.c1
-rw-r--r--arch/um/drivers/vde_user.c2
-rw-r--r--arch/um/include/arch.h2
-rw-r--r--arch/um/include/as-layout.h36
-rw-r--r--arch/um/include/chan_user.h2
-rw-r--r--arch/um/include/common-offsets.h1
-rw-r--r--arch/um/include/init.h25
-rw-r--r--arch/um/include/irq_user.h1
-rw-r--r--arch/um/include/kern_util.h120
-rw-r--r--arch/um/include/mem_user.h5
-rw-r--r--arch/um/include/misc_constants.h6
-rw-r--r--arch/um/include/os.h46
-rw-r--r--arch/um/include/ptrace_user.h11
-rw-r--r--arch/um/include/registers.h7
-rw-r--r--arch/um/include/signal_kern.h22
-rw-r--r--arch/um/include/skas/mode-skas.h11
-rw-r--r--arch/um/include/sysdep-i386/syscalls.h5
-rw-r--r--arch/um/include/sysdep-x86_64/kernel-offsets.h9
-rw-r--r--arch/um/include/sysdep-x86_64/syscalls.h2
-rw-r--r--arch/um/include/tempfile.h11
-rw-r--r--arch/um/include/um_mmu.h5
-rw-r--r--arch/um/include/um_uaccess.h4
-rw-r--r--arch/um/kernel/exec.c5
-rw-r--r--arch/um/kernel/exitcode.c31
-rw-r--r--arch/um/kernel/gmon_syms.c11
-rw-r--r--arch/um/kernel/gprof_syms.c13
-rw-r--r--arch/um/kernel/initrd.c30
-rw-r--r--arch/um/kernel/irq.c6
-rw-r--r--arch/um/kernel/ksyms.c7
-rw-r--r--arch/um/kernel/mem.c151
-rw-r--r--arch/um/kernel/physmem.c16
-rw-r--r--arch/um/kernel/process.c158
-rw-r--r--arch/um/kernel/reboot.c7
-rw-r--r--arch/um/kernel/sigio.c18
-rw-r--r--arch/um/kernel/signal.c16
-rw-r--r--arch/um/kernel/skas/clone.c32
-rw-r--r--arch/um/kernel/skas/mmu.c132
-rw-r--r--arch/um/kernel/skas/process.c20
-rw-r--r--arch/um/kernel/skas/syscall.c6
-rw-r--r--arch/um/kernel/skas/uaccess.c140
-rw-r--r--arch/um/kernel/smp.c14
-rw-r--r--arch/um/kernel/syscall.c3
-rw-r--r--arch/um/kernel/sysrq.c44
-rw-r--r--arch/um/kernel/time.c14
-rw-r--r--arch/um/kernel/tlb.c51
-rw-r--r--arch/um/kernel/trap.c33
-rw-r--r--arch/um/kernel/uaccess.c11
-rw-r--r--arch/um/kernel/um_arch.c112
-rw-r--r--arch/um/kernel/umid.c15
-rw-r--r--arch/um/os-Linux/Makefile4
-rw-r--r--arch/um/os-Linux/aio.c3
-rw-r--r--arch/um/os-Linux/drivers/ethertap_kern.c8
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_kern.c6
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c5
-rw-r--r--arch/um/os-Linux/file.c287
-rw-r--r--arch/um/os-Linux/helper.c74
-rw-r--r--arch/um/os-Linux/include/file.h13
-rw-r--r--arch/um/os-Linux/irq.c39
-rw-r--r--arch/um/os-Linux/main.c14
-rw-r--r--arch/um/os-Linux/mem.c125
-rw-r--r--arch/um/os-Linux/process.c7
-rw-r--r--arch/um/os-Linux/registers.c34
-rw-r--r--arch/um/os-Linux/sigio.c244
-rw-r--r--arch/um/os-Linux/signal.c104
-rw-r--r--arch/um/os-Linux/skas/Makefile6
-rw-r--r--arch/um/os-Linux/skas/process.c287
-rw-r--r--arch/um/os-Linux/skas/trap.c69
-rw-r--r--arch/um/os-Linux/start_up.c17
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile2
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c4
-rw-r--r--arch/um/os-Linux/sys-i386/task_size.c120
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile2
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c21
-rw-r--r--arch/um/os-Linux/sys-x86_64/task_size.c5
-rw-r--r--arch/um/os-Linux/trap.c23
-rw-r--r--arch/um/os-Linux/tty.c57
-rw-r--r--arch/um/os-Linux/tty_log.c1
-rw-r--r--arch/um/os-Linux/uaccess.c4
-rw-r--r--arch/um/os-Linux/user_syms.c4
-rw-r--r--arch/um/os-Linux/util.c58
-rw-r--r--arch/um/sys-i386/bug.c1
-rw-r--r--arch/um/sys-i386/bugs.c201
-rw-r--r--arch/um/sys-i386/ldt.c19
-rw-r--r--arch/um/sys-i386/ptrace.c6
-rw-r--r--arch/um/sys-i386/ptrace_user.c14
-rw-r--r--arch/um/sys-i386/signal.c18
-rw-r--r--arch/um/sys-i386/stub.S8
-rw-r--r--arch/um/sys-i386/stub_segv.c19
-rw-r--r--arch/um/sys-i386/sys_call_table.S5
-rw-r--r--arch/um/sys-i386/tls.c41
-rw-r--r--arch/um/sys-ppc/Makefile22
-rw-r--r--arch/um/sys-x86_64/bug.c3
-rw-r--r--arch/um/sys-x86_64/bugs.c7
-rw-r--r--arch/um/sys-x86_64/ptrace.c29
-rw-r--r--arch/um/sys-x86_64/ptrace_user.c46
-rw-r--r--arch/um/sys-x86_64/signal.c4
-rw-r--r--arch/um/sys-x86_64/stub.S8
-rw-r--r--arch/um/sys-x86_64/stub_segv.c39
-rw-r--r--arch/um/sys-x86_64/syscall_table.c43
-rw-r--r--arch/um/sys-x86_64/syscalls.c10
-rw-r--r--arch/um/sys-x86_64/sysrq.c29
-rw-r--r--arch/um/sys-x86_64/um_module.c8
-rw-r--r--arch/v850/Kconfig11
-rw-r--r--arch/v850/kernel/anna.c3
-rw-r--r--arch/v850/kernel/as85ep1.c3
-rw-r--r--arch/v850/kernel/procfs.c2
-rw-r--r--arch/v850/kernel/rte_ma1_cb.c6
-rw-r--r--arch/v850/kernel/setup.c12
-rw-r--r--arch/x86/Kconfig26
-rw-r--r--arch/x86/Kconfig.debug10
-rw-r--r--arch/x86/Makefile4
-rw-r--r--arch/x86/boot/.gitignore2
-rw-r--r--arch/x86/boot/printf.c24
-rw-r--r--arch/x86/configs/i386_defconfig1
-rw-r--r--arch/x86/configs/x86_64_defconfig1
-rw-r--r--arch/x86/ia32/ia32_aout.c3
-rw-r--r--arch/x86/ia32/ia32entry.S4
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/acpi/boot.c47
-rw-r--r--arch/x86/kernel/acpi/cstate.c2
-rw-r--r--arch/x86/kernel/acpi/processor.c6
-rw-r--r--arch/x86/kernel/cpu/common.c2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/Kconfig4
-rw-r--r--arch/x86/kernel/cpu/cpufreq/e_powersaver.c61
-rw-r--r--arch/x86/kernel/cpu/cpufreq/gx-suspmod.c4
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k7.c2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k8.c10
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k8.h2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-lib.c5
-rw-r--r--arch/x86/kernel/cpu/cyrix.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/therm_throt.c2
-rw-r--r--arch/x86/kernel/cpu/mtrr/main.c19
-rw-r--r--arch/x86/kernel/efi.c14
-rw-r--r--arch/x86/kernel/efi_64.c32
-rw-r--r--arch/x86/kernel/entry_32.S15
-rw-r--r--arch/x86/kernel/entry_64.S40
-rw-r--r--arch/x86/kernel/geode_32.c5
-rw-r--r--arch/x86/kernel/head_32.S151
-rw-r--r--arch/x86/kernel/head_64.S15
-rw-r--r--arch/x86/kernel/i8253.c2
-rw-r--r--arch/x86/kernel/machine_kexec_32.c2
-rw-r--r--arch/x86/kernel/machine_kexec_64.c5
-rw-r--r--arch/x86/kernel/mfgpt_32.c123
-rw-r--r--arch/x86/kernel/mpparse_32.c6
-rw-r--r--arch/x86/kernel/pci-calgary_64.c34
-rw-r--r--arch/x86/kernel/pci-gart_64.c57
-rw-r--r--arch/x86/kernel/process_32.c50
-rw-r--r--arch/x86/kernel/process_64.c1
-rw-r--r--arch/x86/kernel/ptrace.c25
-rw-r--r--arch/x86/kernel/quirks.c35
-rw-r--r--arch/x86/kernel/reboot.c46
-rw-r--r--arch/x86/kernel/setup_32.c22
-rw-r--r--arch/x86/kernel/setup_64.c38
-rw-r--r--arch/x86/kernel/smpboot_32.c2
-rw-r--r--arch/x86/kernel/srat_32.c2
-rw-r--r--arch/x86/kernel/syscall_table_32.S4
-rw-r--r--arch/x86/kernel/test_nx.c2
-rw-r--r--arch/x86/kernel/test_rodata.c2
-rw-r--r--arch/x86/kernel/time_64.c2
-rw-r--r--arch/x86/kernel/topology.c2
-rw-r--r--arch/x86/kernel/traps_32.c15
-rw-r--r--arch/x86/kernel/traps_64.c4
-rw-r--r--arch/x86/kvm/x86.c8
-rw-r--r--arch/x86/lib/Makefile2
-rw-r--r--arch/x86/lib/bitstr_64.c28
-rw-r--r--arch/x86/lib/delay_32.c4
-rw-r--r--arch/x86/lib/delay_64.c4
-rw-r--r--arch/x86/mach-voyager/voyager_smp.c2
-rw-r--r--arch/x86/mm/discontig_32.c3
-rw-r--r--arch/x86/mm/fault.c30
-rw-r--r--arch/x86/mm/init_32.c75
-rw-r--r--arch/x86/mm/init_64.c22
-rw-r--r--arch/x86/mm/ioremap.c57
-rw-r--r--arch/x86/mm/numa_64.c5
-rw-r--r--arch/x86/mm/pageattr-test.c72
-rw-r--r--arch/x86/mm/pageattr.c176
-rw-r--r--arch/x86/mm/pgtable_32.c17
-rw-r--r--arch/x86/mm/srat_64.c3
-rw-r--r--arch/x86/pci/common.c25
-rw-r--r--arch/x86/pci/direct.c4
-rw-r--r--arch/x86/pci/fixup.c6
-rw-r--r--arch/x86/pci/i386.c2
-rw-r--r--arch/x86/pci/legacy.c2
-rw-r--r--arch/x86/pci/mmconfig-shared.c41
-rw-r--r--arch/x86/pci/mmconfig_32.c20
-rw-r--r--arch/x86/pci/mmconfig_64.c18
-rw-r--r--arch/x86/pci/pci.h22
-rw-r--r--arch/x86/pci/visws.c3
-rw-r--r--arch/x86/power/Makefile4
-rw-r--r--arch/x86/power/cpu_32.c (renamed from arch/x86/power/cpu.c)2
-rw-r--r--arch/x86/power/cpu_64.c (renamed from arch/x86/kernel/suspend_64.c)160
-rw-r--r--arch/x86/power/hibernate_32.c (renamed from arch/x86/power/suspend.c)6
-rw-r--r--arch/x86/power/hibernate_64.c169
-rw-r--r--arch/x86/power/hibernate_asm_32.S (renamed from arch/x86/power/swsusp.S)3
-rw-r--r--arch/x86/power/hibernate_asm_64.S (renamed from arch/x86/kernel/suspend_asm_64.S)9
-rw-r--r--arch/x86/vdso/Makefile22
-rw-r--r--arch/x86/xen/enlighten.c4
-rw-r--r--arch/x86/xen/mmu.c6
-rw-r--r--arch/x86/xen/time.c10
-rw-r--r--arch/xtensa/Kconfig5
-rw-r--r--arch/xtensa/kernel/setup.c2
-rw-r--r--arch/xtensa/kernel/time.c2
915 files changed, 46470 insertions, 17539 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 01b10ab588a..002703b8c0b 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -5,6 +5,7 @@
config ALPHA
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
help
The Alpha is a 64-bit general-purpose processor designed and
@@ -67,6 +68,9 @@ config AUTO_IRQ_AFFINITY
depends on SMP
default y
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
source "init/Kconfig"
@@ -612,6 +616,11 @@ config VERBOSE_MCHECK_ON
Take the default (1) unless you want more control or more info.
+config HZ
+ int
+ default 1200 if ALPHA_RAWHIDE
+ default 1024
+
source "drivers/pci/Kconfig"
source "drivers/eisa/Kconfig"
diff --git a/arch/alpha/Kconfig.debug b/arch/alpha/Kconfig.debug
index f45f28cc10d..3f6265f2d9d 100644
--- a/arch/alpha/Kconfig.debug
+++ b/arch/alpha/Kconfig.debug
@@ -7,15 +7,6 @@ config EARLY_PRINTK
depends on ALPHA_GENERIC || ALPHA_SRM
default y
-config DEBUG_RWLOCK
- bool "Read-write spinlock debugging"
- depends on DEBUG_KERNEL
- help
- If you say Y here then read-write lock processing will count how many
- times it has tried to get the lock and issue an error message after
- too many attempts. If you suspect a rwlock problem or a kernel
- hacker asks for this option then say Y. Otherwise say N.
-
config ALPHA_LEGACY_START_ADDRESS
bool "Legacy kernel start address"
depends on ALPHA_GENERIC
diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig
index 6da9c3dbde4..e43f68fd66b 100644
--- a/arch/alpha/defconfig
+++ b/arch/alpha/defconfig
@@ -882,7 +882,6 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_SPINLOCK is not set
CONFIG_DEBUG_INFO=y
CONFIG_EARLY_PRINTK=y
-# CONFIG_DEBUG_RWLOCK is not set
# CONFIG_DEBUG_SEMAPHORE is not set
CONFIG_ALPHA_LEGACY_START_ADDRESS=y
CONFIG_MATHEMU=y
diff --git a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c
index e4a0bcf1d28..a872078497b 100644
--- a/arch/alpha/kernel/core_irongate.c
+++ b/arch/alpha/kernel/core_irongate.c
@@ -241,7 +241,8 @@ albacore_init_arch(void)
size / 1024);
}
#endif
- reserve_bootmem_node(NODE_DATA(0), pci_mem, memtop - pci_mem);
+ reserve_bootmem_node(NODE_DATA(0), pci_mem, memtop -
+ pci_mem, BOOTMEM_DEFAULT);
printk("irongate_init_arch: temporarily reserving "
"region %08lx-%08lx for PCI\n", pci_mem, memtop - 1);
}
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 6413c5f2322..8c71daf94a5 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -22,7 +22,6 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/utsname.h>
#include <linux/time.h>
#include <linux/timex.h>
@@ -260,8 +259,8 @@ osf_statfs(char __user *path, struct osf_statfs __user *buffer, unsigned long bu
retval = user_path_walk(path, &nd);
if (!retval) {
- retval = do_osf_statfs(nd.dentry, buffer, bufsiz);
- path_release(&nd);
+ retval = do_osf_statfs(nd.path.dentry, buffer, bufsiz);
+ path_put(&nd.path);
}
return retval;
}
@@ -430,7 +429,7 @@ sys_getpagesize(void)
asmlinkage unsigned long
sys_getdtablesize(void)
{
- return NR_OPEN;
+ return sysctl_nr_open;
}
/*
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index 468b76ce66a..8ac08311f5a 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -165,7 +165,7 @@ dma_alloc_coherent(struct device *dev, size_t size,
ret = (void *)__get_free_pages(gfp, get_order(size));
if (ret) {
memset(ret, 0, size);
- *dma_handle = virt_to_bus(ret);
+ *dma_handle = virt_to_phys(ret);
}
return ret;
}
@@ -184,7 +184,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
BUG_ON(!sg_page(sg));
va = sg_virt(sg);
- sg_dma_address(sg) = (dma_addr_t)virt_to_bus(va);
+ sg_dma_address(sg) = (dma_addr_t)virt_to_phys(va);
sg_dma_len(sg) = sg->length;
}
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 2d00a08d3f0..26d3789dfdd 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -9,6 +9,7 @@
#include <linux/bootmem.h>
#include <linux/scatterlist.h>
#include <linux/log2.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
@@ -470,22 +471,29 @@ EXPORT_SYMBOL(pci_free_consistent);
#define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG))
static void
-sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
+sg_classify(struct device *dev, struct scatterlist *sg, struct scatterlist *end,
+ int virt_ok)
{
unsigned long next_paddr;
struct scatterlist *leader;
long leader_flag, leader_length;
+ unsigned int max_seg_size;
leader = sg;
leader_flag = 0;
leader_length = leader->length;
next_paddr = SG_ENT_PHYS_ADDRESS(leader) + leader_length;
+ /* we will not marge sg without device. */
+ max_seg_size = dev ? dma_get_max_seg_size(dev) : 0;
for (++sg; sg < end; ++sg) {
unsigned long addr, len;
addr = SG_ENT_PHYS_ADDRESS(sg);
len = sg->length;
+ if (leader_length + len > max_seg_size)
+ goto new_segment;
+
if (next_paddr == addr) {
sg->dma_address = -1;
leader_length += len;
@@ -494,6 +502,7 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
leader_flag = 1;
leader_length += len;
} else {
+new_segment:
leader->dma_address = leader_flag;
leader->dma_length = leader_length;
leader = sg;
@@ -512,7 +521,7 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
in the blanks. */
static int
-sg_fill(struct scatterlist *leader, struct scatterlist *end,
+sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
struct scatterlist *out, struct pci_iommu_arena *arena,
dma_addr_t max_dma, int dac_allowed)
{
@@ -562,8 +571,8 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
/* Otherwise, break up the remaining virtually contiguous
hunks into individual direct maps and retry. */
- sg_classify(leader, end, 0);
- return sg_fill(leader, end, out, arena, max_dma, dac_allowed);
+ sg_classify(dev, leader, end, 0);
+ return sg_fill(dev, leader, end, out, arena, max_dma, dac_allowed);
}
out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
@@ -619,12 +628,15 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
struct pci_iommu_arena *arena;
dma_addr_t max_dma;
int dac_allowed;
+ struct device *dev;
if (direction == PCI_DMA_NONE)
BUG();
dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
+ dev = pdev ? &pdev->dev : NULL;
+
/* Fast path single entry scatterlists. */
if (nents == 1) {
sg->dma_length = sg->length;
@@ -638,7 +650,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
end = sg + nents;
/* First, prepare information about the entries. */
- sg_classify(sg, end, alpha_mv.mv_pci_tbi != 0);
+ sg_classify(dev, sg, end, alpha_mv.mv_pci_tbi != 0);
/* Second, figure out where we're going to map things. */
if (alpha_mv.mv_pci_tbi) {
@@ -658,7 +670,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
for (out = sg; sg < end; ++sg) {
if ((int) sg->dma_address < 0)
continue;
- if (sg_fill(sg, end, out, arena, max_dma, dac_allowed) < 0)
+ if (sg_fill(dev, sg, end, out, arena, max_dma, dac_allowed) < 0)
goto error;
out++;
}
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 92b61629fe3..96ed82fd9ee 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -19,7 +19,6 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/utsname.h>
#include <linux/time.h>
#include <linux/major.h>
@@ -318,68 +317,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
}
/*
- * Fill in the user structure for an ECOFF core dump.
- */
-void
-dump_thread(struct pt_regs * pt, struct user * dump)
-{
- /* switch stack follows right below pt_regs: */
- struct switch_stack * sw = ((struct switch_stack *) pt) - 1;
-
- dump->magic = CMAGIC;
- dump->start_code = current->mm->start_code;
- dump->start_data = current->mm->start_data;
- dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
- dump->u_tsize = ((current->mm->end_code - dump->start_code)
- >> PAGE_SHIFT);
- dump->u_dsize = ((current->mm->brk + PAGE_SIZE-1 - dump->start_data)
- >> PAGE_SHIFT);
- dump->u_ssize = (current->mm->start_stack - dump->start_stack
- + PAGE_SIZE-1) >> PAGE_SHIFT;
-
- /*
- * We store the registers in an order/format that is
- * compatible with DEC Unix/OSF/1 as this makes life easier
- * for gdb.
- */
- dump->regs[EF_V0] = pt->r0;
- dump->regs[EF_T0] = pt->r1;
- dump->regs[EF_T1] = pt->r2;
- dump->regs[EF_T2] = pt->r3;
- dump->regs[EF_T3] = pt->r4;
- dump->regs[EF_T4] = pt->r5;
- dump->regs[EF_T5] = pt->r6;
- dump->regs[EF_T6] = pt->r7;
- dump->regs[EF_T7] = pt->r8;
- dump->regs[EF_S0] = sw->r9;
- dump->regs[EF_S1] = sw->r10;
- dump->regs[EF_S2] = sw->r11;
- dump->regs[EF_S3] = sw->r12;
- dump->regs[EF_S4] = sw->r13;
- dump->regs[EF_S5] = sw->r14;
- dump->regs[EF_S6] = sw->r15;
- dump->regs[EF_A3] = pt->r19;
- dump->regs[EF_A4] = pt->r20;
- dump->regs[EF_A5] = pt->r21;
- dump->regs[EF_T8] = pt->r22;
- dump->regs[EF_T9] = pt->r23;
- dump->regs[EF_T10] = pt->r24;
- dump->regs[EF_T11] = pt->r25;
- dump->regs[EF_RA] = pt->r26;
- dump->regs[EF_T12] = pt->r27;
- dump->regs[EF_AT] = pt->r28;
- dump->regs[EF_SP] = rdusp();
- dump->regs[EF_PS] = pt->ps;
- dump->regs[EF_PC] = pt->pc;
- dump->regs[EF_GP] = pt->gp;
- dump->regs[EF_A0] = pt->r16;
- dump->regs[EF_A1] = pt->r17;
- dump->regs[EF_A2] = pt->r18;
- memcpy((char *)dump->regs + EF_SIZE, sw->fp, 32 * 8);
-}
-EXPORT_SYMBOL(dump_thread);
-
-/*
* Fill in the user structure for a ELF core dump.
*/
void
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index bd5e68cd61e..a449e999027 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -18,7 +18,6 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/screen_info.h>
#include <linux/delay.h>
#include <linux/mc146818rtc.h>
@@ -58,7 +57,6 @@ static struct notifier_block alpha_panic_block = {
#include <asm/system.h>
#include <asm/hwrpb.h>
#include <asm/dma.h>
-#include <asm/io.h>
#include <asm/mmu_context.h>
#include <asm/console.h>
@@ -429,7 +427,8 @@ setup_memory(void *kernel_end)
}
/* Reserve the bootmap memory. */
- reserve_bootmem(PFN_PHYS(bootmap_start), bootmap_size);
+ reserve_bootmem(PFN_PHYS(bootmap_start), bootmap_size,
+ BOOTMEM_DEFAULT);
printk("reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size));
#ifdef CONFIG_BLK_DEV_INITRD
@@ -447,7 +446,7 @@ setup_memory(void *kernel_end)
phys_to_virt(PFN_PHYS(max_low_pfn)));
} else {
reserve_bootmem(virt_to_phys((void *)initrd_start),
- INITRD_SIZE);
+ INITRD_SIZE, BOOTMEM_DEFAULT);
}
}
#endif /* CONFIG_BLK_DEV_INITRD */
@@ -1472,7 +1471,7 @@ c_stop(struct seq_file *f, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index f4ab233201b..63c2073401e 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -77,10 +77,6 @@ int smp_num_probed; /* Internal processor count */
int smp_num_cpus = 1; /* Number that came online. */
EXPORT_SYMBOL(smp_num_cpus);
-extern void calibrate_delay(void);
-
-
-
/*
* Called by both boot and secondaries to move global data into
* per-processor storage.
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index 79de99e32c3..ba914af18c4 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -495,7 +495,7 @@ sys_call_table:
.quad sys_epoll_pwait
.quad sys_utimensat /* 475 */
.quad sys_signalfd
- .quad sys_timerfd
+ .quad sys_ni_syscall
.quad sys_eventfd
.size sys_call_table, . - sys_call_table
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 1dd50d07693..75480cab089 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -119,13 +119,8 @@ irqreturn_t timer_interrupt(int irq, void *dev)
state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1);
nticks = delta >> FIX_SHIFT;
- while (nticks > 0) {
- do_timer(1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
- nticks--;
- }
+ if (nticks)
+ do_timer(nticks);
/*
* If we have an externally synchronized Linux clock, then update
@@ -141,6 +136,12 @@ irqreturn_t timer_interrupt(int irq, void *dev)
}
write_sequnlock(&xtime_lock);
+
+#ifndef CONFIG_SMP
+ while (nticks--)
+ update_process_times(user_mode(get_irq_regs()));
+#endif
+
return IRQ_HANDLED;
}
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index e3e3806a6f2..10ab7833e83 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -242,7 +242,8 @@ setup_memory_node(int nid, void *kernel_end)
}
/* Reserve the bootmap memory. */
- reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(bootmap_start), bootmap_size);
+ reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(bootmap_start),
+ bootmap_size, BOOTMEM_DEFAULT);
printk(" reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size));
node_set_online(nid);
@@ -281,7 +282,7 @@ setup_memory(void *kernel_end)
nid = kvaddr_to_nid(initrd_start);
reserve_bootmem_node(NODE_DATA(nid),
virt_to_phys((void *)initrd_start),
- INITRD_SIZE);
+ INITRD_SIZE, BOOTMEM_DEFAULT);
}
}
#endif /* CONFIG_BLK_DEV_INITRD */
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 64d19eff3fa..9619c43783f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -126,6 +126,9 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
config ARCH_MAY_HAVE_PC_FDC
bool
@@ -219,6 +222,7 @@ config ARCH_CLPS7500
select TIMER_ACORN
select ISA
select NO_IOPORT
+ select HAVE_IDE
help
Support for the Cirrus Logic PS7500FE system-on-a-chip.
@@ -231,6 +235,7 @@ config ARCH_CO285
bool "Co-EBSA285"
select FOOTBRIDGE
select FOOTBRIDGE_ADDIN
+ select HAVE_IDE
help
Support for Intel's EBSA285 companion chip.
@@ -255,6 +260,7 @@ config ARCH_EP93XX
config ARCH_FOOTBRIDGE
bool "FootBridge"
select FOOTBRIDGE
+ select HAVE_IDE
help
Support for systems based on the DC21285 companion chip
("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
@@ -293,6 +299,7 @@ config ARCH_IOP32X
depends on MMU
select PLAT_IOP
select PCI
+ select HAVE_IDE
help
Support for Intel's 80219 and IOP32X (XScale) family of
processors.
@@ -302,12 +309,14 @@ config ARCH_IOP33X
depends on MMU
select PLAT_IOP
select PCI
+ select HAVE_IDE
help
Support for Intel's IOP33X (XScale) family of processors.
config ARCH_IXP23XX
bool "IXP23XX-based"
depends on MMU
+ select HAVE_IDE
select PCI
help
Support for Intel's IXP23xx (XScale) family of processors.
@@ -325,12 +334,14 @@ config ARCH_IXP4XX
select GENERIC_GPIO
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
+ select HAVE_IDE
help
Support for Intel's IXP4XX (XScale) family of processors.
config ARCH_L7200
bool "LinkUp-L7200"
select FIQ
+ select HAVE_IDE
help
Say Y here if you intend to run this kernel on a LinkUp Systems
L7200 Software Development Board which uses an ARM720T processor.
@@ -385,6 +396,8 @@ config ARCH_PXA
depends on MMU
select ARCH_MTD_XIP
select GENERIC_GPIO
+ select HAVE_IDE
+ select HAVE_GPIO_LIB
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
select TICK_ONESHOT
@@ -399,6 +412,7 @@ config ARCH_RPC
select ARCH_MAY_HAVE_PC_FDC
select ISA_DMA_API
select NO_IOPORT
+ select HAVE_IDE
help
On the Acorn Risc-PC, Linux can support the internal IDE disk and
CD-ROM interface, serial and parallel port, and the floppy drive.
@@ -410,12 +424,14 @@ config ARCH_SA1100
select ARCH_MTD_XIP
select GENERIC_GPIO
select GENERIC_TIME
+ select HAVE_IDE
help
Support for StrongARM 11x0 based boards.
config ARCH_S3C2410
bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
select GENERIC_GPIO
+ select HAVE_IDE
help
Samsung S3C2410X CPU based systems, such as the Simtec Electronics
BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -423,6 +439,7 @@ config ARCH_S3C2410
config ARCH_SHARK
bool "Shark"
+ select HAVE_IDE
select ISA
select ISA_DMA
select PCI
@@ -432,6 +449,7 @@ config ARCH_SHARK
config ARCH_LH7A40X
bool "Sharp LH7A40X"
+ select HAVE_IDE
help
Say Y here for systems based on one of the Sharp LH7A40X
System on a Chip processors. These CPUs include an ARM922T
@@ -1089,12 +1107,7 @@ source "drivers/block/Kconfig"
source "drivers/misc/Kconfig"
-if PCMCIA || ARCH_CLPS7500 || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX \
- || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
- || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
- || ARCH_IXP23XX
source "drivers/ide/Kconfig"
-endif
source "drivers/scsi/Kconfig"
@@ -1122,6 +1135,8 @@ source "drivers/i2c/Kconfig"
source "drivers/spi/Kconfig"
+source "drivers/gpio/Kconfig"
+
source "drivers/w1/Kconfig"
source "drivers/power/Kconfig"
diff --git a/arch/arm/configs/omap_h2_1610_defconfig b/arch/arm/configs/omap_h2_1610_defconfig
index b8a78ab49cd..c2345af3707 100644
--- a/arch/arm/configs/omap_h2_1610_defconfig
+++ b/arch/arm/configs/omap_h2_1610_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc6
-# Mon Sep 17 14:21:45 2007
+# Linux kernel version: 2.6.24-rc5
+# Mon Dec 17 20:04:38 2007
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -41,9 +41,14 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -64,7 +69,6 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
@@ -224,10 +228,6 @@ CONFIG_ARM_THUMB=y
#
# CONFIG_PCI_SYSCALL is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
#
@@ -236,6 +236,7 @@ CONFIG_ARM_THUMB=y
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_PREEMPT=y
CONFIG_HZ=128
CONFIG_AEABI=y
@@ -248,6 +249,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
@@ -275,6 +277,8 @@ CONFIG_CPU_FREQ_STAT=y
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
# CONFIG_CPU_FREQ_GOV_PERFORMANCE is not set
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -347,6 +351,7 @@ CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -372,10 +377,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
#
@@ -404,6 +405,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
@@ -422,6 +424,8 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
CONFIG_ATA_OVER_ETH=m
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
#
# SCSI device support
@@ -459,6 +463,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
@@ -471,12 +476,18 @@ CONFIG_NETDEVICES=y
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
+# CONFIG_VETH is not set
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
CONFIG_SMC91X=y
# CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
@@ -522,7 +533,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=y
@@ -576,20 +586,51 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_OMAP_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
-# CONFIG_I2C is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TPS65010=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
#
# SPI support
@@ -597,28 +638,73 @@ CONFIG_WATCHDOG_NOWAYOUT=y
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_OMAP_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
# Multifunction device drivers
#
# CONFIG_MFD_SM501 is not set
-# CONFIG_NEW_LEDS is not set
#
# Multimedia devices
@@ -630,12 +716,6 @@ CONFIG_DAB=y
#
# Graphics support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
# CONFIG_VGASTATE is not set
CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
@@ -644,6 +724,7 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_CFB_FILLRECT is not set
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -659,8 +740,14 @@ CONFIG_FB_MODE_HELPERS=y
# Frame buffer hardware drivers
#
# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_OMAP is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_OMAP is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
#
# Console display driver support
@@ -705,6 +792,7 @@ CONFIG_SOUND_PRIME=y
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -720,23 +808,11 @@ CONFIG_USB_ARCH_HAS_OHCI=y
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
CONFIG_RTC_LIB=y
# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -771,8 +847,9 @@ CONFIG_DNOTIFY=y
#
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
@@ -783,7 +860,6 @@ CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -802,10 +878,7 @@ CONFIG_CRAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -832,13 +905,9 @@ CONFIG_RPCSEC_GSS_KRB5=y
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
# CONFIG_NLS_CODEPAGE_850 is not set
@@ -862,7 +931,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
@@ -876,21 +945,16 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
-
-#
-# Profiling support
-#
+CONFIG_INSTRUMENTATION=y
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
@@ -899,6 +963,7 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
+# CONFIG_SAMPLES is not set
# CONFIG_DEBUG_USER is not set
#
@@ -906,6 +971,7 @@ CONFIG_FRAME_POINTER=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
@@ -925,6 +991,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
@@ -938,11 +1005,13 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
CONFIG_CRYPTO_HW=y
#
diff --git a/arch/arm/configs/omap_osk_5912_defconfig b/arch/arm/configs/omap_osk_5912_defconfig
index 8c1f15c7c45..d592a648711 100644
--- a/arch/arm/configs/omap_osk_5912_defconfig
+++ b/arch/arm/configs/omap_osk_5912_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc6
-# Mon Sep 17 14:15:05 2007
+# Linux kernel version: 2.6.24-rc5
+# Mon Dec 17 21:12:45 2007
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -40,9 +40,14 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -63,7 +68,6 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
@@ -224,10 +228,6 @@ CONFIG_CPU_CP15_MMU=y
#
# CONFIG_PCI_SYSCALL is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
CONFIG_PCCARD=y
# CONFIG_PCMCIA_DEBUG is not set
CONFIG_PCMCIA=y
@@ -245,6 +245,7 @@ CONFIG_OMAP_CF=y
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_PREEMPT is not set
CONFIG_HZ=128
CONFIG_AEABI=y
@@ -257,6 +258,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
@@ -346,6 +348,7 @@ CONFIG_IP_PNP_BOOTP=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -371,10 +374,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
#
@@ -403,6 +402,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
@@ -427,6 +427,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
#
# RAM/ROM/Flash chip drivers
@@ -495,6 +496,8 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_IDE=m
CONFIG_BLK_DEV_IDE=m
@@ -515,9 +518,10 @@ CONFIG_IDE_PROC_FS=y
# IDE chipset support/bugfixes
#
# CONFIG_IDE_GENERIC is not set
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_BLK_DEV_PLATFORM is not set
# CONFIG_IDE_ARM is not set
# CONFIG_BLK_DEV_IDEDMA is not set
+CONFIG_IDE_ARCH_OBSOLETE_INIT=y
# CONFIG_BLK_DEV_HD is not set
#
@@ -536,12 +540,18 @@ CONFIG_NETDEVICES=y
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
+# CONFIG_VETH is not set
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
CONFIG_SMC91X=y
# CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
@@ -585,7 +595,6 @@ CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
@@ -651,7 +660,6 @@ CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=m
CONFIG_HW_RANDOM_OMAP=m
# CONFIG_NVRAM is not set
@@ -712,10 +720,9 @@ CONFIG_TPS65010=y
# CONFIG_SPI is not set
# CONFIG_SPI_MASTER is not set
# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
@@ -723,12 +730,12 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -761,14 +768,18 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
# Multifunction device drivers
#
# CONFIG_MFD_SM501 is not set
-# CONFIG_NEW_LEDS is not set
#
# Multimedia devices
@@ -780,12 +791,6 @@ CONFIG_DAB=y
#
# Graphics support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
# CONFIG_VGASTATE is not set
CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
@@ -794,6 +799,7 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_CFB_FILLRECT is not set
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -809,8 +815,14 @@ CONFIG_FB_MODE_HELPERS=y
# Frame buffer hardware drivers
#
# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_OMAP is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_OMAP is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
#
# Console display driver support
@@ -843,6 +855,7 @@ CONFIG_LOGO_LINUX_CLUT224=y
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -858,23 +871,11 @@ CONFIG_USB_ARCH_HAS_OHCI=y
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
CONFIG_RTC_LIB=y
# CONFIG_RTC_CLASS is not set
#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -922,7 +923,6 @@ CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -938,10 +938,12 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
# CONFIG_JFFS2_SUMMARY is not set
# CONFIG_JFFS2_FS_XATTR is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
@@ -950,10 +952,7 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
@@ -979,10 +978,6 @@ CONFIG_SUNRPC=y
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
CONFIG_NLS=m
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
@@ -1023,21 +1018,16 @@ CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
-
-#
-# Profiling support
-#
+CONFIG_INSTRUMENTATION=y
# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
@@ -1046,6 +1036,7 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_KERNEL is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
+# CONFIG_SAMPLES is not set
# CONFIG_DEBUG_USER is not set
#
@@ -1053,6 +1044,7 @@ CONFIG_FRAME_POINTER=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
#
diff --git a/arch/arm/configs/orion_defconfig b/arch/arm/configs/orion_defconfig
index 17a55def110..1e5aaa645fc 100644
--- a/arch/arm/configs/orion_defconfig
+++ b/arch/arm/configs/orion_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24-rc3
-# Wed Nov 28 15:13:57 2007
+# Linux kernel version: 2.6.24
+# Thu Feb 7 14:10:30 2008
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -63,17 +63,26 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -101,6 +110,8 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_RCU is not set
#
# System Type
@@ -139,6 +150,7 @@ CONFIG_ARCH_ORION=y
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_DAVINCI is not set
# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM7X00A is not set
#
# Orion Implementations
@@ -226,6 +238,7 @@ CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE=""
# CONFIG_XIP_KERNEL is not set
# CONFIG_KEXEC is not set
+# CONFIG_ATAGS_PROC is not set
#
# Floating point emulation
@@ -250,7 +263,7 @@ CONFIG_BINFMT_ELF=y
# Power management options
#
# CONFIG_PM is not set
-CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
#
# Networking
@@ -267,6 +280,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -322,6 +336,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
CONFIG_NET_PKTGEN=m
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
@@ -475,7 +490,7 @@ CONFIG_SCSI=y
CONFIG_SCSI_DMA=y
# CONFIG_SCSI_TGT is not set
# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
+# CONFIG_SCSI_PROC_FS is not set
#
# SCSI support type (disk, tape, CD-ROM)
@@ -483,15 +498,15 @@ CONFIG_SCSI_PROC_FS=y
CONFIG_BLK_DEV_SD=y
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR=m
# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SG=m
# CONFIG_CHR_DEV_SCH is not set
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
-CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
@@ -528,16 +543,6 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_STEX is not set
-CONFIG_SCSI_MVSATA=y
-
-#
-# Sata options
-#
-# CONFIG_MV_SATA_SUPPORT_ATAPI is not set
-# CONFIG_MV_SATA_ENABLE_1MB_IOS is not set
-CONFIG_SATA_NO_DEBUG=y
-# CONFIG_SATA_DEBUG_ON_ERROR is not set
-# CONFIG_SATA_FULL_DEBUG is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
@@ -549,12 +554,12 @@ CONFIG_SATA_NO_DEBUG=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-CONFIG_ATA=m
+CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
-# CONFIG_SATA_MV is not set
+CONFIG_SATA_MV=y
# CONFIG_SATA_NV is not set
# CONFIG_PDC_ADMA is not set
# CONFIG_SATA_QSTOR is not set
@@ -590,6 +595,7 @@ CONFIG_ATA=m
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
# CONFIG_PATA_NS87410 is not set
# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OPTI is not set
@@ -622,7 +628,6 @@ CONFIG_NETDEVICES=y
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
-# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
@@ -653,6 +658,7 @@ CONFIG_E100=y
# CONFIG_NE2K_PCI is not set
# CONFIG_8139CP is not set
# CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
@@ -666,6 +672,9 @@ CONFIG_E1000=y
CONFIG_E1000_NAPI=y
# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_E1000E is not set
+# CONFIG_E1000E_ENABLED is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -691,6 +700,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_NIU is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
# CONFIG_TR is not set
#
@@ -713,7 +723,6 @@ CONFIG_NETDEV_10000=y
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -761,6 +770,7 @@ CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
#
# Serial drivers
@@ -832,13 +842,12 @@ CONFIG_I2C_MV64XXX=y
#
# Miscellaneous I2C Chip support
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -967,6 +976,7 @@ CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
#
# Miscellaneous USB options
@@ -980,16 +990,12 @@ CONFIG_USB_DEVICE_CLASS=y
# USB Host Controller Drivers
#
CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_SPLIT_ISO=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
# CONFIG_USB_ISP116X_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
-# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-CONFIG_USB_UHCI_HCD=y
-CONFIG_USB_SL811_HCD=y
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
#
@@ -1029,10 +1035,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
#
# USB port drivers
#
-
-#
-# USB Serial Converter support
-#
# CONFIG_USB_SERIAL is not set
#
@@ -1058,14 +1060,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
CONFIG_NEW_LEDS=y
@@ -1120,9 +1114,10 @@ CONFIG_RTC_DRV_M41T80=y
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_M48T59 is not set
# CONFIG_RTC_DRV_V3020 is not set
@@ -1298,9 +1293,6 @@ CONFIG_NLS_ISO8859_2=y
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
#
# Kernel hacking
@@ -1327,6 +1319,7 @@ CONFIG_DEBUG_USER=y
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=m
CONFIG_CRYPTO_BLKCIPHER=m
+# CONFIG_CRYPTO_SEQIV is not set
CONFIG_CRYPTO_MANAGER=m
# CONFIG_CRYPTO_HMAC is not set
# CONFIG_CRYPTO_XCBC is not set
@@ -1344,6 +1337,9 @@ CONFIG_CRYPTO_CBC=m
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CCM is not set
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_DES is not set
# CONFIG_CRYPTO_FCRYPT is not set
@@ -1358,13 +1354,16 @@ CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SALSA20 is not set
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
#
# Library routines
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index cecf658e362..283e14fff99 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -359,7 +359,7 @@
CALL(sys_kexec_load)
CALL(sys_utimensat)
CALL(sys_signalfd)
-/* 350 */ CALL(sys_timerfd)
+/* 350 */ CALL(sys_ni_syscall)
CALL(sys_eventfd)
CALL(sys_fallocate)
#ifndef syscalls_counted
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 4f1a03124a7..46bf2ede612 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -18,7 +18,6 @@
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/delay.h>
#include <linux/reboot.h>
#include <linux/interrupt.h>
@@ -368,35 +367,6 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
EXPORT_SYMBOL(dump_fpu);
/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
- struct task_struct *tsk = current;
-
- dump->magic = CMAGIC;
- dump->start_code = tsk->mm->start_code;
- dump->start_stack = regs->ARM_sp & ~(PAGE_SIZE - 1);
-
- dump->u_tsize = (tsk->mm->end_code - tsk->mm->start_code) >> PAGE_SHIFT;
- dump->u_dsize = (tsk->mm->brk - tsk->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT;
- dump->u_ssize = 0;
-
- dump->u_debugreg[0] = tsk->thread.debug.bp[0].address;
- dump->u_debugreg[1] = tsk->thread.debug.bp[1].address;
- dump->u_debugreg[2] = tsk->thread.debug.bp[0].insn.arm;
- dump->u_debugreg[3] = tsk->thread.debug.bp[1].insn.arm;
- dump->u_debugreg[4] = tsk->thread.debug.nsaved;
-
- if (dump->start_stack < 0x04000000)
- dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT;
-
- dump->regs = *regs;
- dump->u_fpvalid = dump_fpu (regs, &dump->u_fp);
-}
-EXPORT_SYMBOL(dump_thread);
-
-/*
* Shuffle the argument into the correct register before calling the
* thread function. r1 is the thread argument, r2 is the pointer to
* the thread function, and r3 points to the exit function.
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index d3941a7b045..b7b0720bc1b 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -1001,7 +1001,7 @@ static void c_stop(struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index e9dfbab46cb..eefae1de334 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -150,7 +150,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
secondary_data.pgdir = 0;
*pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
- pgd_free(pgd);
+ pgd_free(&init_mm, pgd);
if (ret) {
printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index aa29ea58ca0..0ce38dfa6eb 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -383,6 +383,7 @@ static void at91_lcdc_tft_power_control(int on)
}
static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+ .lcdcon_is_backlight = true,
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN,
.default_lcdcon2 = AT91SAM9261_DEFAULT_TFT_LCDCON2,
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index f09347a86e7..38313abef65 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -253,6 +253,7 @@ static void at91_lcdc_power_control(int on)
/* Driver datas */
static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+ .lcdcon_is_backlight = true,
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN,
.default_lcdcon2 = AT91SAM9263_DEFAULT_LCDCON2,
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index ec76eeaafd4..de6424e9ac0 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -343,7 +343,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
EXPORT_SYMBOL(clk_set_parent);
/* establish PCK0..PCK3 parentage and rate */
-static void init_programmable_clock(struct clk *clk)
+static void __init init_programmable_clock(struct clk *clk)
{
struct clk *parent;
u32 pckr;
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index 139ceaa35e2..4143828a968 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -290,7 +290,7 @@ static int davinci_ck_show(struct seq_file *m, void *v)
return 0;
}
-static struct seq_operations davinci_ck_op = {
+static const struct seq_operations davinci_ck_op = {
.start = davinci_ck_start,
.next = davinci_ck_next,
.stop = davinci_ck_stop,
@@ -302,7 +302,7 @@ static int davinci_ck_open(struct inode *inode, struct file *file)
return seq_open(file, &davinci_ck_op);
}
-static struct file_operations proc_davinci_ck_operations = {
+static const struct file_operations proc_davinci_ck_operations = {
.open = davinci_ck_open,
.read = seq_read,
.llseek = seq_lseek,
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 688659668bd..8cb07437a80 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -71,11 +71,11 @@ static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
static struct gpio_led dsmg600_led_pins[] = {
{
- .name = "power",
+ .name = "dsmg600:green:power",
.gpio = DSMG600_LED_PWR_GPIO,
},
{
- .name = "wlan",
+ .name = "dsmg600:green:wlan",
.gpio = DSMG600_LED_WLAN_GPIO,
.active_low = true,
},
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 4cecae84837..159e1c4f1ed 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -60,17 +60,17 @@ static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
static struct gpio_led nas100d_led_pins[] = {
{
- .name = "wlan", /* green led */
+ .name = "nas100d:green:wlan",
.gpio = NAS100D_LED_WLAN_GPIO,
.active_low = true,
},
{
- .name = "power", /* blue power led (off=flashing) */
+ .name = "nas100d:blue:power", /* (off=flashing) */
.gpio = NAS100D_LED_PWR_GPIO,
.active_low = true,
},
{
- .name = "disk", /* yellow led */
+ .name = "nas100d:yellow:disk",
.gpio = NAS100D_LED_DISK_GPIO,
.active_low = true,
},
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index acaebcbce53..d9a182895a0 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -63,20 +63,20 @@ static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
static struct gpio_led nslu2_led_pins[] = {
{
- .name = "ready", /* green led */
+ .name = "nslu2:green:ready",
.gpio = NSLU2_LED_GRN_GPIO,
},
{
- .name = "status", /* red led */
+ .name = "nslu2:red:status",
.gpio = NSLU2_LED_RED_GPIO,
},
{
- .name = "disk-1",
+ .name = "nslu2:green:disk-1",
.gpio = NSLU2_LED_DISK1_GPIO,
.active_low = true,
},
{
- .name = "disk-2",
+ .name = "nslu2:green:disk-2",
.gpio = NSLU2_LED_DISK2_GPIO,
.active_low = true,
},
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 391b6f4827f..015a66b3ca8 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -13,20 +13,20 @@ obj-$(CONFIG_PM) += pm.o sleep.o
led-y := leds.o
# Specific board support
-obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o
+obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o board-h2-mmc.o
obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o
obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
obj-$(CONFIG_MACH_OMAP_FSAMPLE) += board-fsample.o
obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
-obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
+obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o board-h3-mmc.o
obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o
obj-$(CONFIG_MACH_OMAP_PALMZ71) += board-palmz71.o
obj-$(CONFIG_MACH_OMAP_PALMTT) += board-palmtt.o
obj-$(CONFIG_MACH_NOKIA770) += board-nokia770.o
obj-$(CONFIG_MACH_AMS_DELTA) += board-ams-delta.o
-obj-$(CONFIG_MACH_SX1) += board-sx1.o
+obj-$(CONFIG_MACH_SX1) += board-sx1.o board-sx1-mmc.o
ifeq ($(CONFIG_ARCH_OMAP15XX),y)
# Innovator-1510 FPGA
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index c73ca61e585..8b102ad59c1 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -135,21 +135,21 @@ static void __init ams_delta_init_irq(void)
}
static struct map_desc ams_delta_io_desc[] __initdata = {
- // AMS_DELTA_LATCH1
+ /* AMS_DELTA_LATCH1 */
{
.virtual = AMS_DELTA_LATCH1_VIRT,
.pfn = __phys_to_pfn(AMS_DELTA_LATCH1_PHYS),
.length = 0x01000000,
.type = MT_DEVICE
},
- // AMS_DELTA_LATCH2
+ /* AMS_DELTA_LATCH2 */
{
.virtual = AMS_DELTA_LATCH2_VIRT,
.pfn = __phys_to_pfn(AMS_DELTA_LATCH2_PHYS),
.length = 0x01000000,
.type = MT_DEVICE
},
- // AMS_DELTA_MODEM
+ /* AMS_DELTA_MODEM */
{
.virtual = AMS_DELTA_MODEM_VIRT,
.pfn = __phys_to_pfn(AMS_DELTA_MODEM_PHYS),
@@ -227,6 +227,7 @@ static void __init ams_delta_init(void)
omap_board_config = ams_delta_config;
omap_board_config_size = ARRAY_SIZE(ams_delta_config);
omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
/* Clear latch2 (NAND, LCD, modem enable) */
ams_delta_latch2_write(~0, 0);
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index f550b19e1ec..1bdb66638e2 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -30,6 +30,7 @@
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/fpga.h>
+#include <asm/arch/nand.h>
#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
#include <asm/arch/board.h>
@@ -134,7 +135,7 @@ static struct platform_device nor_device = {
.resource = &nor_resource,
};
-static struct nand_platform_data nand_data = {
+static struct omap_nand_platform_data nand_data = {
.options = NAND_SAMSUNG_LP_OPTIONS,
};
@@ -202,7 +203,7 @@ static struct platform_device *devices[] __initdata = {
#define P2_NAND_RB_GPIO_PIN 62
-static int nand_dev_ready(struct nand_platform_data *data)
+static int nand_dev_ready(struct omap_nand_platform_data *data)
{
return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN);
}
@@ -233,6 +234,7 @@ static void __init omap_fsample_init(void)
omap_board_config = fsample_config;
omap_board_config_size = ARRAY_SIZE(fsample_config);
omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
}
static void __init fsample_init_smc91x(void)
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 33d01adab1e..c711bf23f7b 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -55,33 +55,14 @@ static struct omap_usb_config generic1610_usb_config __initdata = {
.hmc_mode = 16,
.pins[0] = 6,
};
-
-static struct omap_mmc_config generic_mmc_config __initdata = {
- .mmc [0] = {
- .enabled = 0,
- .wire4 = 0,
- .wp_pin = -1,
- .power_pin = -1,
- .switch_pin = -1,
- },
- .mmc [1] = {
- .enabled = 0,
- .wire4 = 0,
- .wp_pin = -1,
- .power_pin = -1,
- .switch_pin = -1,
- },
-};
-
#endif
static struct omap_uart_config generic_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
};
-static struct omap_board_config_kernel generic_config[] = {
- { OMAP_TAG_USB, NULL },
- { OMAP_TAG_MMC, &generic_mmc_config },
+static struct omap_board_config_kernel generic_config[] __initdata = {
+ { OMAP_TAG_USB, NULL },
{ OMAP_TAG_UART, &generic_uart_config },
};
@@ -101,6 +82,7 @@ static void __init omap_generic_init(void)
omap_board_config = generic_config;
omap_board_config_size = ARRAY_SIZE(generic_config);
omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
}
static void __init omap_generic_map_io(void)
diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c
new file mode 100644
index 00000000000..6fdc78406b2
--- /dev/null
+++ b/arch/arm/mach-omap1/board-h2-mmc.c
@@ -0,0 +1,110 @@
+/*
+ * linux/arch/arm/mach-omap1/board-h2-mmc.c
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Author: Felipe Balbi <felipe.lima@indt.org.br>
+ *
+ * This code is based on linux/arch/arm/mach-omap2/board-n800-mmc.c, which is:
+ * Copyright (C) 2006 Nokia Corporation
+ *
+ * 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 <asm/arch/mmc.h>
+#include <asm/arch/gpio.h>
+
+#ifdef CONFIG_MMC_OMAP
+static int slot_cover_open;
+static struct device *mmc_device;
+
+static int h2_mmc_set_power(struct device *dev, int slot, int power_on,
+ int vdd)
+{
+#ifdef CONFIG_MMC_DEBUG
+ dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
+ power_on ? "on" : "off", vdd);
+#endif
+ if (slot != 0) {
+ dev_err(dev, "No such slot %d\n", slot + 1);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int h2_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
+{
+#ifdef CONFIG_MMC_DEBUG
+ dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1,
+ bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
+#endif
+ if (slot != 0) {
+ dev_err(dev, "No such slot %d\n", slot + 1);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int h2_mmc_get_cover_state(struct device *dev, int slot)
+{
+ BUG_ON(slot != 0);
+
+ return slot_cover_open;
+}
+
+void h2_mmc_slot_cover_handler(void *arg, int state)
+{
+ if (mmc_device == NULL)
+ return;
+
+ slot_cover_open = state;
+ omap_mmc_notify_cover_event(mmc_device, 0, state);
+}
+
+static int h2_mmc_late_init(struct device *dev)
+{
+ int ret = 0;
+
+ mmc_device = dev;
+
+ return ret;
+}
+
+static void h2_mmc_cleanup(struct device *dev)
+{
+}
+
+static struct omap_mmc_platform_data h2_mmc_data = {
+ .nr_slots = 1,
+ .switch_slot = NULL,
+ .init = h2_mmc_late_init,
+ .cleanup = h2_mmc_cleanup,
+ .slots[0] = {
+ .set_power = h2_mmc_set_power,
+ .set_bus_mode = h2_mmc_set_bus_mode,
+ .get_ro = NULL,
+ .get_cover_state = h2_mmc_get_cover_state,
+ .ocr_mask = MMC_VDD_28_29 | MMC_VDD_30_31 |
+ MMC_VDD_32_33 | MMC_VDD_33_34,
+ .name = "mmcblk",
+ },
+};
+
+void __init h2_mmc_init(void)
+{
+ omap_set_mmc_info(1, &h2_mmc_data);
+}
+
+#else
+
+void __init h2_mmc_init(void)
+{
+}
+
+void h2_mmc_slot_cover_handler(void *arg, int state)
+{
+}
+#endif
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index bfa04fa2552..070345ee39a 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -37,8 +37,10 @@
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
+#include <asm/arch/gpio-switch.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/nand.h>
#include <asm/arch/irda.h>
#include <asm/arch/usb.h>
#include <asm/arch/keypad.h>
@@ -46,8 +48,6 @@
#include <asm/arch/mcbsp.h>
#include <asm/arch/omap-alsa.h>
-extern int omap_gpio_init(void);
-
static int h2_keymap[] = {
KEY(0, 0, KEY_LEFT),
KEY(0, 1, KEY_RIGHT),
@@ -140,8 +140,6 @@ static struct platform_device h2_nor_device = {
.resource = &h2_nor_resource,
};
-#if 0 /* REVISIT: Enable when nand_platform_data is applied */
-
static struct mtd_partition h2_nand_partitions[] = {
#if 0
/* REVISIT: enable these partitions if you make NAND BOOT
@@ -179,7 +177,7 @@ static struct mtd_partition h2_nand_partitions[] = {
};
/* dip switches control NAND chip access: 8 bit, 16 bit, or neither */
-static struct nand_platform_data h2_nand_data = {
+static struct omap_nand_platform_data h2_nand_data = {
.options = NAND_SAMSUNG_LP_OPTIONS,
.parts = h2_nand_partitions,
.nr_parts = ARRAY_SIZE(h2_nand_partitions),
@@ -198,7 +196,6 @@ static struct platform_device h2_nand_device = {
.num_resources = 1,
.resource = &h2_nand_resource,
};
-#endif
static struct resource h2_smc91x_resources[] = {
[0] = {
@@ -311,18 +308,18 @@ static struct omap_mcbsp_reg_cfg mcbsp_regs = {
.srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
.pcr0 = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
- //.pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
+ /*.pcr0 = CLKXP | CLKRP,*/ /* mcbsp: slave */
};
static struct omap_alsa_codec_config alsa_config = {
.name = "H2 TSC2101",
.mcbsp_regs_alsa = &mcbsp_regs,
- .codec_configure_dev = NULL, // tsc2101_configure,
- .codec_set_samplerate = NULL, // tsc2101_set_samplerate,
- .codec_clock_setup = NULL, // tsc2101_clock_setup,
- .codec_clock_on = NULL, // tsc2101_clock_on,
- .codec_clock_off = NULL, // tsc2101_clock_off,
- .get_default_samplerate = NULL, // tsc2101_get_default_samplerate,
+ .codec_configure_dev = NULL, /* tsc2101_configure, */
+ .codec_set_samplerate = NULL, /* tsc2101_set_samplerate, */
+ .codec_clock_setup = NULL, /* tsc2101_clock_setup, */
+ .codec_clock_on = NULL, /* tsc2101_clock_on, */
+ .codec_clock_off = NULL, /* tsc2101_clock_off, */
+ .get_default_samplerate = NULL, /* tsc2101_get_default_samplerate, */
};
static struct platform_device h2_mcbsp1_device = {
@@ -335,7 +332,7 @@ static struct platform_device h2_mcbsp1_device = {
static struct platform_device *h2_devices[] __initdata = {
&h2_nor_device,
- //&h2_nand_device,
+ &h2_nand_device,
&h2_smc91x_device,
&h2_irda_device,
&h2_kp_device,
@@ -343,22 +340,6 @@ static struct platform_device *h2_devices[] __initdata = {
&h2_mcbsp1_device,
};
-#ifdef CONFIG_I2C_BOARDINFO
-static struct i2c_board_info __initdata h2_i2c_board_info[] = {
- {
- I2C_BOARD_INFO("tps65010", 0x48),
- .type = "tps65010",
- .irq = OMAP_GPIO_IRQ(58),
- },
- /* TODO when driver support is ready:
- * - isp1301 OTG transceiver
- * - optional ov9640 camera sensor at 0x30
- * - pcf9754 for aGPS control
- * - ... etc
- */
-};
-#endif
-
static void __init h2_init_smc91x(void)
{
if ((omap_request_gpio(0)) < 0) {
@@ -367,6 +348,14 @@ static void __init h2_init_smc91x(void)
}
}
+static struct i2c_board_info __initdata h2_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO("isp1301_omap", 0x2d),
+ .type = "isp1301_omap",
+ .irq = OMAP_GPIO_IRQ(2),
+ },
+};
+
static void __init h2_init_irq(void)
{
omap1_init_common_hw();
@@ -380,26 +369,25 @@ static struct omap_usb_config h2_usb_config __initdata = {
.otg = 2,
#ifdef CONFIG_USB_GADGET_OMAP
- .hmc_mode = 19, // 0:host(off) 1:dev|otg 2:disabled
- // .hmc_mode = 21, // 0:host(off) 1:dev(loopback) 2:host(loopback)
+ .hmc_mode = 19, /* 0:host(off) 1:dev|otg 2:disabled */
+ /* .hmc_mode = 21,*/ /* 0:host(off) 1:dev(loopback) 2:host(loopback) */
#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
/* needs OTG cable, or NONSTANDARD (B-to-MiniB) */
- .hmc_mode = 20, // 1:dev|otg(off) 1:host 2:disabled
+ .hmc_mode = 20, /* 1:dev|otg(off) 1:host 2:disabled */
#endif
.pins[1] = 3,
};
static struct omap_mmc_config h2_mmc_config __initdata = {
- .mmc [0] = {
- .enabled = 1,
+ .mmc[0] = {
+ .enabled = 1,
.wire4 = 1,
- .wp_pin = OMAP_MPUIO(3),
- .power_pin = -1, /* tps65010 gpio3 */
- .switch_pin = OMAP_MPUIO(1),
},
};
+extern struct omap_mmc_platform_data h2_mmc_data;
+
static struct omap_uart_config h2_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
};
@@ -409,15 +397,15 @@ static struct omap_lcd_config h2_lcd_config __initdata = {
};
static struct omap_board_config_kernel h2_config[] __initdata = {
- { OMAP_TAG_USB, &h2_usb_config },
- { OMAP_TAG_MMC, &h2_mmc_config },
+ { OMAP_TAG_USB, &h2_usb_config },
+ { OMAP_TAG_MMC, &h2_mmc_config },
{ OMAP_TAG_UART, &h2_uart_config },
{ OMAP_TAG_LCD, &h2_lcd_config },
};
#define H2_NAND_RB_GPIO_PIN 62
-static int h2_nand_dev_ready(struct nand_platform_data *data)
+static int h2_nand_dev_ready(struct omap_nand_platform_data *data)
{
return omap_get_gpio_datain(H2_NAND_RB_GPIO_PIN);
}
@@ -436,18 +424,16 @@ static void __init h2_init(void)
h2_nor_resource.end = h2_nor_resource.start = omap_cs3_phys();
h2_nor_resource.end += SZ_32M - 1;
-#if 0 /* REVISIT: Enable when nand_platform_data is applied */
h2_nand_resource.end = h2_nand_resource.start = OMAP_CS2B_PHYS;
h2_nand_resource.end += SZ_4K - 1;
if (!(omap_request_gpio(H2_NAND_RB_GPIO_PIN)))
h2_nand_data.dev_ready = h2_nand_dev_ready;
-#endif
omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
/* MMC: card detect and WP */
- // omap_cfg_reg(U19_ARMIO1); /* CD */
+ /* omap_cfg_reg(U19_ARMIO1); */ /* CD */
omap_cfg_reg(BALLOUT_V8_ARMIO3); /* WP */
/* Irda */
@@ -463,16 +449,9 @@ static void __init h2_init(void)
omap_board_config = h2_config;
omap_board_config_size = ARRAY_SIZE(h2_config);
omap_serial_init();
-
- /* irq for tps65010 chip */
- omap_cfg_reg(W4_GPIO58);
- if (gpio_request(58, "tps65010") == 0)
- gpio_direction_input(58);
-
-#ifdef CONFIG_I2C_BOARDINFO
- i2c_register_board_info(1, h2_i2c_board_info,
- ARRAY_SIZE(h2_i2c_board_info));
-#endif
+ omap_register_i2c_bus(1, 100, h2_i2c_board_info,
+ ARRAY_SIZE(h2_i2c_board_info));
+ h2_mmc_init();
}
static void __init h2_map_io(void)
@@ -480,22 +459,6 @@ static void __init h2_map_io(void)
omap1_map_common_io();
}
-#ifdef CONFIG_TPS65010
-static int __init h2_tps_init(void)
-{
- if (!machine_is_omap_h2())
- return 0;
-
- /* gpio3 for SD, gpio4 for VDD_DSP */
- /* FIXME send power to DSP iff it's configured */
-
- /* Enable LOW_PWR */
- tps65010_set_low_pwr(ON);
- return 0;
-}
-fs_initcall(h2_tps_init);
-#endif
-
MACHINE_START(OMAP_H2, "TI-H2")
/* Maintainer: Imre Deak <imre.deak@nokia.com> */
.phys_io = 0xfff00000,
diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c
new file mode 100644
index 00000000000..66ecc437928
--- /dev/null
+++ b/arch/arm/mach-omap1/board-h3-mmc.c
@@ -0,0 +1,114 @@
+/*
+ * linux/arch/arm/mach-omap1/board-h3-mmc.c
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Author: Felipe Balbi <felipe.lima@indt.org.br>
+ *
+ * This code is based on linux/arch/arm/mach-omap2/board-n800-mmc.c, which is:
+ * Copyright (C) 2006 Nokia Corporation
+ *
+ * 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 <asm/arch/mmc.h>
+#include <asm/arch/gpio.h>
+
+#ifdef CONFIG_MMC_OMAP
+static int slot_cover_open;
+static struct device *mmc_device;
+
+static int h3_mmc_set_power(struct device *dev, int slot, int power_on,
+ int vdd)
+{
+#ifdef CONFIG_MMC_DEBUG
+ dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
+ power_on ? "on" : "off", vdd);
+#endif
+ if (slot != 0) {
+ dev_err(dev, "No such slot %d\n", slot + 1);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int h3_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
+{
+ int ret = 0;
+
+#ifdef CONFIG_MMC_DEBUG
+ dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1,
+ bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
+#endif
+ if (slot != 0) {
+ dev_err(dev, "No such slot %d\n", slot + 1);
+ return -ENODEV;
+ }
+
+ /* Treated on upper level */
+
+ return bus_mode;
+}
+
+static int h3_mmc_get_cover_state(struct device *dev, int slot)
+{
+ BUG_ON(slot != 0);
+
+ return slot_cover_open;
+}
+
+void h3_mmc_slot_cover_handler(void *arg, int state)
+{
+ if (mmc_device == NULL)
+ return;
+
+ slot_cover_open = state;
+ omap_mmc_notify_cover_event(mmc_device, 0, state);
+}
+
+static int h3_mmc_late_init(struct device *dev)
+{
+ int ret = 0;
+
+ mmc_device = dev;
+
+ return ret;
+}
+
+static void h3_mmc_cleanup(struct device *dev)
+{
+}
+
+static struct omap_mmc_platform_data h3_mmc_data = {
+ .nr_slots = 1,
+ .switch_slot = NULL,
+ .init = h3_mmc_late_init,
+ .cleanup = h3_mmc_cleanup,
+ .slots[0] = {
+ .set_power = h3_mmc_set_power,
+ .set_bus_mode = h3_mmc_set_bus_mode,
+ .get_ro = NULL,
+ .get_cover_state = h3_mmc_get_cover_state,
+ .ocr_mask = MMC_VDD_28_29 | MMC_VDD_30_31 |
+ MMC_VDD_32_33 | MMC_VDD_33_34,
+ .name = "mmcblk",
+ },
+};
+
+void __init h3_mmc_init(void)
+{
+ omap_set_mmc_info(1, &h3_mmc_data);
+}
+
+#else
+
+void __init h3_mmc_init(void)
+{
+}
+
+void h3_mmc_slot_cover_handler(void *arg, int state)
+{
+}
+#endif
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 05651986056..6fc516855a8 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -42,6 +42,7 @@
#include <asm/arch/irqs.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/nand.h>
#include <asm/arch/irda.h>
#include <asm/arch/usb.h>
#include <asm/arch/keypad.h>
@@ -50,8 +51,6 @@
#include <asm/arch/mcbsp.h>
#include <asm/arch/omap-alsa.h>
-extern int omap_gpio_init(void);
-
static int h3_keymap[] = {
KEY(0, 0, KEY_LEFT),
KEY(0, 1, KEY_RIGHT),
@@ -179,7 +178,7 @@ static struct mtd_partition nand_partitions[] = {
};
/* dip switches control NAND chip access: 8 bit, 16 bit, or neither */
-static struct nand_platform_data nand_data = {
+static struct omap_nand_platform_data nand_data = {
.options = NAND_SAMSUNG_LP_OPTIONS,
.parts = nand_partitions,
.nr_parts = ARRAY_SIZE(nand_partitions),
@@ -387,18 +386,18 @@ static struct omap_mcbsp_reg_cfg mcbsp_regs = {
.srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
.pcr0 = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
- //.pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
+ /*.pcr0 = CLKXP | CLKRP,*/ /* mcbsp: slave */
};
static struct omap_alsa_codec_config alsa_config = {
.name = "H3 TSC2101",
.mcbsp_regs_alsa = &mcbsp_regs,
- .codec_configure_dev = NULL, // tsc2101_configure,
- .codec_set_samplerate = NULL, // tsc2101_set_samplerate,
- .codec_clock_setup = NULL, // tsc2101_clock_setup,
- .codec_clock_on = NULL, // tsc2101_clock_on,
- .codec_clock_off = NULL, // tsc2101_clock_off,
- .get_default_samplerate = NULL, // tsc2101_get_default_samplerate,
+ .codec_configure_dev = NULL, /* tsc2101_configure, */
+ .codec_set_samplerate = NULL, /* tsc2101_set_samplerate, */
+ .codec_clock_setup = NULL, /* tsc2101_clock_setup, */
+ .codec_clock_on = NULL, /* tsc2101_clock_on, */
+ .codec_clock_off = NULL, /* tsc2101_clock_off, */
+ .get_default_samplerate = NULL, /* tsc2101_get_default_samplerate, */
};
static struct platform_device h3_mcbsp1_device = {
@@ -436,12 +435,13 @@ static struct omap_usb_config h3_usb_config __initdata = {
static struct omap_mmc_config h3_mmc_config __initdata = {
.mmc[0] = {
- .enabled = 1,
- .power_pin = -1, /* tps65010 GPIO4 */
- .switch_pin = OMAP_MPUIO(1),
- },
+ .enabled = 1,
+ .wire4 = 1,
+ },
};
+extern struct omap_mmc_platform_data h3_mmc_data;
+
static struct omap_uart_config h3_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
};
@@ -450,29 +450,28 @@ static struct omap_lcd_config h3_lcd_config __initdata = {
.ctrl_name = "internal",
};
-static struct omap_board_config_kernel h3_config[] = {
+static struct omap_board_config_kernel h3_config[] __initdata = {
{ OMAP_TAG_USB, &h3_usb_config },
{ OMAP_TAG_MMC, &h3_mmc_config },
{ OMAP_TAG_UART, &h3_uart_config },
{ OMAP_TAG_LCD, &h3_lcd_config },
};
-static struct i2c_board_info __initdata h3_i2c_board_info[] = {
+static struct omap_gpio_switch h3_gpio_switches[] __initdata = {
{
- I2C_BOARD_INFO("tps65010", 0x48),
- .type = "tps65013",
- /* .irq = OMAP_GPIO_IRQ(??), */
+ .name = "mmc_slot",
+ .gpio = OMAP_MPUIO(1),
+ .type = OMAP_GPIO_SWITCH_TYPE_COVER,
+ .debounce_rising = 100,
+ .debounce_falling = 0,
+ .notify = h3_mmc_slot_cover_handler,
+ .notify_data = NULL,
},
- /* TODO when driver support is ready:
- * - isp1301 OTG transceiver
- * - optional ov9640 camera sensor at 0x30
- * - ...
- */
};
#define H3_NAND_RB_GPIO_PIN 10
-static int nand_dev_ready(struct nand_platform_data *data)
+static int nand_dev_ready(struct omap_nand_platform_data *data)
{
return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN);
}
@@ -500,13 +499,14 @@ static void __init h3_init(void)
omap_cfg_reg(V2_1710_GPIO10);
platform_add_devices(devices, ARRAY_SIZE(devices));
+ spi_register_board_info(h3_spi_board_info,
+ ARRAY_SIZE(h3_spi_board_info));
omap_board_config = h3_config;
omap_board_config_size = ARRAY_SIZE(h3_config);
omap_serial_init();
-
- /* FIXME setup irq for tps65013 chip */
- i2c_register_board_info(1, h3_i2c_board_info,
- ARRAY_SIZE(h3_i2c_board_info));
+ omap_register_i2c_bus(1, 100, h3_i2c_board_info,
+ ARRAY_SIZE(h3_i2c_board_info));
+ h3_mmc_init();
}
static void __init h3_init_smc91x(void)
@@ -531,23 +531,6 @@ static void __init h3_map_io(void)
omap1_map_common_io();
}
-#ifdef CONFIG_TPS65010
-static int __init h3_tps_init(void)
-{
- if (!machine_is_omap_h3())
- return 0;
-
- /* gpio4 for SD, gpio3 for VDD_DSP */
- /* FIXME send power to DSP iff it's configured */
-
- /* Enable LOW_PWR */
- tps65013_set_low_pwr(ON);
-
- return 0;
-}
-fs_initcall(h3_tps_init);
-#endif
-
MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
/* Maintainer: Texas Instruments, Inc. */
.phys_io = 0xfff00000,
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 7d2d8af155a..4b8ae3ee0d0 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -134,12 +134,12 @@ static struct omap_mcbsp_reg_cfg mcbsp_regs = {
static struct omap_alsa_codec_config alsa_config = {
.name = "OMAP Innovator AIC23",
.mcbsp_regs_alsa = &mcbsp_regs,
- .codec_configure_dev = NULL, // aic23_configure,
- .codec_set_samplerate = NULL, // aic23_set_samplerate,
- .codec_clock_setup = NULL, // aic23_clock_setup,
- .codec_clock_on = NULL, // aic23_clock_on,
- .codec_clock_off = NULL, // aic23_clock_off,
- .get_default_samplerate = NULL, // aic23_get_default_samplerate,
+ .codec_configure_dev = NULL, /* aic23_configure, */
+ .codec_set_samplerate = NULL, /* aic23_set_samplerate, */
+ .codec_clock_setup = NULL, /* aic23_clock_setup, */
+ .codec_clock_on = NULL, /* aic23_clock_on, */
+ .codec_clock_off = NULL, /* aic23_clock_off, */
+ .get_default_samplerate = NULL, /* aic23_get_default_samplerate, */
};
static struct platform_device innovator_mcbsp1_device = {
@@ -345,11 +345,11 @@ static struct omap_usb_config h2_usb_config __initdata = {
.otg = 2,
#ifdef CONFIG_USB_GADGET_OMAP
- .hmc_mode = 19, // 0:host(off) 1:dev|otg 2:disabled
- // .hmc_mode = 21, // 0:host(off) 1:dev(loopback) 2:host(loopback)
+ .hmc_mode = 19, /* 0:host(off) 1:dev|otg 2:disabled */
+ /* .hmc_mode = 21,*/ /* 0:host(off) 1:dev(loopback) 2:host(loopback) */
#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
/* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
- .hmc_mode = 20, // 1:dev|otg(off) 1:host 2:disabled
+ .hmc_mode = 20, /* 1:dev|otg(off) 1:host 2:disabled */
#endif
.pins[1] = 3,
@@ -411,6 +411,7 @@ static void __init innovator_init(void)
omap_board_config = innovator_config;
omap_board_config_size = ARRAY_SIZE(innovator_config);
omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
}
static void __init innovator_map_io(void)
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index e2c8ffd75cf..bcb984f2300 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -189,7 +189,7 @@ static struct omap_mmc_config nokia770_mmc_config __initdata = {
},
};
-static struct omap_board_config_kernel nokia770_config[] = {
+static struct omap_board_config_kernel nokia770_config[] __initdata = {
{ OMAP_TAG_USB, NULL },
{ OMAP_TAG_MMC, &nokia770_mmc_config },
};
@@ -330,6 +330,7 @@ static void __init omap_nokia770_init(void)
omap_board_config_size = ARRAY_SIZE(nokia770_config);
omap_gpio_init();
omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
omap_dsp_init();
ads7846_dev_init();
mipid_dev_init();
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 84333440008..5279e35a8ae 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -160,12 +160,12 @@ static struct omap_mcbsp_reg_cfg mcbsp_regs = {
static struct omap_alsa_codec_config alsa_config = {
.name = "OSK AIC23",
.mcbsp_regs_alsa = &mcbsp_regs,
- .codec_configure_dev = NULL, // aic23_configure,
- .codec_set_samplerate = NULL, // aic23_set_samplerate,
- .codec_clock_setup = NULL, // aic23_clock_setup,
- .codec_clock_on = NULL, // aic23_clock_on,
- .codec_clock_off = NULL, // aic23_clock_off,
- .get_default_samplerate = NULL, // aic23_get_default_samplerate,
+ .codec_configure_dev = NULL, /* aic23_configure, */
+ .codec_set_samplerate = NULL, /* aic23_set_samplerate, */
+ .codec_clock_setup = NULL, /* aic23_clock_setup, */
+ .codec_clock_on = NULL, /* aic23_clock_on, */
+ .codec_clock_off = NULL, /* aic23_clock_off, */
+ .get_default_samplerate = NULL, /* aic23_get_default_samplerate, */
};
static struct platform_device osk5912_mcbsp1_device = {
@@ -253,7 +253,7 @@ static struct omap_lcd_config osk_lcd_config __initdata = {
};
#endif
-static struct omap_board_config_kernel osk_config[] = {
+static struct omap_board_config_kernel osk_config[] __initdata = {
{ OMAP_TAG_USB, &osk_usb_config },
{ OMAP_TAG_UART, &osk_uart_config },
#ifdef CONFIG_OMAP_OSK_MISTRAL
@@ -392,7 +392,7 @@ static void __init osk_mistral_init(void)
omap_cfg_reg(W13_1610_CCP_CLKM);
omap_cfg_reg(Y12_1610_CCP_CLKP);
/* CCP_DATAM CONFLICTS WITH UART1.TX (and serial console) */
- // omap_cfg_reg(Y14_1610_CCP_DATAM);
+ /* omap_cfg_reg(Y14_1610_CCP_DATAM); */
omap_cfg_reg(W14_1610_CCP_DATAP);
/* CAM_PWDN */
@@ -404,8 +404,8 @@ static void __init osk_mistral_init(void)
pr_debug("OSK+Mistral: CAM_PWDN is awol\n");
- // omap_cfg_reg(P19_1610_GPIO6); // BUSY
- omap_cfg_reg(P20_1610_GPIO4); // PENIRQ
+ /* omap_cfg_reg(P19_1610_GPIO6); */ /* BUSY */
+ omap_cfg_reg(P20_1610_GPIO4); /* PENIRQ */
set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING);
spi_register_board_info(mistral_boardinfo,
ARRAY_SIZE(mistral_boardinfo));
@@ -473,10 +473,9 @@ static void __init osk_init(void)
if (gpio_request(OMAP_MPUIO(1), "tps65010") == 0)
gpio_direction_input(OMAP_MPUIO(1));
- i2c_register_board_info(1, osk_i2c_board_info,
- ARRAY_SIZE(osk_i2c_board_info));
-
omap_serial_init();
+ omap_register_i2c_bus(1, 400, osk_i2c_board_info,
+ ARRAY_SIZE(osk_i2c_board_info));
osk_mistral_init();
}
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 2f9d00a0013..ca1a4bf78a1 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -10,6 +10,8 @@
* Maintainers : http://palmtelinux.sf.net
* palmtelinux-developpers@lists.sf.net
*
+ * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
+ *
* 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.
@@ -24,8 +26,8 @@
#include <linux/spi/spi.h>
#include <linux/spi/tsc2102.h>
#include <linux/interrupt.h>
+#include <linux/apm-emulation.h>
-#include <asm/apm.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -51,11 +53,11 @@ static void __init omap_palmte_init_irq(void)
omap_gpio_init();
}
-static int palmte_keymap[] = {
- KEY(0, 0, KEY_F1),
- KEY(0, 1, KEY_F2),
- KEY(0, 2, KEY_F3),
- KEY(0, 3, KEY_F4),
+static const int palmte_keymap[] = {
+ KEY(0, 0, KEY_F1), /* Calendar */
+ KEY(0, 1, KEY_F2), /* Contacts */
+ KEY(0, 2, KEY_F3), /* Tasks List */
+ KEY(0, 3, KEY_F4), /* Note Pad */
KEY(0, 4, KEY_POWER),
KEY(1, 0, KEY_LEFT),
KEY(1, 1, KEY_DOWN),
@@ -68,7 +70,7 @@ static int palmte_keymap[] = {
static struct omap_kp_platform_data palmte_kp_data = {
.rows = 8,
.cols = 8,
- .keymap = palmte_keymap,
+ .keymap = (int *) palmte_keymap,
.rep = 1,
.delay = 12,
};
@@ -180,7 +182,7 @@ static struct platform_device palmte_irda_device = {
.resource = palmte_irda_resources,
};
-static struct platform_device *devices[] __initdata = {
+static struct platform_device *palmte_devices[] __initdata = {
&palmte_rom_device,
&palmte_kp_device,
&palmte_lcd_device,
@@ -273,7 +275,7 @@ static void palmte_get_power_status(struct apm_power_info *info, int *battery)
info->time = 0;
} else {
while (hi > lo + 1) {
- mid = (hi + lo) >> 2;
+ mid = (hi + lo) >> 1;
if (batt <= palmte_battery_sample[mid])
lo = mid;
else
@@ -321,7 +323,7 @@ static struct tsc2102_config palmte_tsc2102_config = {
.alsa_config = &palmte_alsa_config,
};
-static struct omap_board_config_kernel palmte_config[] = {
+static struct omap_board_config_kernel palmte_config[] __initdata = {
{ OMAP_TAG_USB, &palmte_usb_config },
{ OMAP_TAG_MMC, &palmte_mmc_config },
{ OMAP_TAG_LCD, &palmte_lcd_config },
@@ -339,74 +341,34 @@ static struct spi_board_info palmte_spi_info[] __initdata = {
},
};
-/* Periodically check for changes on important input pins */
-struct timer_list palmte_pin_timer;
-int prev_power, prev_headphones;
-
-static void palmte_pin_handler(unsigned long data) {
- int power, headphones;
-
- power = !omap_get_gpio_datain(PALMTE_DC_GPIO);
- headphones = omap_get_gpio_datain(PALMTE_HEADPHONES_GPIO);
-
- if (power && !prev_power)
- printk(KERN_INFO "PM: cable connected\n");
- else if (!power && prev_power)
- printk(KERN_INFO "PM: cable disconnected\n");
-
- if (headphones && !prev_headphones) {
+static void palmte_headphones_detect(void *data, int state)
+{
+ if (state) {
/* Headphones connected, disable speaker */
omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 0);
printk(KERN_INFO "PM: speaker off\n");
- } else if (!headphones && prev_headphones) {
+ } else {
/* Headphones unplugged, re-enable speaker */
omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 1);
printk(KERN_INFO "PM: speaker on\n");
}
-
- prev_power = power;
- prev_headphones = headphones;
- mod_timer(&palmte_pin_timer, jiffies + msecs_to_jiffies(500));
}
-static void __init palmte_gpio_setup(void)
+static void __init palmte_misc_gpio_setup(void)
{
- /* Set TSC2102 PINTDAV pin as input */
+ /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
if (omap_request_gpio(PALMTE_PINTDAV_GPIO)) {
printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
return;
}
omap_set_gpio_direction(PALMTE_PINTDAV_GPIO, 1);
- /* Monitor cable-connected signals */
- if (omap_request_gpio(PALMTE_DC_GPIO) ||
- omap_request_gpio(PALMTE_USB_OR_DC_GPIO) ||
- omap_request_gpio(PALMTE_USBDETECT_GPIO)) {
+ /* Set USB-or-DC-IN pin as input (unused) */
+ if (omap_request_gpio(PALMTE_USB_OR_DC_GPIO)) {
printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
return;
}
- omap_set_gpio_direction(PALMTE_DC_GPIO, 1);
omap_set_gpio_direction(PALMTE_USB_OR_DC_GPIO, 1);
- omap_set_gpio_direction(PALMTE_USBDETECT_GPIO, 1);
-
- /* Set speaker-enable pin as output */
- if (omap_request_gpio(PALMTE_SPEAKER_GPIO)) {
- printk(KERN_ERR "Could not reserve speaker GPIO!\n");
- return;
- }
- omap_set_gpio_direction(PALMTE_SPEAKER_GPIO, 0);
-
- /* Monitor the headphones-connected signal */
- if (omap_request_gpio(PALMTE_HEADPHONES_GPIO)) {
- printk(KERN_ERR "Could not reserve headphones signal GPIO!\n");
- return;
- }
- omap_set_gpio_direction(PALMTE_HEADPHONES_GPIO, 1);
-
- prev_power = omap_get_gpio_datain(PALMTE_DC_GPIO);
- prev_headphones = !omap_get_gpio_datain(PALMTE_HEADPHONES_GPIO);
- setup_timer(&palmte_pin_timer, palmte_pin_handler, 0);
- palmte_pin_handler(0);
}
static void __init omap_palmte_init(void)
@@ -414,12 +376,12 @@ static void __init omap_palmte_init(void)
omap_board_config = palmte_config;
omap_board_config_size = ARRAY_SIZE(palmte_config);
- platform_add_devices(devices, ARRAY_SIZE(devices));
+ platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices));
spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
-
+ palmte_misc_gpio_setup();
omap_serial_init();
- palmte_gpio_setup();
+ omap_register_i2c_bus(1, 100, NULL, 0);
}
static void __init omap_palmte_map_io(void)
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index ed7094a7006..2a033689f9f 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -144,12 +144,12 @@ static struct omap_mcbsp_reg_cfg mcbsp_regs = {
static struct omap_alsa_codec_config alsa_config = {
.name = "PalmTT AIC23",
.mcbsp_regs_alsa = &mcbsp_regs,
- .codec_configure_dev = NULL, // aic23_configure,
- .codec_set_samplerate = NULL, // aic23_set_samplerate,
- .codec_clock_setup = NULL, // aic23_clock_setup,
- .codec_clock_on = NULL, // aic23_clock_on,
- .codec_clock_off = NULL, // aic23_clock_off,
- .get_default_samplerate = NULL, // aic23_get_default_samplerate,
+ .codec_configure_dev = NULL, /* aic23_configure, */
+ .codec_set_samplerate = NULL, /* aic23_set_samplerate, */
+ .codec_clock_setup = NULL, /* aic23_clock_setup, */
+ .codec_clock_on = NULL, /* aic23_clock_on, */
+ .codec_clock_off = NULL, /* aic23_clock_off, */
+ .get_default_samplerate = NULL, /* aic23_get_default_samplerate, */
};
static struct platform_device palmtt_mcbsp1_device = {
@@ -312,7 +312,7 @@ static struct omap_uart_config palmtt_uart_config __initdata = {
.enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
};
-static struct omap_board_config_kernel palmtt_config[] = {
+static struct omap_board_config_kernel palmtt_config[] __initdata = {
{ OMAP_TAG_USB, &palmtt_usb_config },
{ OMAP_TAG_LCD, &palmtt_lcd_config },
{ OMAP_TAG_UART, &palmtt_uart_config },
@@ -338,6 +338,7 @@ static void __init omap_palmtt_init(void)
spi_register_board_info(palmtt_boardinfo,ARRAY_SIZE(palmtt_boardinfo));
omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
}
static void __init omap_palmtt_map_io(void)
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index a9a0f6610c3..156510777ff 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -285,7 +285,7 @@ static struct omap_uart_config palmz71_uart_config __initdata = {
.enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
};
-static struct omap_board_config_kernel palmz71_config[] = {
+static struct omap_board_config_kernel palmz71_config[] __initdata = {
{OMAP_TAG_USB, &palmz71_usb_config},
{OMAP_TAG_MMC, &palmz71_mmc_config},
{OMAP_TAG_LCD, &palmz71_lcd_config},
@@ -363,6 +363,7 @@ omap_palmz71_init(void)
spi_register_board_info(palmz71_boardinfo,
ARRAY_SIZE(palmz71_boardinfo));
omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
palmz71_gpio_setup(0);
}
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 534dcfb9d26..94bc0745ab2 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -30,6 +30,7 @@
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/fpga.h>
+#include <asm/arch/nand.h>
#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
#include <asm/arch/board.h>
@@ -133,7 +134,7 @@ static struct platform_device nor_device = {
.resource = &nor_resource,
};
-static struct nand_platform_data nand_data = {
+static struct omap_nand_platform_data nand_data = {
.options = NAND_SAMSUNG_LP_OPTIONS,
};
@@ -202,7 +203,7 @@ static struct platform_device *devices[] __initdata = {
#define P2_NAND_RB_GPIO_PIN 62
-static int nand_dev_ready(struct nand_platform_data *data)
+static int nand_dev_ready(struct omap_nand_platform_data *data)
{
return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN);
}
@@ -215,7 +216,7 @@ static struct omap_lcd_config perseus2_lcd_config __initdata = {
.ctrl_name = "internal",
};
-static struct omap_board_config_kernel perseus2_config[] = {
+static struct omap_board_config_kernel perseus2_config[] __initdata = {
{ OMAP_TAG_UART, &perseus2_uart_config },
{ OMAP_TAG_LCD, &perseus2_lcd_config },
};
@@ -233,6 +234,7 @@ static void __init omap_perseus2_init(void)
omap_board_config = perseus2_config;
omap_board_config_size = ARRAY_SIZE(perseus2_config);
omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
}
static void __init perseus2_init_smc91x(void)
diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c
new file mode 100644
index 00000000000..8c93d47719e
--- /dev/null
+++ b/arch/arm/mach-omap1/board-sx1-mmc.c
@@ -0,0 +1,124 @@
+/*
+ * linux/arch/arm/mach-omap1/board-sx1-mmc.c
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Author: Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>
+ *
+ * This code is based on linux/arch/arm/mach-omap1/board-h2-mmc.c, which is:
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ *
+ * 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 <asm/arch/hardware.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/gpio.h>
+
+#ifdef CONFIG_MMC_OMAP
+static int slot_cover_open;
+static struct device *mmc_device;
+
+static int sx1_mmc_set_power(struct device *dev, int slot, int power_on,
+ int vdd)
+{
+ int err;
+ u8 dat = 0;
+
+#ifdef CONFIG_MMC_DEBUG
+ dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
+ power_on ? "on" : "off", vdd);
+#endif
+
+ if (slot != 0) {
+ dev_err(dev, "No such slot %d\n", slot + 1);
+ return -ENODEV;
+ }
+
+ err = sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
+ if (err < 0)
+ return err;
+
+ if (power_on)
+ dat |= SOFIA_MMC_POWER;
+ else
+ dat &= ~SOFIA_MMC_POWER;
+
+ return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
+}
+
+static int sx1_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
+{
+#ifdef CONFIG_MMC_DEBUG
+ dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1,
+ bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
+#endif
+ if (slot != 0) {
+ dev_err(dev, "No such slot %d\n", slot + 1);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int sx1_mmc_get_cover_state(struct device *dev, int slot)
+{
+ BUG_ON(slot != 0);
+
+ return slot_cover_open;
+}
+
+void sx1_mmc_slot_cover_handler(void *arg, int state)
+{
+ if (mmc_device == NULL)
+ return;
+
+ slot_cover_open = state;
+ omap_mmc_notify_cover_event(mmc_device, 0, state);
+}
+
+static int sx1_mmc_late_init(struct device *dev)
+{
+ int ret = 0;
+
+ mmc_device = dev;
+
+ return ret;
+}
+
+static void sx1_mmc_cleanup(struct device *dev)
+{
+}
+
+static struct omap_mmc_platform_data sx1_mmc_data = {
+ .nr_slots = 1,
+ .switch_slot = NULL,
+ .init = sx1_mmc_late_init,
+ .cleanup = sx1_mmc_cleanup,
+ .slots[0] = {
+ .set_power = sx1_mmc_set_power,
+ .set_bus_mode = sx1_mmc_set_bus_mode,
+ .get_ro = NULL,
+ .get_cover_state = sx1_mmc_get_cover_state,
+ .ocr_mask = MMC_VDD_28_29 | MMC_VDD_30_31 |
+ MMC_VDD_32_33 | MMC_VDD_33_34,
+ .name = "mmcblk",
+ },
+};
+
+void __init sx1_mmc_init(void)
+{
+ omap_set_mmc_info(1, &sx1_mmc_data);
+}
+
+#else
+
+void __init sx1_mmc_init(void)
+{
+}
+
+void sx1_mmc_slot_cover_handler(void *arg, int state)
+{
+}
+#endif
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 2743d639aa0..1c7f09aedf0 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -44,7 +44,7 @@
#include <asm/arch/keypad.h>
/* Write to I2C device */
-int i2c_write_byte(u8 devaddr, u8 regoffset, u8 value)
+int sx1_i2c_write_byte(u8 devaddr, u8 regoffset, u8 value)
{
struct i2c_adapter *adap;
int err;
@@ -67,7 +67,7 @@ int i2c_write_byte(u8 devaddr, u8 regoffset, u8 value)
}
/* Read from I2C device */
-int i2c_read_byte(u8 devaddr, u8 regoffset, u8 * value)
+int sx1_i2c_read_byte(u8 devaddr, u8 regoffset, u8 *value)
{
struct i2c_adapter *adap;
int err;
@@ -101,66 +101,55 @@ int sx1_setkeylight(u8 keylight)
{
if (keylight > SOFIA_MAX_LIGHT_VAL)
keylight = SOFIA_MAX_LIGHT_VAL;
- return i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_KEYLIGHT_REG, keylight);
+ return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_KEYLIGHT_REG, keylight);
}
/* get current keylight intensity */
int sx1_getkeylight(u8 * keylight)
{
- return i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_KEYLIGHT_REG, keylight);
+ return sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_KEYLIGHT_REG, keylight);
}
/* set LCD backlight intensity */
int sx1_setbacklight(u8 backlight)
{
if (backlight > SOFIA_MAX_LIGHT_VAL)
backlight = SOFIA_MAX_LIGHT_VAL;
- return i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_BACKLIGHT_REG, backlight);
+ return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_BACKLIGHT_REG,
+ backlight);
}
/* get current LCD backlight intensity */
int sx1_getbacklight (u8 * backlight)
{
- return i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_BACKLIGHT_REG, backlight);
+ return sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_BACKLIGHT_REG,
+ backlight);
}
/* set LCD backlight power on/off */
int sx1_setmmipower(u8 onoff)
{
int err;
u8 dat = 0;
- err = i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
+ err = sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
if (err < 0)
return err;
if (onoff)
dat |= SOFIA_MMILIGHT_POWER;
else
dat &= ~SOFIA_MMILIGHT_POWER;
- return i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
-}
-/* set MMC power on/off */
-int sx1_setmmcpower(u8 onoff)
-{
- int err;
- u8 dat = 0;
- err = i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
- if (err < 0)
- return err;
- if (onoff)
- dat |= SOFIA_MMC_POWER;
- else
- dat &= ~SOFIA_MMC_POWER;
- return i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
+ return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
}
+
/* set USB power on/off */
int sx1_setusbpower(u8 onoff)
{
int err;
u8 dat = 0;
- err = i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
+ err = sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
if (err < 0)
return err;
if (onoff)
dat |= SOFIA_USB_POWER;
else
dat &= ~SOFIA_USB_POWER;
- return i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
+ return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
}
EXPORT_SYMBOL(sx1_setkeylight);
@@ -168,7 +157,6 @@ EXPORT_SYMBOL(sx1_getkeylight);
EXPORT_SYMBOL(sx1_setbacklight);
EXPORT_SYMBOL(sx1_getbacklight);
EXPORT_SYMBOL(sx1_setmmipower);
-EXPORT_SYMBOL(sx1_setmmcpower);
EXPORT_SYMBOL(sx1_setusbpower);
/*----------- Keypad -------------------------*/
@@ -280,21 +268,6 @@ static struct omap_mcbsp_reg_cfg mcbsp1_regs = {
/* PCR0 =0f0f */
};
-/* TODO: PCM interface - McBSP2 */
-static struct omap_mcbsp_reg_cfg mcbsp2_regs = {
- .spcr2 = FRST | GRST | XRST | XINTM(3), /* SPCR2=F1 */
- .spcr1 = RINTM(3) | RRST, /* SPCR1=30 */
- .rcr2 = 0, /* RCR2 =00 */
- .rcr1 = RFRLEN1(1) | RWDLEN1(OMAP_MCBSP_WORD_16), /* RCR1 = 140 */
- .xcr2 = 0, /* XCR2 = 0 */
- .xcr1 = XFRLEN1(1) | XWDLEN1(OMAP_MCBSP_WORD_16), /* XCR1 = 140 */
- .srgr1 = FWID(15) | CLKGDV(12), /* SRGR1=0f0c */
- .srgr2 = FSGM | FPER(31), /* SRGR2=101f */
- .pcr0 = FSXM | FSRM | CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
- /* PCR0=0f0f */
- /* mcbsp: slave */
-};
-
static struct omap_alsa_codec_config sx1_alsa_config = {
.name = "SX1 EGold",
.mcbsp_regs_alsa = &mcbsp1_regs,
@@ -407,11 +380,8 @@ static struct omap_usb_config sx1_usb_config __initdata = {
static struct omap_mmc_config sx1_mmc_config __initdata = {
.mmc [0] = {
- .enabled = 1,
+ .enabled = 1,
.wire4 = 0,
- .wp_pin = -1,
- .power_pin = -1, /* power is in Sofia */
- .switch_pin = OMAP_MPUIO(3),
},
};
@@ -440,13 +410,15 @@ static struct omap_uart_config sx1_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
};
-static struct omap_board_config_kernel sx1_config[] = {
+static struct omap_board_config_kernel sx1_config[] __initdata = {
{ OMAP_TAG_USB, &sx1_usb_config },
{ OMAP_TAG_MMC, &sx1_mmc_config },
{ OMAP_TAG_LCD, &sx1_lcd_config },
{ OMAP_TAG_UART, &sx1_uart_config },
};
+
/*-----------------------------------------*/
+
static void __init omap_sx1_init(void)
{
platform_add_devices(sx1_devices, ARRAY_SIZE(sx1_devices));
@@ -454,6 +426,8 @@ static void __init omap_sx1_init(void)
omap_board_config = sx1_config;
omap_board_config_size = ARRAY_SIZE(sx1_config);
omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
+ sx1_mmc_init();
/* turn on USB power */
/* sx1_setusbpower(1); cant do it here because i2c is not ready */
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index c82a1cd20ad..5c00b3f39cd 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -34,9 +34,6 @@
#include <asm/arch/tc.h>
#include <asm/arch/usb.h>
-extern void omap_init_time(void);
-extern int omap_gpio_init(void);
-
static struct plat_serial8250_port voiceblue_ports[] = {
{
.mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x40000),
@@ -198,6 +195,7 @@ static void __init voiceblue_init(void)
omap_board_config = voiceblue_config;
omap_board_config_size = ARRAY_SIZE(voiceblue_config);
omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
/* There is a good chance board is going up, so enable power LED
* (it is connected through invertor) */
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 5d9faa68d2e..4ea2933f887 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -1,4 +1,3 @@
-//kernel/linux-omap-fsample/arch/arm/mach-omap1/clock.c#2 - edit change 3808 (text)
/*
* linux/arch/arm/mach-omap1/clock.c
*
@@ -650,9 +649,9 @@ static void __init omap1_clk_disable_unused(struct clk *clk)
/* FIXME: This clock seems to be necessary but no-one
* has asked for its activation. */
- if (clk == &tc2_ck // FIX: pm.c (SRAM), CCP, Camera
- || clk == &ck_dpll1out.clk // FIX: SoSSI, SSR
- || clk == &arm_gpio_ck // FIX: GPIO code for 1510
+ if (clk == &tc2_ck /* FIX: pm.c (SRAM), CCP, Camera */
+ || clk == &ck_dpll1out.clk /* FIX: SoSSI, SSR */
+ || clk == &arm_gpio_ck /* FIX: GPIO code for 1510 */
) {
printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n",
clk->name);
diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c
index 6939d5e7569..026685ed461 100644
--- a/arch/arm/mach-omap1/leds-osk.c
+++ b/arch/arm/mach-omap1/leds-osk.c
@@ -82,7 +82,7 @@ static void mistral_setled(void)
red = 1;
else if (hw_led_state & IDLE_LED)
green = 1;
- // else both sides are disabled
+ /* else both sides are disabled */
omap_set_gpio_dataout(GPIO_LED_GREEN, green);
omap_set_gpio_dataout(GPIO_LED_RED, red);
@@ -112,7 +112,7 @@ void osk_leds_event(led_event_t evt)
case led_stop:
led_state &= ~LED_STATE_ENABLED;
hw_led_state = 0;
- // NOTE: work may still be pending!!
+ /* NOTE: work may still be pending!! */
break;
case led_claim:
diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c
index d3abf560990..bad1e7152d8 100644
--- a/arch/arm/mach-omap1/mailbox.c
+++ b/arch/arm/mach-omap1/mailbox.c
@@ -51,7 +51,7 @@ static inline void mbox_write_reg(unsigned int val, unsigned int reg)
}
/* msg */
-static inline mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
+static mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
{
struct omap_mbox1_fifo *fifo =
&((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
@@ -63,7 +63,7 @@ static inline mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
return msg;
}
-static inline void
+static void
omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
{
struct omap_mbox1_fifo *fifo =
@@ -73,12 +73,12 @@ omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
mbox_write_reg(msg >> 16, fifo->cmd);
}
-static inline int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
+static int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
{
return 0;
}
-static inline int omap1_mbox_fifo_full(struct omap_mbox *mbox)
+static int omap1_mbox_fifo_full(struct omap_mbox *mbox)
{
struct omap_mbox1_fifo *fifo =
&((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
@@ -87,21 +87,21 @@ static inline int omap1_mbox_fifo_full(struct omap_mbox *mbox)
}
/* irq */
-static inline void
+static void
omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
{
if (irq == IRQ_RX)
enable_irq(mbox->irq);
}
-static inline void
+static void
omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
{
if (irq == IRQ_RX)
disable_irq(mbox->irq);
}
-static inline int
+static int
omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
{
if (irq == IRQ_TX)
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 06b7e54a012..8eb5dcdaead 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -57,7 +57,6 @@
#include <asm/arch/pm.h>
#include <asm/arch/mux.h>
#include <asm/arch/dma.h>
-#include <asm/arch/dsp_common.h>
#include <asm/arch/dmtimer.h>
static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
@@ -67,6 +66,8 @@ static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE];
static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
+#ifdef CONFIG_OMAP_32K_TIMER
+
static unsigned short enable_dyn_sleep = 1;
static ssize_t idle_show(struct kobject *kobj, struct kobj_attribute *attr,
@@ -91,7 +92,8 @@ static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr,
static struct kobj_attribute sleep_while_idle_attr =
__ATTR(sleep_while_idle, 0644, idle_show, idle_store);
-static void (*omap_sram_idle)(void) = NULL;
+#endif
+
static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
/*
@@ -104,9 +106,7 @@ void omap_pm_idle(void)
{
extern __u32 arm_idlect1_mask;
__u32 use_idlect1 = arm_idlect1_mask;
-#ifndef CONFIG_OMAP_MPU_TIMER
- int do_sleep;
-#endif
+ int do_sleep = 0;
local_irq_disable();
local_fiq_disable();
@@ -128,7 +128,6 @@ void omap_pm_idle(void)
use_idlect1 = use_idlect1 & ~(1 << 9);
#else
- do_sleep = 0;
while (enable_dyn_sleep) {
#ifdef CONFIG_CBUS_TAHVO_USB
@@ -141,6 +140,8 @@ void omap_pm_idle(void)
break;
}
+#endif
+
#ifdef CONFIG_OMAP_DM_TIMER
use_idlect1 = omap_dm_timer_modify_idlect_mask(use_idlect1);
#endif
@@ -168,7 +169,6 @@ void omap_pm_idle(void)
}
omap_sram_suspend(omap_readl(ARM_IDLECT1),
omap_readl(ARM_IDLECT2));
-#endif
local_fiq_enable();
local_irq_enable();
@@ -661,7 +661,10 @@ static struct platform_suspend_ops omap_pm_ops ={
static int __init omap_pm_init(void)
{
+
+#ifdef CONFIG_OMAP_32K_TIMER
int error;
+#endif
printk("Power Management for TI OMAP.\n");
@@ -671,23 +674,17 @@ static int __init omap_pm_init(void)
* memory the MPU can see when it wakes up.
*/
if (cpu_is_omap730()) {
- omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend,
- omap730_idle_loop_suspend_sz);
omap_sram_suspend = omap_sram_push(omap730_cpu_suspend,
omap730_cpu_suspend_sz);
} else if (cpu_is_omap15xx()) {
- omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
- omap1510_idle_loop_suspend_sz);
omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
omap1510_cpu_suspend_sz);
} else if (cpu_is_omap16xx()) {
- omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
- omap1610_idle_loop_suspend_sz);
omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
omap1610_cpu_suspend_sz);
}
- if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
+ if (omap_sram_suspend == NULL) {
printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
return -ENODEV;
}
@@ -719,9 +716,11 @@ static int __init omap_pm_init(void)
omap_pm_init_proc();
#endif
+#ifdef CONFIG_OMAP_32K_TIMER
error = sysfs_create_file(power_kobj, &sleep_while_idle_attr);
if (error)
printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
+#endif
if (cpu_is_omap16xx()) {
/* configure LOW_PWR pin */
diff --git a/arch/arm/mach-omap1/sleep.S b/arch/arm/mach-omap1/sleep.S
index abef33d10f0..68f5b39030b 100644
--- a/arch/arm/mach-omap1/sleep.S
+++ b/arch/arm/mach-omap1/sleep.S
@@ -39,167 +39,6 @@
.text
-/*
- * Forces OMAP into idle state
- *
- * omapXXXX_idle_loop_suspend()
- *
- * Note: This code get's copied to internal SRAM at boot. When the OMAP
- * wakes up it continues execution at the point it went to sleep.
- *
- * Note: Because of slightly different configuration values we have
- * processor specific functions here.
- */
-
-#if defined(CONFIG_ARCH_OMAP730)
-ENTRY(omap730_idle_loop_suspend)
-
- stmfd sp!, {r0 - r12, lr} @ save registers on stack
-
- @ load base address of ARM_IDLECT1 and ARM_IDLECT2
- mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
- orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
- orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
-
- @ turn off clock domains
- @ get ARM_IDLECT2 into r2
- ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
- mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff
- orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00
- strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
-
- @ request ARM idle
- @ get ARM_IDLECT1 into r1
- ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
- orr r3, r1, #OMAP730_IDLE_LOOP_REQUEST & 0xffff
- strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
-
- mov r5, #IDLE_WAIT_CYCLES & 0xff
- orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
-l_730: subs r5, r5, #1
- bne l_730
-/*
- * Let's wait for the next clock tick to wake us up.
- */
- mov r0, #0
- mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
-/*
- * omap730_idle_loop_suspend()'s resume point.
- *
- * It will just start executing here, so we'll restore stuff from the
- * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
- */
-
- @ restore ARM_IDLECT1 and ARM_IDLECT2 and return
- @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2
- strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
- strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
-
- ldmfd sp!, {r0 - r12, pc} @ restore regs and return
-
-ENTRY(omap730_idle_loop_suspend_sz)
- .word . - omap730_idle_loop_suspend
-#endif /* CONFIG_ARCH_OMAP730 */
-
-#ifdef CONFIG_ARCH_OMAP15XX
-ENTRY(omap1510_idle_loop_suspend)
-
- stmfd sp!, {r0 - r12, lr} @ save registers on stack
-
- @ load base address of ARM_IDLECT1 and ARM_IDLECT2
- mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
- orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
- orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
-
- @ turn off clock domains
- @ get ARM_IDLECT2 into r2
- ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
- mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
- orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
- strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
-
- @ request ARM idle
- @ get ARM_IDLECT1 into r1
- ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
- orr r3, r1, #OMAP1510_IDLE_LOOP_REQUEST & 0xffff
- strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
-
- mov r5, #IDLE_WAIT_CYCLES & 0xff
- orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
-l_1510: subs r5, r5, #1
- bne l_1510
-/*
- * Let's wait for the next clock tick to wake us up.
- */
- mov r0, #0
- mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
-/*
- * omap1510_idle_loop_suspend()'s resume point.
- *
- * It will just start executing here, so we'll restore stuff from the
- * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
- */
-
- @ restore ARM_IDLECT1 and ARM_IDLECT2 and return
- @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2
- strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
- strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
-
- ldmfd sp!, {r0 - r12, pc} @ restore regs and return
-
-ENTRY(omap1510_idle_loop_suspend_sz)
- .word . - omap1510_idle_loop_suspend
-#endif /* CONFIG_ARCH_OMAP15XX */
-
-#if defined(CONFIG_ARCH_OMAP16XX)
-ENTRY(omap1610_idle_loop_suspend)
-
- stmfd sp!, {r0 - r12, lr} @ save registers on stack
-
- @ load base address of ARM_IDLECT1 and ARM_IDLECT2
- mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
- orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
- orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
-
- @ turn off clock domains
- @ get ARM_IDLECT2 into r2
- ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
- mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
- orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
- strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
-
- @ request ARM idle
- @ get ARM_IDLECT1 into r1
- ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
- orr r3, r1, #OMAP1610_IDLE_LOOP_REQUEST & 0xffff
- strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
-
- mov r5, #IDLE_WAIT_CYCLES & 0xff
- orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
-l_1610: subs r5, r5, #1
- bne l_1610
-/*
- * Let's wait for the next clock tick to wake us up.
- */
- mov r0, #0
- mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
-/*
- * omap1610_idle_loop_suspend()'s resume point.
- *
- * It will just start executing here, so we'll restore stuff from the
- * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
- */
-
- @ restore ARM_IDLECT1 and ARM_IDLECT2 and return
- @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2
- strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
- strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
-
- ldmfd sp!, {r0 - r12, pc} @ restore regs and return
-
-ENTRY(omap1610_idle_loop_suspend_sz)
- .word . - omap1610_idle_loop_suspend
-#endif /* CONFIG_ARCH_OMAP16XX */
/*
* Forces OMAP into deep sleep state
diff --git a/arch/arm/mach-orion/addr-map.c b/arch/arm/mach-orion/addr-map.c
index 488da3811a6..2e2fd63643c 100644
--- a/arch/arm/mach-orion/addr-map.c
+++ b/arch/arm/mach-orion/addr-map.c
@@ -265,15 +265,15 @@ void __init orion_setup_cpu_wins(void)
}
/*
- * Setup windows for PCI+PCIE IO+MAM space
+ * Setup windows for PCI+PCIe IO+MEM space.
*/
- orion_setup_cpu_win(ORION_PCIE_IO, ORION_PCIE_IO_BASE,
- ORION_PCIE_IO_SIZE, ORION_PCIE_IO_REMAP);
- orion_setup_cpu_win(ORION_PCI_IO, ORION_PCI_IO_BASE,
- ORION_PCI_IO_SIZE, ORION_PCI_IO_REMAP);
- orion_setup_cpu_win(ORION_PCIE_MEM, ORION_PCIE_MEM_BASE,
+ orion_setup_cpu_win(ORION_PCIE_IO, ORION_PCIE_IO_PHYS_BASE,
+ ORION_PCIE_IO_SIZE, ORION_PCIE_IO_BUS_BASE);
+ orion_setup_cpu_win(ORION_PCI_IO, ORION_PCI_IO_PHYS_BASE,
+ ORION_PCI_IO_SIZE, ORION_PCI_IO_BUS_BASE);
+ orion_setup_cpu_win(ORION_PCIE_MEM, ORION_PCIE_MEM_PHYS_BASE,
ORION_PCIE_MEM_SIZE, -1);
- orion_setup_cpu_win(ORION_PCI_MEM, ORION_PCI_MEM_BASE,
+ orion_setup_cpu_win(ORION_PCI_MEM, ORION_PCI_MEM_PHYS_BASE,
ORION_PCI_MEM_SIZE, -1);
}
diff --git a/arch/arm/mach-orion/common.c b/arch/arm/mach-orion/common.c
index 5e20b6b3250..5f0ee4b8a9b 100644
--- a/arch/arm/mach-orion/common.c
+++ b/arch/arm/mach-orion/common.c
@@ -19,7 +19,7 @@
#include <asm/page.h>
#include <asm/timex.h>
#include <asm/mach/map.h>
-#include <asm/arch/orion.h>
+#include <asm/arch/hardware.h>
#include "common.h"
/*****************************************************************************
@@ -27,26 +27,26 @@
****************************************************************************/
static struct map_desc orion_io_desc[] __initdata = {
{
- .virtual = ORION_REGS_BASE,
- .pfn = __phys_to_pfn(ORION_REGS_BASE),
+ .virtual = ORION_REGS_VIRT_BASE,
+ .pfn = __phys_to_pfn(ORION_REGS_PHYS_BASE),
.length = ORION_REGS_SIZE,
.type = MT_DEVICE
},
{
- .virtual = ORION_PCIE_IO_BASE,
- .pfn = __phys_to_pfn(ORION_PCIE_IO_BASE),
+ .virtual = ORION_PCIE_IO_VIRT_BASE,
+ .pfn = __phys_to_pfn(ORION_PCIE_IO_PHYS_BASE),
.length = ORION_PCIE_IO_SIZE,
.type = MT_DEVICE
},
{
- .virtual = ORION_PCI_IO_BASE,
- .pfn = __phys_to_pfn(ORION_PCI_IO_BASE),
+ .virtual = ORION_PCI_IO_VIRT_BASE,
+ .pfn = __phys_to_pfn(ORION_PCI_IO_PHYS_BASE),
.length = ORION_PCI_IO_SIZE,
.type = MT_DEVICE
},
{
- .virtual = ORION_PCIE_WA_BASE,
- .pfn = __phys_to_pfn(ORION_PCIE_WA_BASE),
+ .virtual = ORION_PCIE_WA_VIRT_BASE,
+ .pfn = __phys_to_pfn(ORION_PCIE_WA_PHYS_BASE),
.length = ORION_PCIE_WA_SIZE,
.type = MT_DEVICE
},
@@ -63,8 +63,8 @@ void __init orion_map_io(void)
static struct resource orion_uart_resources[] = {
{
- .start = UART0_BASE,
- .end = UART0_BASE + 0xff,
+ .start = UART0_PHYS_BASE,
+ .end = UART0_PHYS_BASE + 0xff,
.flags = IORESOURCE_MEM,
},
{
@@ -73,8 +73,8 @@ static struct resource orion_uart_resources[] = {
.flags = IORESOURCE_IRQ,
},
{
- .start = UART1_BASE,
- .end = UART1_BASE + 0xff,
+ .start = UART1_PHYS_BASE,
+ .end = UART1_PHYS_BASE + 0xff,
.flags = IORESOURCE_MEM,
},
{
@@ -86,8 +86,8 @@ static struct resource orion_uart_resources[] = {
static struct plat_serial8250_port orion_uart_data[] = {
{
- .mapbase = UART0_BASE,
- .membase = (char *)UART0_BASE,
+ .mapbase = UART0_PHYS_BASE,
+ .membase = (char *)UART0_VIRT_BASE,
.irq = IRQ_ORION_UART0,
.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
.iotype = UPIO_MEM,
@@ -95,8 +95,8 @@ static struct plat_serial8250_port orion_uart_data[] = {
.uartclk = ORION_TCLK,
},
{
- .mapbase = UART1_BASE,
- .membase = (char *)UART1_BASE,
+ .mapbase = UART1_PHYS_BASE,
+ .membase = (char *)UART1_VIRT_BASE,
.irq = IRQ_ORION_UART1,
.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
.iotype = UPIO_MEM,
@@ -122,8 +122,8 @@ static struct platform_device orion_uart = {
static struct resource orion_ehci0_resources[] = {
{
- .start = ORION_USB0_REG_BASE,
- .end = ORION_USB0_REG_BASE + SZ_4K,
+ .start = ORION_USB0_PHYS_BASE,
+ .end = ORION_USB0_PHYS_BASE + SZ_4K,
.flags = IORESOURCE_MEM,
},
{
@@ -135,8 +135,8 @@ static struct resource orion_ehci0_resources[] = {
static struct resource orion_ehci1_resources[] = {
{
- .start = ORION_USB1_REG_BASE,
- .end = ORION_USB1_REG_BASE + SZ_4K,
+ .start = ORION_USB1_PHYS_BASE,
+ .end = ORION_USB1_PHYS_BASE + SZ_4K,
.flags = IORESOURCE_MEM,
},
{
@@ -177,8 +177,8 @@ static struct platform_device orion_ehci1 = {
static struct resource orion_eth_shared_resources[] = {
{
- .start = ORION_ETH_REG_BASE,
- .end = ORION_ETH_REG_BASE + 0xffff,
+ .start = ORION_ETH_PHYS_BASE,
+ .end = ORION_ETH_PHYS_BASE + 0xffff,
.flags = IORESOURCE_MEM,
},
};
@@ -227,8 +227,8 @@ static struct mv64xxx_i2c_pdata orion_i2c_pdata = {
static struct resource orion_i2c_resources[] = {
{
.name = "i2c base",
- .start = I2C_BASE,
- .end = I2C_BASE + 0x20 -1,
+ .start = I2C_PHYS_BASE,
+ .end = I2C_PHYS_BASE + 0x20 -1,
.flags = IORESOURCE_MEM,
},
{
@@ -250,6 +250,40 @@ static struct platform_device orion_i2c = {
};
/*****************************************************************************
+ * Sata port
+ ****************************************************************************/
+static struct resource orion_sata_resources[] = {
+ {
+ .name = "sata base",
+ .start = ORION_SATA_PHYS_BASE,
+ .end = ORION_SATA_PHYS_BASE + 0x5000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "sata irq",
+ .start = IRQ_ORION_SATA,
+ .end = IRQ_ORION_SATA,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device orion_sata = {
+ .name = "sata_mv",
+ .id = 0,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(orion_sata_resources),
+ .resource = orion_sata_resources,
+};
+
+void __init orion_sata_init(struct mv_sata_platform_data *sata_data)
+{
+ orion_sata.dev.platform_data = sata_data;
+ platform_device_register(&orion_sata);
+}
+
+/*****************************************************************************
* General
****************************************************************************/
diff --git a/arch/arm/mach-orion/common.h b/arch/arm/mach-orion/common.h
index 06c10c06f03..10154ec885d 100644
--- a/arch/arm/mach-orion/common.h
+++ b/arch/arm/mach-orion/common.h
@@ -75,4 +75,12 @@ struct mv643xx_eth_platform_data;
void __init orion_eth_init(struct mv643xx_eth_platform_data *eth_data);
+/*
+ * Orion Sata platform_data, used by machine-setup
+ */
+
+struct mv_sata_platform_data;
+
+void __init orion_sata_init(struct mv_sata_platform_data *sata_data);
+
#endif /* __ARCH_ORION_COMMON_H__ */
diff --git a/arch/arm/mach-orion/db88f5281-setup.c b/arch/arm/mach-orion/db88f5281-setup.c
index cb2a95ce5b5..5ef44e1a2d3 100644
--- a/arch/arm/mach-orion/db88f5281-setup.c
+++ b/arch/arm/mach-orion/db88f5281-setup.c
@@ -354,8 +354,8 @@ static void __init db88f5281_init(void)
MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
/* Maintainer: Tzachi Perelstein <tzachi@marvell.com> */
- .phys_io = ORION_REGS_BASE,
- .io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xfffc,
+ .phys_io = ORION_REGS_PHYS_BASE,
+ .io_pg_offst = ((ORION_REGS_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.init_machine = db88f5281_init,
.map_io = orion_map_io,
diff --git a/arch/arm/mach-orion/dns323-setup.c b/arch/arm/mach-orion/dns323-setup.c
index c8a806f249c..02b280c2482 100644
--- a/arch/arm/mach-orion/dns323-setup.c
+++ b/arch/arm/mach-orion/dns323-setup.c
@@ -259,8 +259,8 @@ static void __init dns323_init(void)
*
* Open a special address decode windows for the PCIE WA.
*/
- orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE);
- orion_write(ORION_REGS_BASE | 0x20070,
+ orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+ orion_write(ORION_REGS_VIRT_BASE | 0x20070,
(0x7941 | (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
/* set MPP to 0 as D-Link's 2.6.12.6 kernel did */
@@ -312,8 +312,8 @@ static void __init dns323_init(void)
/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
MACHINE_START(DNS323, "D-Link DNS-323")
/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
- .phys_io = ORION_REGS_BASE,
- .io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC,
+ .phys_io = ORION_REGS_PHYS_BASE,
+ .io_pg_offst = ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = dns323_init,
.map_io = orion_map_io,
diff --git a/arch/arm/mach-orion/kurobox_pro-setup.c b/arch/arm/mach-orion/kurobox_pro-setup.c
index 2d812ed6b5c..6817aca4aa2 100644
--- a/arch/arm/mach-orion/kurobox_pro-setup.c
+++ b/arch/arm/mach-orion/kurobox_pro-setup.c
@@ -17,6 +17,7 @@
#include <linux/mtd/nand.h>
#include <linux/mv643xx_eth.h>
#include <linux/i2c.h>
+#include <linux/ata_platform.h>
#include <asm/mach-types.h>
#include <asm/gpio.h>
#include <asm/mach/arch.h>
@@ -167,6 +168,13 @@ static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
};
/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct mv_sata_platform_data kurobox_pro_sata_data = {
+ .n_ports = 2,
+};
+
+/*****************************************************************************
* General Setup
****************************************************************************/
@@ -192,8 +200,8 @@ static void __init kurobox_pro_init(void)
/*
* Open a special address decode windows for the PCIE WA.
*/
- orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE);
- orion_write(ORION_REGS_BASE | 0x20070, (0x7941 |
+ orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+ orion_write(ORION_REGS_VIRT_BASE | 0x20070, (0x7941 |
(((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
/*
@@ -220,12 +228,13 @@ static void __init kurobox_pro_init(void)
platform_add_devices(kurobox_pro_devices, ARRAY_SIZE(kurobox_pro_devices));
i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1);
orion_eth_init(&kurobox_pro_eth_data);
+ orion_sata_init(&kurobox_pro_sata_data);
}
MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
- .phys_io = ORION_REGS_BASE,
- .io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC,
+ .phys_io = ORION_REGS_PHYS_BASE,
+ .io_pg_offst = ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = kurobox_pro_init,
.map_io = orion_map_io,
diff --git a/arch/arm/mach-orion/pci.c b/arch/arm/mach-orion/pci.c
index 0498d7c69b3..b109bb46681 100644
--- a/arch/arm/mach-orion/pci.c
+++ b/arch/arm/mach-orion/pci.c
@@ -156,7 +156,7 @@ static int orion_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
orion_pcie_id(&dev, &rev);
if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) {
/* extended register space */
- pcie_addr = ORION_PCIE_WA_BASE;
+ pcie_addr = ORION_PCIE_WA_VIRT_BASE;
pcie_addr |= PCIE_CONF_BUS(bus->number) |
PCIE_CONF_DEV(PCI_SLOT(devfn)) |
PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
@@ -241,7 +241,7 @@ static int orion_pcie_setup(struct pci_sys_data *sys)
*/
res[0].name = "PCI-EX I/O Space";
res[0].flags = IORESOURCE_IO;
- res[0].start = ORION_PCIE_IO_REMAP;
+ res[0].start = ORION_PCIE_IO_BUS_BASE;
res[0].end = res[0].start + ORION_PCIE_IO_SIZE - 1;
if (request_resource(&ioport_resource, &res[0]))
panic("Request PCIE IO resource failed\n");
@@ -252,7 +252,7 @@ static int orion_pcie_setup(struct pci_sys_data *sys)
*/
res[1].name = "PCI-EX Memory Space";
res[1].flags = IORESOURCE_MEM;
- res[1].start = ORION_PCIE_MEM_BASE;
+ res[1].start = ORION_PCIE_MEM_PHYS_BASE;
res[1].end = res[1].start + ORION_PCIE_MEM_SIZE - 1;
if (request_resource(&iomem_resource, &res[1]))
panic("Request PCIE Memory resource failed\n");
@@ -477,7 +477,7 @@ static int orion_pci_setup(struct pci_sys_data *sys)
*/
res[0].name = "PCI I/O Space";
res[0].flags = IORESOURCE_IO;
- res[0].start = ORION_PCI_IO_REMAP;
+ res[0].start = ORION_PCI_IO_BUS_BASE;
res[0].end = res[0].start + ORION_PCI_IO_SIZE - 1;
if (request_resource(&ioport_resource, &res[0]))
panic("Request PCI IO resource failed\n");
@@ -488,7 +488,7 @@ static int orion_pci_setup(struct pci_sys_data *sys)
*/
res[1].name = "PCI Memory Space";
res[1].flags = IORESOURCE_MEM;
- res[1].start = ORION_PCI_MEM_BASE;
+ res[1].start = ORION_PCI_MEM_PHYS_BASE;
res[1].end = res[1].start + ORION_PCI_MEM_SIZE - 1;
if (request_resource(&iomem_resource, &res[1]))
panic("Request PCI Memory resource failed\n");
diff --git a/arch/arm/mach-orion/rd88f5182-setup.c b/arch/arm/mach-orion/rd88f5182-setup.c
index 026d74325d0..e851b8ca5ac 100644
--- a/arch/arm/mach-orion/rd88f5182-setup.c
+++ b/arch/arm/mach-orion/rd88f5182-setup.c
@@ -17,6 +17,7 @@
#include <linux/irq.h>
#include <linux/mtd/physmap.h>
#include <linux/mv643xx_eth.h>
+#include <linux/ata_platform.h>
#include <linux/i2c.h>
#include <asm/mach-types.h>
#include <asm/gpio.h>
@@ -230,6 +231,13 @@ static struct i2c_board_info __initdata rd88f5182_i2c_rtc = {
};
/*****************************************************************************
+ * Sata
+ ****************************************************************************/
+static struct mv_sata_platform_data rd88f5182_sata_data = {
+ .n_ports = 2,
+};
+
+/*****************************************************************************
* General Setup
****************************************************************************/
@@ -255,8 +263,8 @@ static void __init rd88f5182_init(void)
/*
* Open a special address decode windows for the PCIE WA.
*/
- orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE);
- orion_write(ORION_REGS_BASE | 0x20070, (0x7941 |
+ orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+ orion_write(ORION_REGS_VIRT_BASE | 0x20070, (0x7941 |
(((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
/*
@@ -292,12 +300,13 @@ static void __init rd88f5182_init(void)
platform_add_devices(rd88f5182_devices, ARRAY_SIZE(rd88f5182_devices));
i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1);
orion_eth_init(&rd88f5182_eth_data);
+ orion_sata_init(&rd88f5182_sata_data);
}
MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
- .phys_io = ORION_REGS_BASE,
- .io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC,
+ .phys_io = ORION_REGS_PHYS_BASE,
+ .io_pg_offst = ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = rd88f5182_init,
.map_io = orion_map_io,
diff --git a/arch/arm/mach-orion/ts209-setup.c b/arch/arm/mach-orion/ts209-setup.c
index e3e930efd15..306dbcd1e37 100644
--- a/arch/arm/mach-orion/ts209-setup.c
+++ b/arch/arm/mach-orion/ts209-setup.c
@@ -21,6 +21,7 @@
#include <linux/input.h>
#include <linux/i2c.h>
#include <linux/serial_reg.h>
+#include <linux/ata_platform.h>
#include <asm/mach-types.h>
#include <asm/gpio.h>
#include <asm/mach/arch.h>
@@ -232,6 +233,14 @@ static struct platform_device qnap_ts209_button_device = {
};
/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct mv_sata_platform_data qnap_ts209_sata_data = {
+ .n_ports = 2,
+};
+
+/*****************************************************************************
+
* General Setup
****************************************************************************/
@@ -244,7 +253,7 @@ static struct platform_device *qnap_ts209_devices[] __initdata = {
* QNAP TS-[12]09 specific power off method via UART1-attached PIC
*/
-#define UART1_REG(x) (UART1_BASE + ((UART_##x) << 2))
+#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2))
static void qnap_ts209_power_off(void)
{
@@ -282,8 +291,8 @@ static void __init qnap_ts209_init(void)
/*
* Open a special address decode windows for the PCIE WA.
*/
- orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE);
- orion_write(ORION_REGS_BASE | 0x20070, (0x7941 |
+ orion_write(ORION_REGS_VIRT_BASE | 0x20074, ORION_PCIE_WA_PHYS_BASE);
+ orion_write(ORION_REGS_VIRT_BASE | 0x20070, (0x7941 |
(((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
/*
@@ -321,12 +330,13 @@ static void __init qnap_ts209_init(void)
ARRAY_SIZE(qnap_ts209_devices));
i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1);
orion_eth_init(&qnap_ts209_eth_data);
+ orion_sata_init(&qnap_ts209_sata_data);
}
MACHINE_START(TS209, "QNAP TS-109/TS-209")
/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
- .phys_io = ORION_REGS_BASE,
- .io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC,
+ .phys_io = ORION_REGS_PHYS_BASE,
+ .io_pg_offst = ((ORION_REGS_VIRT_BASE) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
.init_machine = qnap_ts209_init,
.map_io = orion_map_io,
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 8604938bd94..6e0c4f5b5ae 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -3,7 +3,8 @@
#
# Common support (must be linked before board specific support)
-obj-y += clock.o devices.o generic.o irq.o dma.o time.o
+obj-y += clock.o devices.o generic.o irq.o dma.o \
+ time.o gpio.o
obj-$(CONFIG_PXA25x) += pxa25x.o
obj-$(CONFIG_PXA27x) += pxa27x.o
obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o smemc.o
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 76970598f55..80721c610d4 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -32,7 +32,6 @@
#include <asm/mach/map.h>
#include <asm/arch/pxa-regs.h>
-#include <asm/arch/gpio.h>
#include "generic.h"
@@ -67,97 +66,6 @@ unsigned int get_memclk_frequency_10khz(void)
EXPORT_SYMBOL(get_memclk_frequency_10khz);
/*
- * Handy function to set GPIO alternate functions
- */
-int pxa_last_gpio;
-
-int pxa_gpio_mode(int gpio_mode)
-{
- unsigned long flags;
- int gpio = gpio_mode & GPIO_MD_MASK_NR;
- int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
- int gafr;
-
- if (gpio > pxa_last_gpio)
- return -EINVAL;
-
- local_irq_save(flags);
- if (gpio_mode & GPIO_DFLT_LOW)
- GPCR(gpio) = GPIO_bit(gpio);
- else if (gpio_mode & GPIO_DFLT_HIGH)
- GPSR(gpio) = GPIO_bit(gpio);
- if (gpio_mode & GPIO_MD_MASK_DIR)
- GPDR(gpio) |= GPIO_bit(gpio);
- else
- GPDR(gpio) &= ~GPIO_bit(gpio);
- gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
- GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
- local_irq_restore(flags);
-
- return 0;
-}
-
-EXPORT_SYMBOL(pxa_gpio_mode);
-
-int gpio_direction_input(unsigned gpio)
-{
- unsigned long flags;
- u32 mask;
-
- if (gpio > pxa_last_gpio)
- return -EINVAL;
-
- mask = GPIO_bit(gpio);
- local_irq_save(flags);
- GPDR(gpio) &= ~mask;
- local_irq_restore(flags);
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_input);
-
-int gpio_direction_output(unsigned gpio, int value)
-{
- unsigned long flags;
- u32 mask;
-
- if (gpio > pxa_last_gpio)
- return -EINVAL;
-
- mask = GPIO_bit(gpio);
- local_irq_save(flags);
- if (value)
- GPSR(gpio) = mask;
- else
- GPCR(gpio) = mask;
- GPDR(gpio) |= mask;
- local_irq_restore(flags);
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_output);
-
-/*
- * Return GPIO level
- */
-int pxa_gpio_get_value(unsigned gpio)
-{
- return __gpio_get_value(gpio);
-}
-
-EXPORT_SYMBOL(pxa_gpio_get_value);
-
-/*
- * Set output GPIO level
- */
-void pxa_gpio_set_value(unsigned gpio, int value)
-{
- __gpio_set_value(gpio, value);
-}
-
-EXPORT_SYMBOL(pxa_gpio_set_value);
-
-/*
* Routine to safely enable or disable a clock in the CKEN
*/
void __pxa_set_cken(int clock, int enable)
@@ -172,7 +80,6 @@ void __pxa_set_cken(int clock, int enable)
local_irq_restore(flags);
}
-
EXPORT_SYMBOL(__pxa_set_cken);
/*
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index 1a16ad3ecee..b3d10b0e52a 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -16,6 +16,7 @@ extern void __init pxa_init_irq_low(void);
extern void __init pxa_init_irq_high(void);
extern void __init pxa_init_irq_gpio(int gpio_nr);
extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
+extern void __init pxa_init_gpio(int gpio_nr);
extern void __init pxa25x_init_irq(void);
extern void __init pxa27x_init_irq(void);
extern void __init pxa3xx_init_irq(void);
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
new file mode 100644
index 00000000000..8638dd7dd07
--- /dev/null
+++ b/arch/arm/mach-pxa/gpio.c
@@ -0,0 +1,197 @@
+/*
+ * linux/arch/arm/mach-pxa/gpio.c
+ *
+ * Generic PXA GPIO handling
+ *
+ * Author: Nicolas Pitre
+ * Created: Jun 15, 2001
+ * Copyright: MontaVista Software Inc.
+ *
+ * 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/init.h>
+#include <linux/module.h>
+
+#include <asm/gpio.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/arch/pxa-regs.h>
+
+#include "generic.h"
+
+
+struct pxa_gpio_chip {
+ struct gpio_chip chip;
+ void __iomem *regbase;
+};
+
+int pxa_last_gpio;
+
+/*
+ * Configure pins for GPIO or other functions
+ */
+int pxa_gpio_mode(int gpio_mode)
+{
+ unsigned long flags;
+ int gpio = gpio_mode & GPIO_MD_MASK_NR;
+ int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
+ int gafr;
+
+ if (gpio > pxa_last_gpio)
+ return -EINVAL;
+
+ local_irq_save(flags);
+ if (gpio_mode & GPIO_DFLT_LOW)
+ GPCR(gpio) = GPIO_bit(gpio);
+ else if (gpio_mode & GPIO_DFLT_HIGH)
+ GPSR(gpio) = GPIO_bit(gpio);
+ if (gpio_mode & GPIO_MD_MASK_DIR)
+ GPDR(gpio) |= GPIO_bit(gpio);
+ else
+ GPDR(gpio) &= ~GPIO_bit(gpio);
+ gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
+ GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
+ local_irq_restore(flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(pxa_gpio_mode);
+
+static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ unsigned long flags;
+ u32 mask = 1 << offset;
+ u32 value;
+ struct pxa_gpio_chip *pxa;
+ void __iomem *gpdr;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+ gpdr = pxa->regbase + GPDR_OFFSET;
+ local_irq_save(flags);
+ value = __raw_readl(gpdr);
+ value &= ~mask;
+ __raw_writel(value, gpdr);
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static int pxa_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ unsigned long flags;
+ u32 mask = 1 << offset;
+ u32 tmp;
+ struct pxa_gpio_chip *pxa;
+ void __iomem *gpdr;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+ __raw_writel(mask,
+ pxa->regbase + (value ? GPSR_OFFSET : GPCR_OFFSET));
+ gpdr = pxa->regbase + GPDR_OFFSET;
+ local_irq_save(flags);
+ tmp = __raw_readl(gpdr);
+ tmp |= mask;
+ __raw_writel(tmp, gpdr);
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+/*
+ * Return GPIO level
+ */
+static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ u32 mask = 1 << offset;
+ struct pxa_gpio_chip *pxa;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+ return __raw_readl(pxa->regbase + GPLR_OFFSET) & mask;
+}
+
+/*
+ * Set output GPIO level
+ */
+static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ u32 mask = 1 << offset;
+ struct pxa_gpio_chip *pxa;
+
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+
+ if (value)
+ __raw_writel(mask, pxa->regbase + GPSR_OFFSET);
+ else
+ __raw_writel(mask, pxa->regbase + GPCR_OFFSET);
+}
+
+static struct pxa_gpio_chip pxa_gpio_chip[] = {
+ [0] = {
+ .regbase = GPIO0_BASE,
+ .chip = {
+ .label = "gpio-0",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 0,
+ .ngpio = 32,
+ },
+ },
+ [1] = {
+ .regbase = GPIO1_BASE,
+ .chip = {
+ .label = "gpio-1",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 32,
+ .ngpio = 32,
+ },
+ },
+ [2] = {
+ .regbase = GPIO2_BASE,
+ .chip = {
+ .label = "gpio-2",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 64,
+ .ngpio = 32, /* 21 for PXA25x */
+ },
+ },
+#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ [3] = {
+ .regbase = GPIO3_BASE,
+ .chip = {
+ .label = "gpio-3",
+ .direction_input = pxa_gpio_direction_input,
+ .direction_output = pxa_gpio_direction_output,
+ .get = pxa_gpio_get,
+ .set = pxa_gpio_set,
+ .base = 96,
+ .ngpio = 32,
+ },
+ },
+#endif
+};
+
+void __init pxa_init_gpio(int gpio_nr)
+{
+ int i;
+
+ /* add a GPIO chip for each register bank.
+ * the last PXA25x register only contains 21 GPIOs
+ */
+ for (i = 0; i < gpio_nr; i += 32) {
+ if (i+32 > gpio_nr)
+ pxa_gpio_chip[i/32].chip.ngpio = gpio_nr - i;
+ gpiochip_add(&pxa_gpio_chip[i/32].chip);
+ }
+}
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 5a1d5eef10a..36c6a68beca 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -311,6 +311,8 @@ void __init pxa_init_irq_gpio(int gpio_nr)
/* Install handler for GPIO>=2 edge detect interrupts */
set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
+
+ pxa_init_gpio(gpio_nr);
}
void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index e47e67c11af..7cd9ef8deb0 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -266,8 +266,6 @@ static void pxa3xx_cpu_standby(unsigned int pwrmode)
AD2D0ER = 0;
AD2D1ER = 0;
-
- printk("PM: AD2D0SR=%08x ASCR=%08x\n", AD2D0SR, ASCR);
}
/*
@@ -515,6 +513,14 @@ static int __init pxa3xx_init(void)
int i, ret = 0;
if (cpu_is_pxa3xx()) {
+ /*
+ * clear RDH bit every time after reset
+ *
+ * Note: the last 3 bits DxS are write-1-to-clear so carefully
+ * preserve them here in case they will be referenced later
+ */
+ ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
+
clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
if ((ret = pxa_init_dma(32)))
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 9b26fa5edad..f99112d50b4 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -21,6 +21,8 @@
#include <linux/mmc/host.h>
#include <linux/pm.h>
#include <linux/delay.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
#include <asm/setup.h>
#include <asm/memory.h>
@@ -246,6 +248,46 @@ static struct platform_device tosakbd_device = {
.id = -1,
};
+static struct gpio_keys_button tosa_gpio_keys[] = {
+ {
+ .type = EV_PWR,
+ .code = KEY_SUSPEND,
+ .gpio = TOSA_GPIO_ON_KEY,
+ .desc = "On key",
+ .wakeup = 1,
+ .active_low = 1,
+ },
+ {
+ .type = EV_KEY,
+ .code = TOSA_KEY_RECORD,
+ .gpio = TOSA_GPIO_RECORD_BTN,
+ .desc = "Record Button",
+ .wakeup = 1,
+ .active_low = 1,
+ },
+ {
+ .type = EV_KEY,
+ .code = TOSA_KEY_SYNC,
+ .gpio = TOSA_GPIO_SYNC,
+ .desc = "Sync Button",
+ .wakeup = 1,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_keys_platform_data tosa_gpio_keys_platform_data = {
+ .buttons = tosa_gpio_keys,
+ .nbuttons = ARRAY_SIZE(tosa_gpio_keys),
+};
+
+static struct platform_device tosa_gpio_keys_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &tosa_gpio_keys_platform_data,
+ },
+};
+
/*
* Tosa LEDs
*/
@@ -258,6 +300,7 @@ static struct platform_device *devices[] __initdata = {
&tosascoop_device,
&tosascoop_jc_device,
&tosakbd_device,
+ &tosa_gpio_keys_device,
&tosaled_device,
};
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index a454451c97c..eca558c6bf5 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -17,7 +17,7 @@
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/serial_8250.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <asm/elf.h>
#include <asm/io.h>
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index c0ad7c0fbae..ec00f26bffa 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -239,7 +239,7 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
* Reserve the bootmem bitmap for this node.
*/
reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT,
- boot_pages << PAGE_SHIFT);
+ boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
#ifdef CONFIG_BLK_DEV_INITRD
/*
@@ -247,7 +247,7 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi)
*/
if (node == initrd_node) {
reserve_bootmem_node(pgdat, phys_initrd_start,
- phys_initrd_size);
+ phys_initrd_size, BOOTMEM_DEFAULT);
initrd_start = __phys_to_virt(phys_initrd_start);
initrd_end = initrd_start + phys_initrd_size;
}
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 75952779ce1..303a7ff6bfd 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -162,7 +162,7 @@ static void unmap_area_sections(unsigned long virt, unsigned long size)
* Free the page table, if there was one.
*/
if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
- pte_free_kernel(pmd_page_vaddr(pmd));
+ pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
}
addr += PGDIR_SIZE;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e5d61ee3d4a..d41a75ed3dc 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -605,9 +605,11 @@ void __init reserve_node_zero(pg_data_t *pgdat)
* Note that this can only be in node 0.
*/
#ifdef CONFIG_XIP_KERNEL
- reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start);
+ reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start,
+ BOOTMEM_DEFAULT);
#else
- reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
+ reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext,
+ BOOTMEM_DEFAULT);
#endif
/*
@@ -615,7 +617,7 @@ void __init reserve_node_zero(pg_data_t *pgdat)
* and can only be in node 0.
*/
reserve_bootmem_node(pgdat, __pa(swapper_pg_dir),
- PTRS_PER_PGD * sizeof(pgd_t));
+ PTRS_PER_PGD * sizeof(pgd_t), BOOTMEM_DEFAULT);
/*
* Hmm... This should go elsewhere, but we really really need to
@@ -638,8 +640,10 @@ void __init reserve_node_zero(pg_data_t *pgdat)
/* H1940 and RX3715 need to reserve this for suspend */
if (machine_is_h1940() || machine_is_rx3715()) {
- reserve_bootmem_node(pgdat, 0x30003000, 0x1000);
- reserve_bootmem_node(pgdat, 0x30081000, 0x1000);
+ reserve_bootmem_node(pgdat, 0x30003000, 0x1000,
+ BOOTMEM_DEFAULT);
+ reserve_bootmem_node(pgdat, 0x30081000, 0x1000,
+ BOOTMEM_DEFAULT);
}
#ifdef CONFIG_SA1111
@@ -650,7 +654,8 @@ void __init reserve_node_zero(pg_data_t *pgdat)
res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
#endif
if (res_size)
- reserve_bootmem_node(pgdat, PHYS_OFFSET, res_size);
+ reserve_bootmem_node(pgdat, PHYS_OFFSET, res_size,
+ BOOTMEM_DEFAULT);
}
/*
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 8cd3a60954f..63c62fdea52 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -27,9 +27,11 @@ void __init reserve_node_zero(pg_data_t *pgdat)
* Note that this can only be in node 0.
*/
#ifdef CONFIG_XIP_KERNEL
- reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start);
+ reserve_bootmem_node(pgdat, __pa(&__data_start), &_end - &__data_start,
+ BOOTMEM_DEFAULT);
#else
- reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
+ reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext,
+ BOOTMEM_DEFAULT);
#endif
/*
@@ -37,7 +39,8 @@ void __init reserve_node_zero(pg_data_t *pgdat)
* some architectures which the DRAM is the exception vector to trap,
* alloc_page breaks with error, although it is not NULL, but "0."
*/
- reserve_bootmem_node(pgdat, CONFIG_VECTORS_BASE, PAGE_SIZE);
+ reserve_bootmem_node(pgdat, CONFIG_VECTORS_BASE, PAGE_SIZE,
+ BOOTMEM_DEFAULT);
}
/*
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index 50b9aed6000..500c9610ab3 100644
--- a/arch/arm/mm/pgd.c
+++ b/arch/arm/mm/pgd.c
@@ -65,14 +65,14 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
return new_pgd;
no_pte:
- pmd_free(new_pmd);
+ pmd_free(mm, new_pmd);
no_pmd:
free_pages((unsigned long)new_pgd, 2);
no_pgd:
return NULL;
}
-void free_pgd_slow(pgd_t *pgd)
+void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd)
{
pmd_t *pmd;
struct page *pte;
@@ -94,8 +94,8 @@ void free_pgd_slow(pgd_t *pgd)
pmd_clear(pmd);
dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
pte_lock_deinit(pte);
- pte_free(pte);
- pmd_free(pmd);
+ pte_free(mm, pte);
+ pmd_free(mm, pmd);
free:
free_pages((unsigned long) pgd, 2);
}
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 2549129aabc..ce17df31b84 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
+obj-$(CONFIG_I2C_OMAP) += i2c.o
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index dcbba07cf98..a46676db811 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -6,7 +6,7 @@
* DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
* Graphics DMA and LCD DMA graphics tranformations
* by Imre Deak <imre.deak@nokia.com>
- * OMAP2 support Copyright (C) 2004-2005 Texas Instruments, Inc.
+ * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
* Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com>
* Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
*
@@ -33,12 +33,14 @@
#include <asm/arch/tc.h>
-#define DEBUG_PRINTS
-#undef DEBUG_PRINTS
-#ifdef DEBUG_PRINTS
-#define debug_printk(x) printk x
-#else
-#define debug_printk(x)
+#undef DEBUG
+
+#ifndef CONFIG_ARCH_OMAP1
+enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
+ DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED
+};
+
+enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
#endif
#define OMAP_DMA_ACTIVE 0x01
@@ -57,9 +59,66 @@ struct omap_dma_lch {
const char *dev_name;
void (* callback)(int lch, u16 ch_status, void *data);
void *data;
+
+#ifndef CONFIG_ARCH_OMAP1
+ /* required for Dynamic chaining */
+ int prev_linked_ch;
+ int next_linked_ch;
+ int state;
+ int chain_id;
+
+ int status;
+#endif
long flags;
};
+#ifndef CONFIG_ARCH_OMAP1
+struct dma_link_info {
+ int *linked_dmach_q;
+ int no_of_lchs_linked;
+
+ int q_count;
+ int q_tail;
+ int q_head;
+
+ int chain_state;
+ int chain_mode;
+
+};
+
+static struct dma_link_info dma_linked_lch[OMAP_LOGICAL_DMA_CH_COUNT];
+
+/* Chain handling macros */
+#define OMAP_DMA_CHAIN_QINIT(chain_id) \
+ do { \
+ dma_linked_lch[chain_id].q_head = \
+ dma_linked_lch[chain_id].q_tail = \
+ dma_linked_lch[chain_id].q_count = 0; \
+ } while (0)
+#define OMAP_DMA_CHAIN_QFULL(chain_id) \
+ (dma_linked_lch[chain_id].no_of_lchs_linked == \
+ dma_linked_lch[chain_id].q_count)
+#define OMAP_DMA_CHAIN_QLAST(chain_id) \
+ do { \
+ ((dma_linked_lch[chain_id].no_of_lchs_linked-1) == \
+ dma_linked_lch[chain_id].q_count) \
+ } while (0)
+#define OMAP_DMA_CHAIN_QEMPTY(chain_id) \
+ (0 == dma_linked_lch[chain_id].q_count)
+#define __OMAP_DMA_CHAIN_INCQ(end) \
+ ((end) = ((end)+1) % dma_linked_lch[chain_id].no_of_lchs_linked)
+#define OMAP_DMA_CHAIN_INCQHEAD(chain_id) \
+ do { \
+ __OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_head); \
+ dma_linked_lch[chain_id].q_count--; \
+ } while (0)
+
+#define OMAP_DMA_CHAIN_INCQTAIL(chain_id) \
+ do { \
+ __OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_tail); \
+ dma_linked_lch[chain_id].q_count++; \
+ } while (0)
+#endif
static int dma_chan_count;
static spinlock_t dma_chan_lock;
@@ -73,6 +132,10 @@ static const u8 omap1_dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = {
INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD
};
+static inline void disable_lnk(int lch);
+static void omap_disable_channel_irq(int lch);
+static inline void omap_enable_channel_irq(int lch);
+
#define REVISIT_24XX() printk(KERN_ERR "FIXME: no %s on 24xx\n", \
__FUNCTION__);
@@ -148,7 +211,7 @@ void omap_set_dma_priority(int lch, int dst_port, int priority)
omap_writel(l, reg);
}
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
if (priority)
OMAP_DMA_CCR_REG(lch) |= (1 << 6);
else
@@ -173,7 +236,7 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
OMAP1_DMA_CCR2_REG(lch) |= 1 << 2;
}
- if (cpu_is_omap24xx() && dma_trigger) {
+ if (cpu_class_is_omap2() && dma_trigger) {
u32 val = OMAP_DMA_CCR_REG(lch);
val &= ~(3 << 19);
@@ -213,7 +276,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
BUG_ON(omap_dma_in_1510_mode());
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
REVISIT_24XX();
return;
}
@@ -245,7 +308,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
{
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
OMAP_DMA_CSDP_REG(lch) &= ~(0x3 << 16);
OMAP_DMA_CSDP_REG(lch) |= (mode << 16);
}
@@ -269,7 +332,7 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
OMAP1_DMA_CSSA_L_REG(lch) = src_start;
}
- if (cpu_is_omap24xx())
+ if (cpu_class_is_omap2())
OMAP2_DMA_CSSA_REG(lch) = src_start;
OMAP_DMA_CSEI_REG(lch) = src_ei;
@@ -289,11 +352,14 @@ void omap_set_dma_params(int lch, struct omap_dma_channel_params * params)
omap_set_dma_dest_params(lch, params->dst_port,
params->dst_amode, params->dst_start,
params->dst_ei, params->dst_fi);
+ if (params->read_prio || params->write_prio)
+ omap_dma_set_prio_lch(lch, params->read_prio,
+ params->write_prio);
}
void omap_set_dma_src_index(int lch, int eidx, int fidx)
{
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
REVISIT_24XX();
return;
}
@@ -317,13 +383,13 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
case OMAP_DMA_DATA_BURST_DIS:
break;
case OMAP_DMA_DATA_BURST_4:
- if (cpu_is_omap24xx())
+ if (cpu_class_is_omap2())
burst = 0x1;
else
burst = 0x2;
break;
case OMAP_DMA_DATA_BURST_8:
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
burst = 0x2;
break;
}
@@ -332,7 +398,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
* fall through
*/
case OMAP_DMA_DATA_BURST_16:
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
burst = 0x3;
break;
}
@@ -363,7 +429,7 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
OMAP1_DMA_CDSA_L_REG(lch) = dest_start;
}
- if (cpu_is_omap24xx())
+ if (cpu_class_is_omap2())
OMAP2_DMA_CDSA_REG(lch) = dest_start;
OMAP_DMA_CDEI_REG(lch) = dst_ei;
@@ -372,7 +438,7 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
void omap_set_dma_dest_index(int lch, int eidx, int fidx)
{
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
REVISIT_24XX();
return;
}
@@ -396,19 +462,19 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
case OMAP_DMA_DATA_BURST_DIS:
break;
case OMAP_DMA_DATA_BURST_4:
- if (cpu_is_omap24xx())
+ if (cpu_class_is_omap2())
burst = 0x1;
else
burst = 0x2;
break;
case OMAP_DMA_DATA_BURST_8:
- if (cpu_is_omap24xx())
+ if (cpu_class_is_omap2())
burst = 0x2;
else
burst = 0x3;
break;
case OMAP_DMA_DATA_BURST_16:
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
burst = 0x3;
break;
}
@@ -430,7 +496,7 @@ static inline void omap_enable_channel_irq(int lch)
/* Clear CSR */
if (cpu_class_is_omap1())
status = OMAP_DMA_CSR_REG(lch);
- else if (cpu_is_omap24xx())
+ else if (cpu_class_is_omap2())
OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK;
/* Enable some nice interrupts. */
@@ -441,7 +507,7 @@ static inline void omap_enable_channel_irq(int lch)
static void omap_disable_channel_irq(int lch)
{
- if (cpu_is_omap24xx())
+ if (cpu_class_is_omap2())
OMAP_DMA_CICR_REG(lch) = 0;
}
@@ -464,6 +530,12 @@ static inline void enable_lnk(int lch)
if (dma_chan[lch].next_lch != -1)
OMAP_DMA_CLNK_CTRL_REG(lch) =
dma_chan[lch].next_lch | (1 << 15);
+
+#ifndef CONFIG_ARCH_OMAP1
+ if (dma_chan[lch].next_linked_ch != -1)
+ OMAP_DMA_CLNK_CTRL_REG(lch) =
+ dma_chan[lch].next_linked_ch | (1 << 15);
+#endif
}
static inline void disable_lnk(int lch)
@@ -475,7 +547,7 @@ static inline void disable_lnk(int lch)
OMAP_DMA_CLNK_CTRL_REG(lch) |= 1 << 14;
}
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
omap_disable_channel_irq(lch);
/* Clear the ENABLE_LNK bit */
OMAP_DMA_CLNK_CTRL_REG(lch) &= ~(1 << 15);
@@ -488,7 +560,7 @@ static inline void omap2_enable_irq_lch(int lch)
{
u32 val;
- if (!cpu_is_omap24xx())
+ if (!cpu_class_is_omap2())
return;
val = omap_readl(OMAP_DMA4_IRQENABLE_L0);
@@ -522,7 +594,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
if (cpu_class_is_omap1())
clear_lch_regs(free_ch);
- if (cpu_is_omap24xx())
+ if (cpu_class_is_omap2())
omap_clear_dma(free_ch);
spin_unlock_irqrestore(&dma_chan_lock, flags);
@@ -530,11 +602,14 @@ int omap_request_dma(int dev_id, const char *dev_name,
chan->dev_name = dev_name;
chan->callback = callback;
chan->data = data;
+#ifndef CONFIG_ARCH_OMAP1
+ chan->chain_id = -1;
+#endif
chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
if (cpu_class_is_omap1())
chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ;
- else if (cpu_is_omap24xx())
+ else if (cpu_class_is_omap2())
chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ |
OMAP2_DMA_TRANS_ERR_IRQ;
@@ -551,7 +626,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
OMAP_DMA_CCR_REG(free_ch) = dev_id;
}
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
omap2_enable_irq_lch(free_ch);
omap_enable_channel_irq(free_ch);
@@ -588,7 +663,7 @@ void omap_free_dma(int lch)
OMAP_DMA_CCR_REG(lch) = 0;
}
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
u32 val;
/* Disable interrupts */
val = omap_readl(OMAP_DMA4_IRQENABLE_L0);
@@ -608,6 +683,67 @@ void omap_free_dma(int lch)
}
}
+/**
+ * @brief omap_dma_set_global_params : Set global priority settings for dma
+ *
+ * @param arb_rate
+ * @param max_fifo_depth
+ * @param tparams - Number of thereads to reserve : DMA_THREAD_RESERVE_NORM
+ * DMA_THREAD_RESERVE_ONET
+ * DMA_THREAD_RESERVE_TWOT
+ * DMA_THREAD_RESERVE_THREET
+ */
+void
+omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
+{
+ u32 reg;
+
+ if (!cpu_class_is_omap2()) {
+ printk(KERN_ERR "FIXME: no %s on 15xx/16xx\n", __FUNCTION__);
+ return;
+ }
+
+ if (arb_rate == 0)
+ arb_rate = 1;
+
+ reg = (arb_rate & 0xff) << 16;
+ reg |= (0xff & max_fifo_depth);
+
+ omap_writel(reg, OMAP_DMA4_GCR_REG);
+}
+EXPORT_SYMBOL(omap_dma_set_global_params);
+
+/**
+ * @brief omap_dma_set_prio_lch : Set channel wise priority settings
+ *
+ * @param lch
+ * @param read_prio - Read priority
+ * @param write_prio - Write priority
+ * Both of the above can be set with one of the following values :
+ * DMA_CH_PRIO_HIGH/DMA_CH_PRIO_LOW
+ */
+int
+omap_dma_set_prio_lch(int lch, unsigned char read_prio,
+ unsigned char write_prio)
+{
+ u32 w;
+
+ if (unlikely((lch < 0 || lch >= OMAP_LOGICAL_DMA_CH_COUNT))) {
+ printk(KERN_ERR "Invalid channel id\n");
+ return -EINVAL;
+ }
+ w = OMAP_DMA_CCR_REG(lch);
+ w &= ~((1 << 6) | (1 << 26));
+ if (cpu_is_omap2430() || cpu_is_omap34xx())
+ w |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
+ else
+ w |= ((read_prio & 0x1) << 6);
+
+ OMAP_DMA_CCR_REG(lch) = w;
+ return 0;
+}
+EXPORT_SYMBOL(omap_dma_set_prio_lch);
+
/*
* Clears any DMA state so the DMA engine is ready to restart with new buffers
* through omap_start_dma(). Any buffers in flight are discarded.
@@ -626,9 +762,9 @@ void omap_clear_dma(int lch)
status = OMAP_DMA_CSR_REG(lch);
}
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
int i;
- u32 lch_base = OMAP24XX_DMA_BASE + lch * 0x60 + 0x80;
+ u32 lch_base = OMAP_DMA4_BASE + lch * 0x60 + 0x80;
for (i = 0; i < 0x44; i += 4)
omap_writel(0, lch_base + i);
}
@@ -662,7 +798,7 @@ void omap_start_dma(int lch)
cur_lch = next_lch;
} while (next_lch != -1);
- } else if (cpu_is_omap24xx()) {
+ } else if (cpu_class_is_omap2()) {
/* Errata: Need to write lch even if not using chaining */
OMAP_DMA_CLNK_CTRL_REG(lch) = lch;
}
@@ -753,7 +889,7 @@ dma_addr_t omap_get_dma_src_pos(int lch)
offset = (dma_addr_t) (OMAP1_DMA_CSSA_L_REG(lch) |
(OMAP1_DMA_CSSA_U_REG(lch) << 16));
- if (cpu_is_omap24xx())
+ if (cpu_class_is_omap2())
offset = OMAP_DMA_CSAC_REG(lch);
return offset;
@@ -775,8 +911,8 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
offset = (dma_addr_t) (OMAP1_DMA_CDSA_L_REG(lch) |
(OMAP1_DMA_CDSA_U_REG(lch) << 16));
- if (cpu_is_omap24xx())
- offset = OMAP2_DMA_CDSA_REG(lch);
+ if (cpu_class_is_omap2())
+ offset = OMAP_DMA_CDAC_REG(lch);
return offset;
}
@@ -859,6 +995,605 @@ void omap_dma_unlink_lch (int lch_head, int lch_queue)
dma_chan[lch_head].next_lch = -1;
}
+#ifndef CONFIG_ARCH_OMAP1
+/* Create chain of DMA channesls */
+static void create_dma_lch_chain(int lch_head, int lch_queue)
+{
+ u32 w;
+
+ /* Check if this is the first link in chain */
+ if (dma_chan[lch_head].next_linked_ch == -1) {
+ dma_chan[lch_head].next_linked_ch = lch_queue;
+ dma_chan[lch_head].prev_linked_ch = lch_queue;
+ dma_chan[lch_queue].next_linked_ch = lch_head;
+ dma_chan[lch_queue].prev_linked_ch = lch_head;
+ }
+
+ /* a link exists, link the new channel in circular chain */
+ else {
+ dma_chan[lch_queue].next_linked_ch =
+ dma_chan[lch_head].next_linked_ch;
+ dma_chan[lch_queue].prev_linked_ch = lch_head;
+ dma_chan[lch_head].next_linked_ch = lch_queue;
+ dma_chan[dma_chan[lch_queue].next_linked_ch].prev_linked_ch =
+ lch_queue;
+ }
+
+ w = OMAP_DMA_CLNK_CTRL_REG(lch_head);
+ w &= ~(0x0f);
+ w |= lch_queue;
+ OMAP_DMA_CLNK_CTRL_REG(lch_head) = w;
+
+ w = OMAP_DMA_CLNK_CTRL_REG(lch_queue);
+ w &= ~(0x0f);
+ w |= (dma_chan[lch_queue].next_linked_ch);
+ OMAP_DMA_CLNK_CTRL_REG(lch_queue) = w;
+}
+
+/**
+ * @brief omap_request_dma_chain : Request a chain of DMA channels
+ *
+ * @param dev_id - Device id using the dma channel
+ * @param dev_name - Device name
+ * @param callback - Call back function
+ * @chain_id -
+ * @no_of_chans - Number of channels requested
+ * @chain_mode - Dynamic or static chaining : OMAP_DMA_STATIC_CHAIN
+ * OMAP_DMA_DYNAMIC_CHAIN
+ * @params - Channel parameters
+ *
+ * @return - Succes : 0
+ * Failure: -EINVAL/-ENOMEM
+ */
+int omap_request_dma_chain(int dev_id, const char *dev_name,
+ void (*callback) (int chain_id, u16 ch_status,
+ void *data),
+ int *chain_id, int no_of_chans, int chain_mode,
+ struct omap_dma_channel_params params)
+{
+ int *channels;
+ int i, err;
+
+ /* Is the chain mode valid ? */
+ if (chain_mode != OMAP_DMA_STATIC_CHAIN
+ && chain_mode != OMAP_DMA_DYNAMIC_CHAIN) {
+ printk(KERN_ERR "Invalid chain mode requested\n");
+ return -EINVAL;
+ }
+
+ if (unlikely((no_of_chans < 1
+ || no_of_chans > OMAP_LOGICAL_DMA_CH_COUNT))) {
+ printk(KERN_ERR "Invalid Number of channels requested\n");
+ return -EINVAL;
+ }
+
+ /* Allocate a queue to maintain the status of the channels
+ * in the chain */
+ channels = kmalloc(sizeof(*channels) * no_of_chans, GFP_KERNEL);
+ if (channels == NULL) {
+ printk(KERN_ERR "omap_dma: No memory for channel queue\n");
+ return -ENOMEM;
+ }
+
+ /* request and reserve DMA channels for the chain */
+ for (i = 0; i < no_of_chans; i++) {
+ err = omap_request_dma(dev_id, dev_name,
+ callback, 0, &channels[i]);
+ if (err < 0) {
+ int j;
+ for (j = 0; j < i; j++)
+ omap_free_dma(channels[j]);
+ kfree(channels);
+ printk(KERN_ERR "omap_dma: Request failed %d\n", err);
+ return err;
+ }
+ dma_chan[channels[i]].next_linked_ch = -1;
+ dma_chan[channels[i]].prev_linked_ch = -1;
+ dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
+
+ /*
+ * Allowing client drivers to set common parameters now,
+ * so that later only relevant (src_start, dest_start
+ * and element count) can be set
+ */
+ omap_set_dma_params(channels[i], &params);
+ }
+
+ *chain_id = channels[0];
+ dma_linked_lch[*chain_id].linked_dmach_q = channels;
+ dma_linked_lch[*chain_id].chain_mode = chain_mode;
+ dma_linked_lch[*chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
+ dma_linked_lch[*chain_id].no_of_lchs_linked = no_of_chans;
+
+ for (i = 0; i < no_of_chans; i++)
+ dma_chan[channels[i]].chain_id = *chain_id;
+
+ /* Reset the Queue pointers */
+ OMAP_DMA_CHAIN_QINIT(*chain_id);
+
+ /* Set up the chain */
+ if (no_of_chans == 1)
+ create_dma_lch_chain(channels[0], channels[0]);
+ else {
+ for (i = 0; i < (no_of_chans - 1); i++)
+ create_dma_lch_chain(channels[i], channels[i + 1]);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_request_dma_chain);
+
+/**
+ * @brief omap_modify_dma_chain_param : Modify the chain's params - Modify the
+ * params after setting it. Dont do this while dma is running!!
+ *
+ * @param chain_id - Chained logical channel id.
+ * @param params
+ *
+ * @return - Success : 0
+ * Failure : -EINVAL
+ */
+int omap_modify_dma_chain_params(int chain_id,
+ struct omap_dma_channel_params params)
+{
+ int *channels;
+ u32 i;
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0
+ || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
+ /*
+ * Allowing client drivers to set common parameters now,
+ * so that later only relevant (src_start, dest_start
+ * and element count) can be set
+ */
+ omap_set_dma_params(channels[i], &params);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_modify_dma_chain_params);
+
+/**
+ * @brief omap_free_dma_chain - Free all the logical channels in a chain.
+ *
+ * @param chain_id
+ *
+ * @return - Success : 0
+ * Failure : -EINVAL
+ */
+int omap_free_dma_chain(int chain_id)
+{
+ int *channels;
+ u32 i;
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+ for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
+ dma_chan[channels[i]].next_linked_ch = -1;
+ dma_chan[channels[i]].prev_linked_ch = -1;
+ dma_chan[channels[i]].chain_id = -1;
+ dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
+ omap_free_dma(channels[i]);
+ }
+
+ kfree(channels);
+
+ dma_linked_lch[chain_id].linked_dmach_q = NULL;
+ dma_linked_lch[chain_id].chain_mode = -1;
+ dma_linked_lch[chain_id].chain_state = -1;
+ return (0);
+}
+EXPORT_SYMBOL(omap_free_dma_chain);
+
+/**
+ * @brief omap_dma_chain_status - Check if the chain is in
+ * active / inactive state.
+ * @param chain_id
+ *
+ * @return - Success : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
+ * Failure : -EINVAL
+ */
+int omap_dma_chain_status(int chain_id)
+{
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+ pr_debug("CHAINID=%d, qcnt=%d\n", chain_id,
+ dma_linked_lch[chain_id].q_count);
+
+ if (OMAP_DMA_CHAIN_QEMPTY(chain_id))
+ return OMAP_DMA_CHAIN_INACTIVE;
+ return OMAP_DMA_CHAIN_ACTIVE;
+}
+EXPORT_SYMBOL(omap_dma_chain_status);
+
+/**
+ * @brief omap_dma_chain_a_transfer - Get a free channel from a chain,
+ * set the params and start the transfer.
+ *
+ * @param chain_id
+ * @param src_start - buffer start address
+ * @param dest_start - Dest address
+ * @param elem_count
+ * @param frame_count
+ * @param callbk_data - channel callback parameter data.
+ *
+ * @return - Success : start_dma status
+ * Failure: -EINVAL/-EBUSY
+ */
+int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
+ int elem_count, int frame_count, void *callbk_data)
+{
+ int *channels;
+ u32 w, lch;
+ int start_dma = 0;
+
+ /* if buffer size is less than 1 then there is
+ * no use of starting the chain */
+ if (elem_count < 1) {
+ printk(KERN_ERR "Invalid buffer size\n");
+ return -EINVAL;
+ }
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0
+ || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exist\n");
+ return -EINVAL;
+ }
+
+ /* Check if all the channels in chain are in use */
+ if (OMAP_DMA_CHAIN_QFULL(chain_id))
+ return -EBUSY;
+
+ /* Frame count may be negative in case of indexed transfers */
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ /* Get a free channel */
+ lch = channels[dma_linked_lch[chain_id].q_tail];
+
+ /* Store the callback data */
+ dma_chan[lch].data = callbk_data;
+
+ /* Increment the q_tail */
+ OMAP_DMA_CHAIN_INCQTAIL(chain_id);
+
+ /* Set the params to the free channel */
+ if (src_start != 0)
+ OMAP2_DMA_CSSA_REG(lch) = src_start;
+ if (dest_start != 0)
+ OMAP2_DMA_CDSA_REG(lch) = dest_start;
+
+ /* Write the buffer size */
+ OMAP_DMA_CEN_REG(lch) = elem_count;
+ OMAP_DMA_CFN_REG(lch) = frame_count;
+
+ /* If the chain is dynamically linked,
+ * then we may have to start the chain if its not active */
+ if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_DYNAMIC_CHAIN) {
+
+ /* In Dynamic chain, if the chain is not started,
+ * queue the channel */
+ if (dma_linked_lch[chain_id].chain_state ==
+ DMA_CHAIN_NOTSTARTED) {
+ /* Enable the link in previous channel */
+ if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
+ DMA_CH_QUEUED)
+ enable_lnk(dma_chan[lch].prev_linked_ch);
+ dma_chan[lch].state = DMA_CH_QUEUED;
+ }
+
+ /* Chain is already started, make sure its active,
+ * if not then start the chain */
+ else {
+ start_dma = 1;
+
+ if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
+ DMA_CH_STARTED) {
+ enable_lnk(dma_chan[lch].prev_linked_ch);
+ dma_chan[lch].state = DMA_CH_QUEUED;
+ start_dma = 0;
+ if (0 == ((1 << 7) & (OMAP_DMA_CCR_REG
+ (dma_chan[lch].prev_linked_ch)))) {
+ disable_lnk(dma_chan[lch].
+ prev_linked_ch);
+ pr_debug("\n prev ch is stopped\n");
+ start_dma = 1;
+ }
+ }
+
+ else if (dma_chan[dma_chan[lch].prev_linked_ch].state
+ == DMA_CH_QUEUED) {
+ enable_lnk(dma_chan[lch].prev_linked_ch);
+ dma_chan[lch].state = DMA_CH_QUEUED;
+ start_dma = 0;
+ }
+ omap_enable_channel_irq(lch);
+
+ w = OMAP_DMA_CCR_REG(lch);
+
+ if ((0 == (w & (1 << 24))))
+ w &= ~(1 << 25);
+ else
+ w |= (1 << 25);
+ if (start_dma == 1) {
+ if (0 == (w & (1 << 7))) {
+ w |= (1 << 7);
+ dma_chan[lch].state = DMA_CH_STARTED;
+ pr_debug("starting %d\n", lch);
+ OMAP_DMA_CCR_REG(lch) = w;
+ } else
+ start_dma = 0;
+ } else {
+ if (0 == (w & (1 << 7)))
+ OMAP_DMA_CCR_REG(lch) = w;
+ }
+ dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
+ }
+ }
+ return start_dma;
+}
+EXPORT_SYMBOL(omap_dma_chain_a_transfer);
+
+/**
+ * @brief omap_start_dma_chain_transfers - Start the chain
+ *
+ * @param chain_id
+ *
+ * @return - Success : 0
+ * Failure : -EINVAL/-EBUSY
+ */
+int omap_start_dma_chain_transfers(int chain_id)
+{
+ int *channels;
+ u32 w, i;
+
+ if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ if (dma_linked_lch[channels[0]].chain_state == DMA_CHAIN_STARTED) {
+ printk(KERN_ERR "Chain is already started\n");
+ return -EBUSY;
+ }
+
+ if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_STATIC_CHAIN) {
+ for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked;
+ i++) {
+ enable_lnk(channels[i]);
+ omap_enable_channel_irq(channels[i]);
+ }
+ } else {
+ omap_enable_channel_irq(channels[0]);
+ }
+
+ w = OMAP_DMA_CCR_REG(channels[0]);
+ w |= (1 << 7);
+ dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;
+ dma_chan[channels[0]].state = DMA_CH_STARTED;
+
+ if ((0 == (w & (1 << 24))))
+ w &= ~(1 << 25);
+ else
+ w |= (1 << 25);
+ OMAP_DMA_CCR_REG(channels[0]) = w;
+
+ dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
+ return 0;
+}
+EXPORT_SYMBOL(omap_start_dma_chain_transfers);
+
+/**
+ * @brief omap_stop_dma_chain_transfers - Stop the dma transfer of a chain.
+ *
+ * @param chain_id
+ *
+ * @return - Success : 0
+ * Failure : EINVAL
+ */
+int omap_stop_dma_chain_transfers(int chain_id)
+{
+ int *channels;
+ u32 w, i;
+ u32 sys_cf;
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ /* DMA Errata:
+ * Special programming model needed to disable DMA before end of block
+ */
+ sys_cf = omap_readl(OMAP_DMA4_OCP_SYSCONFIG);
+ w = sys_cf;
+ /* Middle mode reg set no Standby */
+ w &= ~((1 << 12)|(1 << 13));
+ omap_writel(w, OMAP_DMA4_OCP_SYSCONFIG);
+
+ for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
+
+ /* Stop the Channel transmission */
+ w = OMAP_DMA_CCR_REG(channels[i]);
+ w &= ~(1 << 7);
+ OMAP_DMA_CCR_REG(channels[i]) = w;
+
+ /* Disable the link in all the channels */
+ disable_lnk(channels[i]);
+ dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
+
+ }
+ dma_linked_lch[chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
+
+ /* Reset the Queue pointers */
+ OMAP_DMA_CHAIN_QINIT(chain_id);
+
+ /* Errata - put in the old value */
+ omap_writel(sys_cf, OMAP_DMA4_OCP_SYSCONFIG);
+ return 0;
+}
+EXPORT_SYMBOL(omap_stop_dma_chain_transfers);
+
+/* Get the index of the ongoing DMA in chain */
+/**
+ * @brief omap_get_dma_chain_index - Get the element and frame index
+ * of the ongoing DMA in chain
+ *
+ * @param chain_id
+ * @param ei - Element index
+ * @param fi - Frame index
+ *
+ * @return - Success : 0
+ * Failure : -EINVAL
+ */
+int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)
+{
+ int lch;
+ int *channels;
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+ if ((!ei) || (!fi))
+ return -EINVAL;
+
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ /* Get the current channel */
+ lch = channels[dma_linked_lch[chain_id].q_head];
+
+ *ei = OMAP2_DMA_CCEN_REG(lch);
+ *fi = OMAP2_DMA_CCFN_REG(lch);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_get_dma_chain_index);
+
+/**
+ * @brief omap_get_dma_chain_dst_pos - Get the destination position of the
+ * ongoing DMA in chain
+ *
+ * @param chain_id
+ *
+ * @return - Success : Destination position
+ * Failure : -EINVAL
+ */
+int omap_get_dma_chain_dst_pos(int chain_id)
+{
+ int lch;
+ int *channels;
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ /* Get the current channel */
+ lch = channels[dma_linked_lch[chain_id].q_head];
+
+ return (OMAP_DMA_CDAC_REG(lch));
+}
+EXPORT_SYMBOL(omap_get_dma_chain_dst_pos);
+
+/**
+ * @brief omap_get_dma_chain_src_pos - Get the source position
+ * of the ongoing DMA in chain
+ * @param chain_id
+ *
+ * @return - Success : Destination position
+ * Failure : -EINVAL
+ */
+int omap_get_dma_chain_src_pos(int chain_id)
+{
+ int lch;
+ int *channels;
+
+ /* Check for input params */
+ if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
+ printk(KERN_ERR "Invalid chain id\n");
+ return -EINVAL;
+ }
+
+ /* Check if the chain exists */
+ if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
+ printk(KERN_ERR "Chain doesn't exists\n");
+ return -EINVAL;
+ }
+
+ channels = dma_linked_lch[chain_id].linked_dmach_q;
+
+ /* Get the current channel */
+ lch = channels[dma_linked_lch[chain_id].q_head];
+
+ return (OMAP_DMA_CSAC_REG(lch));
+}
+EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
+#endif
+
/*----------------------------------------------------------------------------*/
#ifdef CONFIG_ARCH_OMAP1
@@ -919,7 +1654,7 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
#define omap1_dma_irq_handler NULL
#endif
-#ifdef CONFIG_ARCH_OMAP2
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
static int omap2_dma_handle_ch(int ch)
{
@@ -953,8 +1688,33 @@ static int omap2_dma_handle_ch(int ch)
OMAP_DMA_CSR_REG(ch) = OMAP2_DMA_CSR_CLEAR_MASK;
omap_writel(1 << ch, OMAP_DMA4_IRQSTATUS_L0);
- if (likely(dma_chan[ch].callback != NULL))
- dma_chan[ch].callback(ch, status, dma_chan[ch].data);
+ /* If the ch is not chained then chain_id will be -1 */
+ if (dma_chan[ch].chain_id != -1) {
+ int chain_id = dma_chan[ch].chain_id;
+ dma_chan[ch].state = DMA_CH_NOTSTARTED;
+ if (OMAP_DMA_CLNK_CTRL_REG(ch) & (1 << 15))
+ dma_chan[dma_chan[ch].next_linked_ch].state =
+ DMA_CH_STARTED;
+ if (dma_linked_lch[chain_id].chain_mode ==
+ OMAP_DMA_DYNAMIC_CHAIN)
+ disable_lnk(ch);
+
+ if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
+ OMAP_DMA_CHAIN_INCQHEAD(chain_id);
+
+ status = OMAP_DMA_CSR_REG(ch);
+ }
+
+ if (likely(dma_chan[ch].callback != NULL)) {
+ if (dma_chan[ch].chain_id != -1)
+ dma_chan[ch].callback(dma_chan[ch].chain_id, status,
+ dma_chan[ch].data);
+ else
+ dma_chan[ch].callback(ch, status, dma_chan[ch].data);
+
+ }
+
+ OMAP_DMA_CSR_REG(ch) = status;
return 0;
}
@@ -1385,7 +2145,7 @@ static int __init omap_init_dma(void)
w &= ~(1 << 8);
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
}
- } else if (cpu_is_omap24xx()) {
+ } else if (cpu_class_is_omap2()) {
u8 revision = omap_readb(OMAP_DMA4_REVISION);
printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
revision >> 4, revision & 0xf);
@@ -1428,7 +2188,11 @@ static int __init omap_init_dma(void)
}
}
- if (cpu_is_omap24xx())
+ if (cpu_is_omap2430() || cpu_is_omap34xx())
+ omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
+ DMA_DEFAULT_FIFO_DEPTH, 0);
+
+ if (cpu_class_is_omap2())
setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq);
/* FIXME: Update LCD DMA to work on 24xx */
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 3856f5aedfc..e719d0eeb5c 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -48,7 +48,7 @@
#define OMAP_TIMER_COUNTER_REG 0x28
#define OMAP_TIMER_LOAD_REG 0x2c
#define OMAP_TIMER_TRIGGER_REG 0x30
-#define OMAP_TIMER_WRITE_PEND_REG 0x34
+#define OMAP_TIMER_WRITE_PEND_REG 0x34
#define OMAP_TIMER_MATCH_REG 0x38
#define OMAP_TIMER_CAPTURE_REG 0x3c
#define OMAP_TIMER_IF_CTRL_REG 0x40
@@ -70,7 +70,7 @@
struct omap_dm_timer {
unsigned long phys_base;
int irq;
-#ifdef CONFIG_ARCH_OMAP2
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
struct clk *iclk, *fclk;
#endif
void __iomem *io_base;
@@ -82,8 +82,14 @@ struct omap_dm_timer {
#define omap_dm_clk_enable(x)
#define omap_dm_clk_disable(x)
-
-static struct omap_dm_timer dm_timers[] = {
+#define omap2_dm_timers NULL
+#define omap2_dm_source_names NULL
+#define omap2_dm_source_clocks NULL
+#define omap3_dm_timers NULL
+#define omap3_dm_source_names NULL
+#define omap3_dm_source_clocks NULL
+
+static struct omap_dm_timer omap1_dm_timers[] = {
{ .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
{ .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
{ .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
@@ -94,12 +100,18 @@ static struct omap_dm_timer dm_timers[] = {
{ .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
};
+static const int dm_timer_count = ARRAY_SIZE(omap1_dm_timers);
+
#elif defined(CONFIG_ARCH_OMAP2)
-#define omap_dm_clk_enable(x) clk_enable(x)
-#define omap_dm_clk_disable(x) clk_disable(x)
+#define omap_dm_clk_enable(x) clk_enable(x)
+#define omap_dm_clk_disable(x) clk_disable(x)
+#define omap1_dm_timers NULL
+#define omap3_dm_timers NULL
+#define omap3_dm_source_names NULL
+#define omap3_dm_source_clocks NULL
-static struct omap_dm_timer dm_timers[] = {
+static struct omap_dm_timer omap2_dm_timers[] = {
{ .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
{ .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
{ .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
@@ -114,13 +126,48 @@ static struct omap_dm_timer dm_timers[] = {
{ .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
};
-static const char *dm_source_names[] = {
+static const char *omap2_dm_source_names[] __initdata = {
"sys_ck",
"func_32k_ck",
- "alt_ck"
+ "alt_ck",
+ NULL
+};
+
+static struct clk **omap2_dm_source_clocks[3];
+static const int dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
+
+#elif defined(CONFIG_ARCH_OMAP3)
+
+#define omap_dm_clk_enable(x) clk_enable(x)
+#define omap_dm_clk_disable(x) clk_disable(x)
+#define omap1_dm_timers NULL
+#define omap2_dm_timers NULL
+#define omap2_dm_source_names NULL
+#define omap2_dm_source_clocks NULL
+
+static struct omap_dm_timer omap3_dm_timers[] = {
+ { .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
+ { .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 },
+ { .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 },
+ { .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 },
+ { .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 },
+ { .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 },
+ { .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 },
+ { .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 },
+ { .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
+ { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
+ { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
+ { .phys_base = 0x48304000, .irq = INT_24XX_GPTIMER12 },
+};
+
+static const char *omap3_dm_source_names[] __initdata = {
+ "sys_ck",
+ "omap_32k_fck",
+ NULL
};
-static struct clk *dm_source_clocks[3];
+static struct clk **omap3_dm_source_clocks[2];
+static const int dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
#else
@@ -128,7 +175,10 @@ static struct clk *dm_source_clocks[3];
#endif
-static const int dm_timer_count = ARRAY_SIZE(dm_timers);
+static struct omap_dm_timer *dm_timers;
+static char **dm_source_names;
+static struct clk **dm_source_clocks;
+
static spinlock_t dm_timer_lock;
static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg)
@@ -299,7 +349,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
return inputmask;
}
-#elif defined(CONFIG_ARCH_OMAP2)
+#elif defined(CONFIG_ARCH_OMAP2) || defined (CONFIG_ARCH_OMAP3)
struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
{
@@ -486,36 +536,46 @@ int omap_dm_timers_active(void)
return 0;
}
-int omap_dm_timer_init(void)
+int __init omap_dm_timer_init(void)
{
struct omap_dm_timer *timer;
int i;
- if (!(cpu_is_omap16xx() || cpu_is_omap24xx()))
+ if (!(cpu_is_omap16xx() || cpu_class_is_omap2()))
return -ENODEV;
spin_lock_init(&dm_timer_lock);
-#ifdef CONFIG_ARCH_OMAP2
- for (i = 0; i < ARRAY_SIZE(dm_source_names); i++) {
- dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
- BUG_ON(dm_source_clocks[i] == NULL);
+
+ if (cpu_class_is_omap1())
+ dm_timers = omap1_dm_timers;
+ else if (cpu_is_omap24xx()) {
+ dm_timers = omap2_dm_timers;
+ dm_source_names = (char **)omap2_dm_source_names;
+ dm_source_clocks = (struct clk **)omap2_dm_source_clocks;
+ } else if (cpu_is_omap34xx()) {
+ dm_timers = omap3_dm_timers;
+ dm_source_names = (char **)omap3_dm_source_names;
+ dm_source_clocks = (struct clk **)omap3_dm_source_clocks;
}
-#endif
+
+ if (cpu_class_is_omap2())
+ for (i = 0; dm_source_names[i] != NULL; i++)
+ dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
+
if (cpu_is_omap243x())
dm_timers[0].phys_base = 0x49018000;
for (i = 0; i < dm_timer_count; i++) {
-#ifdef CONFIG_ARCH_OMAP2
- char clk_name[16];
-#endif
-
timer = &dm_timers[i];
- timer->io_base = (void __iomem *) io_p2v(timer->phys_base);
-#ifdef CONFIG_ARCH_OMAP2
- sprintf(clk_name, "gpt%d_ick", i + 1);
- timer->iclk = clk_get(NULL, clk_name);
- sprintf(clk_name, "gpt%d_fck", i + 1);
- timer->fclk = clk_get(NULL, clk_name);
+ timer->io_base = (void __iomem *)io_p2v(timer->phys_base);
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+ if (cpu_class_is_omap2()) {
+ char clk_name[16];
+ sprintf(clk_name, "gpt%d_ick", i + 1);
+ timer->iclk = clk_get(NULL, clk_name);
+ sprintf(clk_name, "gpt%d_fck", i + 1);
+ timer->fclk = clk_get(NULL, clk_name);
+ }
#endif
}
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index ee40c1a0b83..7854f19b77c 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -207,7 +207,7 @@ void __init omapfb_reserve_sdram(void)
return;
}
if (rg.paddr)
- reserve_bootmem(rg.paddr, rg.size);
+ reserve_bootmem(rg.paddr, rg.size, BOOTMEM_DEFAULT);
reserved += rg.size;
omapfb_config.mem_desc.region[i] = rg;
configured_regions++;
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index b2a87b8ef67..56f4d1394d5 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -110,6 +110,8 @@
#define OMAP24XX_GPIO_LEVELDETECT1 0x0044
#define OMAP24XX_GPIO_RISINGDETECT 0x0048
#define OMAP24XX_GPIO_FALLINGDETECT 0x004c
+#define OMAP24XX_GPIO_DEBOUNCE_EN 0x0050
+#define OMAP24XX_GPIO_DEBOUNCE_VAL 0x0054
#define OMAP24XX_GPIO_CLEARIRQENABLE1 0x0060
#define OMAP24XX_GPIO_SETIRQENABLE1 0x0064
#define OMAP24XX_GPIO_CLEARWKUENA 0x0080
@@ -117,17 +119,29 @@
#define OMAP24XX_GPIO_CLEARDATAOUT 0x0090
#define OMAP24XX_GPIO_SETDATAOUT 0x0094
+/*
+ * omap34xx specific GPIO registers
+ */
+
+#define OMAP34XX_GPIO1_BASE (void __iomem *)0x48310000
+#define OMAP34XX_GPIO2_BASE (void __iomem *)0x49050000
+#define OMAP34XX_GPIO3_BASE (void __iomem *)0x49052000
+#define OMAP34XX_GPIO4_BASE (void __iomem *)0x49054000
+#define OMAP34XX_GPIO5_BASE (void __iomem *)0x49056000
+#define OMAP34XX_GPIO6_BASE (void __iomem *)0x49058000
+
+
struct gpio_bank {
void __iomem *base;
u16 irq;
u16 virtual_irq_start;
int method;
u32 reserved_map;
-#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_ARCH_OMAP24XX)
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
u32 suspend_wakeup;
u32 saved_wakeup;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
u32 non_wakeup_gpios;
u32 enabled_non_wakeup_gpios;
@@ -192,48 +206,52 @@ static struct gpio_bank gpio_bank_243x[5] = {
#endif
+#ifdef CONFIG_ARCH_OMAP34XX
+static struct gpio_bank gpio_bank_34xx[6] = {
+ { OMAP34XX_GPIO1_BASE, INT_34XX_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_24XX },
+ { OMAP34XX_GPIO2_BASE, INT_34XX_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_24XX },
+ { OMAP34XX_GPIO3_BASE, INT_34XX_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_24XX },
+ { OMAP34XX_GPIO4_BASE, INT_34XX_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_24XX },
+ { OMAP34XX_GPIO5_BASE, INT_34XX_GPIO_BANK5, IH_GPIO_BASE + 128, METHOD_GPIO_24XX },
+ { OMAP34XX_GPIO6_BASE, INT_34XX_GPIO_BANK6, IH_GPIO_BASE + 160, METHOD_GPIO_24XX },
+};
+
+#endif
+
static struct gpio_bank *gpio_bank;
static int gpio_bank_count;
static inline struct gpio_bank *get_gpio_bank(int gpio)
{
-#ifdef CONFIG_ARCH_OMAP15XX
if (cpu_is_omap15xx()) {
if (OMAP_GPIO_IS_MPUIO(gpio))
return &gpio_bank[0];
return &gpio_bank[1];
}
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
if (cpu_is_omap16xx()) {
if (OMAP_GPIO_IS_MPUIO(gpio))
return &gpio_bank[0];
return &gpio_bank[1 + (gpio >> 4)];
}
-#endif
-#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730()) {
if (OMAP_GPIO_IS_MPUIO(gpio))
return &gpio_bank[0];
return &gpio_bank[1 + (gpio >> 5)];
}
-#endif
-#ifdef CONFIG_ARCH_OMAP24XX
if (cpu_is_omap24xx())
return &gpio_bank[gpio >> 5];
-#endif
+ if (cpu_is_omap34xx())
+ return &gpio_bank[gpio >> 5];
}
static inline int get_gpio_index(int gpio)
{
-#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730())
return gpio & 0x1f;
-#endif
-#ifdef CONFIG_ARCH_OMAP24XX
if (cpu_is_omap24xx())
return gpio & 0x1f;
-#endif
+ if (cpu_is_omap34xx())
+ return gpio & 0x1f;
return gpio & 0x0f;
}
@@ -241,29 +259,21 @@ static inline int gpio_valid(int gpio)
{
if (gpio < 0)
return -1;
-#ifndef CONFIG_ARCH_OMAP24XX
- if (OMAP_GPIO_IS_MPUIO(gpio)) {
+ if (cpu_class_is_omap1() && OMAP_GPIO_IS_MPUIO(gpio)) {
if (gpio >= OMAP_MAX_GPIO_LINES + 16)
return -1;
return 0;
}
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
if (cpu_is_omap15xx() && gpio < 16)
return 0;
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
if ((cpu_is_omap16xx()) && gpio < 64)
return 0;
-#endif
-#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730() && gpio < 192)
return 0;
-#endif
-#ifdef CONFIG_ARCH_OMAP24XX
if (cpu_is_omap24xx() && gpio < 128)
return 0;
-#endif
+ if (cpu_is_omap34xx() && gpio < 160)
+ return 0;
return -1;
}
@@ -303,7 +313,7 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
reg += OMAP730_GPIO_DIR_CONTROL;
break;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
reg += OMAP24XX_GPIO_OE;
break;
@@ -377,7 +387,7 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
l &= ~(1 << gpio);
break;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
if (enable)
reg += OMAP24XX_GPIO_SETDATAOUT;
@@ -435,7 +445,7 @@ int omap_get_gpio_datain(int gpio)
reg += OMAP730_GPIO_DATA_INPUT;
break;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
reg += OMAP24XX_GPIO_DATAIN;
break;
@@ -455,8 +465,50 @@ do { \
__raw_writel(l, base + reg); \
} while(0)
-#ifdef CONFIG_ARCH_OMAP24XX
-static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
+void omap_set_gpio_debounce(int gpio, int enable)
+{
+ struct gpio_bank *bank;
+ void __iomem *reg;
+ u32 val, l = 1 << get_gpio_index(gpio);
+
+ if (cpu_class_is_omap1())
+ return;
+
+ bank = get_gpio_bank(gpio);
+ reg = bank->base;
+
+ reg += OMAP24XX_GPIO_DEBOUNCE_EN;
+ val = __raw_readl(reg);
+
+ if (enable)
+ val |= l;
+ else
+ val &= ~l;
+
+ __raw_writel(val, reg);
+}
+EXPORT_SYMBOL(omap_set_gpio_debounce);
+
+void omap_set_gpio_debounce_time(int gpio, int enc_time)
+{
+ struct gpio_bank *bank;
+ void __iomem *reg;
+
+ if (cpu_class_is_omap1())
+ return;
+
+ bank = get_gpio_bank(gpio);
+ reg = bank->base;
+
+ enc_time &= 0xff;
+ reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
+ __raw_writel(enc_time, reg);
+}
+EXPORT_SYMBOL(omap_set_gpio_debounce_time);
+
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
+ int trigger)
{
void __iomem *base = bank->base;
u32 gpio_bit = 1 << gpio;
@@ -469,19 +521,25 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, in
trigger & __IRQT_RISEDGE);
MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
trigger & __IRQT_FALEDGE);
+
if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
if (trigger != 0)
- __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_SETWKUENA);
+ __raw_writel(1 << gpio, bank->base
+ + OMAP24XX_GPIO_SETWKUENA);
else
- __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_CLEARWKUENA);
+ __raw_writel(1 << gpio, bank->base
+ + OMAP24XX_GPIO_CLEARWKUENA);
} else {
if (trigger != 0)
bank->enabled_non_wakeup_gpios |= gpio_bit;
else
bank->enabled_non_wakeup_gpios &= ~gpio_bit;
}
- /* FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only level
- * triggering requested. */
+
+ /*
+ * FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only
+ * level triggering requested.
+ */
}
#endif
@@ -547,7 +605,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
goto bad;
break;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
set_24xx_gpio_triggering(bank, gpio, trigger);
break;
@@ -567,7 +625,7 @@ static int gpio_irq_type(unsigned irq, unsigned type)
unsigned gpio;
int retval;
- if (!cpu_is_omap24xx() && irq > IH_MPUIO_BASE)
+ if (!cpu_class_is_omap2() && irq > IH_MPUIO_BASE)
gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
else
gpio = irq - IH_GPIO_BASE;
@@ -579,7 +637,7 @@ static int gpio_irq_type(unsigned irq, unsigned type)
return -EINVAL;
/* OMAP1 allows only only edge triggering */
- if (!cpu_is_omap24xx()
+ if (!cpu_class_is_omap2()
&& (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
return -EINVAL;
@@ -620,7 +678,7 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
reg += OMAP730_GPIO_INT_STATUS;
break;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
reg += OMAP24XX_GPIO_IRQSTATUS1;
break;
@@ -632,8 +690,10 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
__raw_writel(gpio_mask, reg);
/* Workaround for clearing DSP GPIO interrupts to allow retention */
- if (cpu_is_omap2420())
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+ if (cpu_is_omap24xx() || cpu_is_omap34xx())
__raw_writel(gpio_mask, bank->base + OMAP24XX_GPIO_IRQSTATUS2);
+#endif
}
static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
@@ -676,7 +736,7 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
inv = 1;
break;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
reg += OMAP24XX_GPIO_IRQENABLE1;
mask = 0xffffffff;
@@ -739,7 +799,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab
l |= gpio_mask;
break;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
if (enable)
reg += OMAP24XX_GPIO_SETIRQENABLE1;
@@ -785,7 +845,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
spin_unlock(&bank->lock);
return 0;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
if (bank->non_wakeup_gpios & (1 << gpio)) {
printk(KERN_ERR "Unable to modify wakeup on "
@@ -891,7 +951,7 @@ void omap_free_gpio(int gpio)
__raw_writel(1 << get_gpio_index(gpio), reg);
}
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
if (bank->method == METHOD_GPIO_24XX) {
/* Disable wake-up during idle for dynamic tick */
void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
@@ -940,7 +1000,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
if (bank->method == METHOD_GPIO_730)
isr_reg = bank->base + OMAP730_GPIO_INT_STATUS;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
if (bank->method == METHOD_GPIO_24XX)
isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
#endif
@@ -954,7 +1014,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
isr &= 0x0000ffff;
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
level_mask =
__raw_readl(bank->base +
OMAP24XX_GPIO_LEVELDETECT0) |
@@ -1023,7 +1083,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
}
}
- if (cpu_is_omap24xx()) {
+ if (cpu_class_is_omap2()) {
/* clear level sensitive interrupts after handler(s) */
_enable_gpio_irqbank(bank, isr_saved & level_mask, 0);
_clear_gpio_irqbank(bank, isr_saved & level_mask);
@@ -1199,21 +1259,35 @@ static inline void mpuio_init(void) {}
/*---------------------------------------------------------------------*/
static int initialized;
+#if !defined(CONFIG_ARCH_OMAP3)
static struct clk * gpio_ick;
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2)
static struct clk * gpio_fck;
+#endif
-#ifdef CONFIG_ARCH_OMAP2430
+#if defined(CONFIG_ARCH_OMAP2430)
static struct clk * gpio5_ick;
static struct clk * gpio5_fck;
#endif
+#if defined(CONFIG_ARCH_OMAP3)
+static struct clk *gpio_fclks[OMAP34XX_NR_GPIOS];
+static struct clk *gpio_iclks[OMAP34XX_NR_GPIOS];
+#endif
+
static int __init _omap_gpio_init(void)
{
int i;
struct gpio_bank *bank;
+#if defined(CONFIG_ARCH_OMAP3)
+ char clk_name[11];
+#endif
initialized = 1;
+#if defined(CONFIG_ARCH_OMAP1)
if (cpu_is_omap15xx()) {
gpio_ick = clk_get(NULL, "arm_gpio_ck");
if (IS_ERR(gpio_ick))
@@ -1221,7 +1295,9 @@ static int __init _omap_gpio_init(void)
else
clk_enable(gpio_ick);
}
- if (cpu_is_omap24xx()) {
+#endif
+#if defined(CONFIG_ARCH_OMAP2)
+ if (cpu_class_is_omap2()) {
gpio_ick = clk_get(NULL, "gpios_ick");
if (IS_ERR(gpio_ick))
printk("Could not get gpios_ick\n");
@@ -1234,9 +1310,9 @@ static int __init _omap_gpio_init(void)
clk_enable(gpio_fck);
/*
- * On 2430 GPIO 5 uses CORE L4 ICLK
+ * On 2430 & 3430 GPIO 5 uses CORE L4 ICLK
*/
-#ifdef CONFIG_ARCH_OMAP2430
+#if defined(CONFIG_ARCH_OMAP2430)
if (cpu_is_omap2430()) {
gpio5_ick = clk_get(NULL, "gpio5_ick");
if (IS_ERR(gpio5_ick))
@@ -1250,7 +1326,28 @@ static int __init _omap_gpio_init(void)
clk_enable(gpio5_fck);
}
#endif
-}
+ }
+#endif
+
+#if defined(CONFIG_ARCH_OMAP3)
+ if (cpu_is_omap34xx()) {
+ for (i = 0; i < OMAP34XX_NR_GPIOS; i++) {
+ sprintf(clk_name, "gpio%d_ick", i + 1);
+ gpio_iclks[i] = clk_get(NULL, clk_name);
+ if (IS_ERR(gpio_iclks[i]))
+ printk(KERN_ERR "Could not get %s\n", clk_name);
+ else
+ clk_enable(gpio_iclks[i]);
+ sprintf(clk_name, "gpio%d_fck", i + 1);
+ gpio_fclks[i] = clk_get(NULL, clk_name);
+ if (IS_ERR(gpio_fclks[i]))
+ printk(KERN_ERR "Could not get %s\n", clk_name);
+ else
+ clk_enable(gpio_fclks[i]);
+ }
+ }
+#endif
+
#ifdef CONFIG_ARCH_OMAP15XX
if (cpu_is_omap15xx()) {
@@ -1298,6 +1395,17 @@ static int __init _omap_gpio_init(void)
(rev >> 4) & 0x0f, rev & 0x0f);
}
#endif
+#ifdef CONFIG_ARCH_OMAP34XX
+ if (cpu_is_omap34xx()) {
+ int rev;
+
+ gpio_bank_count = OMAP34XX_NR_GPIOS;
+ gpio_bank = gpio_bank_34xx;
+ rev = omap_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
+ printk(KERN_INFO "OMAP34xx GPIO hardware version %d.%d\n",
+ (rev >> 4) & 0x0f, rev & 0x0f);
+ }
+#endif
for (i = 0; i < gpio_bank_count; i++) {
int j, gpio_count = 16;
@@ -1307,28 +1415,23 @@ static int __init _omap_gpio_init(void)
spin_lock_init(&bank->lock);
if (bank_is_mpuio(bank))
omap_writew(0xFFFF, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_MASKIT);
-#ifdef CONFIG_ARCH_OMAP15XX
- if (bank->method == METHOD_GPIO_1510) {
+ if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) {
__raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK);
__raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS);
}
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
- if (bank->method == METHOD_GPIO_1610) {
+ if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) {
__raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
__raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG);
}
-#endif
-#ifdef CONFIG_ARCH_OMAP730
- if (bank->method == METHOD_GPIO_730) {
+ if (cpu_is_omap730() && bank->method == METHOD_GPIO_730) {
__raw_writel(0xffffffff, bank->base + OMAP730_GPIO_INT_MASK);
__raw_writel(0x00000000, bank->base + OMAP730_GPIO_INT_STATUS);
gpio_count = 32; /* 730 has 32-bit GPIOs */
}
-#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
if (bank->method == METHOD_GPIO_24XX) {
static const u32 non_wakeup_gpios[] = {
0xe203ffc0, 0x08700040
@@ -1364,21 +1467,21 @@ static int __init _omap_gpio_init(void)
if (cpu_is_omap16xx())
omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
-#ifdef CONFIG_ARCH_OMAP24XX
/* Enable autoidle for the OCP interface */
if (cpu_is_omap24xx())
omap_writel(1 << 0, 0x48019010);
-#endif
+ if (cpu_is_omap34xx())
+ omap_writel(1 << 0, 0x48306814);
return 0;
}
-#if defined (CONFIG_ARCH_OMAP16XX) || defined (CONFIG_ARCH_OMAP24XX)
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
{
int i;
- if (!cpu_is_omap24xx() && !cpu_is_omap16xx())
+ if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
return 0;
for (i = 0; i < gpio_bank_count; i++) {
@@ -1395,7 +1498,7 @@ static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
break;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
wake_status = bank->base + OMAP24XX_GPIO_SETWKUENA;
wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
@@ -1435,7 +1538,7 @@ static int omap_gpio_resume(struct sys_device *dev)
wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
break;
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
@@ -1467,7 +1570,7 @@ static struct sys_device omap_gpio_device = {
#endif
-#ifdef CONFIG_ARCH_OMAP24XX
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
static int workaround_enabled;
@@ -1483,15 +1586,19 @@ void omap2_gpio_prepare_for_retention(void)
if (!(bank->enabled_non_wakeup_gpios))
continue;
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
bank->saved_datain = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
l1 = __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
l2 = __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
+#endif
bank->saved_fallingdetect = l1;
bank->saved_risingdetect = l2;
l1 &= ~bank->enabled_non_wakeup_gpios;
l2 &= ~bank->enabled_non_wakeup_gpios;
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
__raw_writel(l1, bank->base + OMAP24XX_GPIO_FALLINGDETECT);
__raw_writel(l2, bank->base + OMAP24XX_GPIO_RISINGDETECT);
+#endif
c++;
}
if (!c) {
@@ -1513,26 +1620,31 @@ void omap2_gpio_resume_after_retention(void)
if (!(bank->enabled_non_wakeup_gpios))
continue;
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
__raw_writel(bank->saved_fallingdetect,
bank->base + OMAP24XX_GPIO_FALLINGDETECT);
__raw_writel(bank->saved_risingdetect,
bank->base + OMAP24XX_GPIO_RISINGDETECT);
+#endif
/* Check if any of the non-wakeup interrupt GPIOs have changed
* state. If so, generate an IRQ by software. This is
* horribly racy, but it's the best we can do to work around
* this silicon bug. */
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
+#endif
l ^= bank->saved_datain;
l &= bank->non_wakeup_gpios;
if (l) {
u32 old0, old1;
-
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
old0 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
old1 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
__raw_writel(old0 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT0);
__raw_writel(old1 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT1);
__raw_writel(old0, bank->base + OMAP24XX_GPIO_LEVELDETECT0);
__raw_writel(old1, bank->base + OMAP24XX_GPIO_LEVELDETECT1);
+#endif
}
}
@@ -1561,8 +1673,8 @@ static int __init omap_gpio_sysinit(void)
mpuio_init();
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX)
- if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+ if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
if (ret == 0) {
ret = sysdev_class_register(&omap_gpio_sysclass);
if (ret == 0)
@@ -1624,7 +1736,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
if (bank_is_mpuio(bank))
gpio = OMAP_MPUIO(0);
- else if (cpu_is_omap24xx() || cpu_is_omap730())
+ else if (cpu_class_is_omap2() || cpu_is_omap730())
bankwidth = 32;
for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) {
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
new file mode 100644
index 00000000000..7990ab185bb
--- /dev/null
+++ b/arch/arm/plat-omap/i2c.c
@@ -0,0 +1,148 @@
+/*
+ * linux/arch/arm/plat-omap/i2c.c
+ *
+ * Helper module for board specific I2C bus registration
+ *
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@nokia.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.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <asm/mach-types.h>
+#include <asm/arch/mux.h>
+
+#define OMAP_I2C_SIZE 0x3f
+#define OMAP1_I2C_BASE 0xfffb3800
+#define OMAP2_I2C_BASE1 0x48070000
+#define OMAP2_I2C_BASE2 0x48072000
+#define OMAP2_I2C_BASE3 0x48060000
+
+static const char name[] = "i2c_omap";
+
+#define I2C_RESOURCE_BUILDER(base, irq) \
+ { \
+ .start = (base), \
+ .end = (base) + OMAP_I2C_SIZE, \
+ .flags = IORESOURCE_MEM, \
+ }, \
+ { \
+ .start = (irq), \
+ .flags = IORESOURCE_IRQ, \
+ },
+
+static struct resource i2c_resources[][2] = {
+ { I2C_RESOURCE_BUILDER(0, 0) },
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+ { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, INT_24XX_I2C2_IRQ) },
+#endif
+#if defined(CONFIG_ARCH_OMAP34XX)
+ { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, INT_34XX_I2C3_IRQ) },
+#endif
+};
+
+#define I2C_DEV_BUILDER(bus_id, res, data) \
+ { \
+ .id = (bus_id), \
+ .name = name, \
+ .num_resources = ARRAY_SIZE(res), \
+ .resource = (res), \
+ .dev = { \
+ .platform_data = (data), \
+ }, \
+ }
+
+static u32 i2c_rate[ARRAY_SIZE(i2c_resources)];
+static struct platform_device omap_i2c_devices[] = {
+ I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_rate[0]),
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+ I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_rate[1]),
+#endif
+#if defined(CONFIG_ARCH_OMAP34XX)
+ I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_rate[2]),
+#endif
+};
+
+static void __init omap_i2c_mux_pins(int bus_id)
+{
+ /* TODO: Muxing for OMAP3 */
+ switch (bus_id) {
+ case 1:
+ if (cpu_class_is_omap1()) {
+ omap_cfg_reg(I2C_SCL);
+ omap_cfg_reg(I2C_SDA);
+ } else if (cpu_is_omap24xx()) {
+ omap_cfg_reg(M19_24XX_I2C1_SCL);
+ omap_cfg_reg(L15_24XX_I2C1_SDA);
+ }
+ break;
+ case 2:
+ if (cpu_is_omap24xx()) {
+ omap_cfg_reg(J15_24XX_I2C2_SCL);
+ omap_cfg_reg(H19_24XX_I2C2_SDA);
+ }
+ break;
+ }
+}
+
+int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
+ struct i2c_board_info const *info,
+ unsigned len)
+{
+ int ports, err;
+ struct platform_device *pdev;
+ struct resource *res;
+ resource_size_t base, irq;
+
+ if (cpu_class_is_omap1())
+ ports = 1;
+ else if (cpu_is_omap24xx())
+ ports = 2;
+ else if (cpu_is_omap34xx())
+ ports = 3;
+
+ BUG_ON(bus_id < 1 || bus_id > ports);
+
+ if (info) {
+ err = i2c_register_board_info(bus_id, info, len);
+ if (err)
+ return err;
+ }
+
+ pdev = &omap_i2c_devices[bus_id - 1];
+ *(u32 *)pdev->dev.platform_data = clkrate;
+
+ if (bus_id == 1) {
+ res = pdev->resource;
+ if (cpu_class_is_omap1()) {
+ base = OMAP1_I2C_BASE;
+ irq = INT_I2C;
+ } else {
+ base = OMAP2_I2C_BASE1;
+ irq = INT_24XX_I2C1_IRQ;
+ }
+ res[0].start = base;
+ res[0].end = base + OMAP_I2C_SIZE;
+ res[1].start = irq;
+ }
+
+ omap_i2c_mux_pins(bus_id);
+ return platform_device_register(pdev);
+}
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 2af5bd5a134..9cf83c4da9f 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -201,6 +201,14 @@ static int omap_mcbsp_check(unsigned int id)
static void omap_mcbsp_dsp_request(void)
{
if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
+ int ret;
+
+ ret = omap_dsp_request_mem();
+ if (ret < 0) {
+ printk(KERN_ERR "Could not get dsp memory: %i\n", ret);
+ return;
+ }
+
clk_enable(mcbsp_dsp_ck);
clk_enable(mcbsp_api_ck);
@@ -219,6 +227,7 @@ static void omap_mcbsp_dsp_request(void)
static void omap_mcbsp_dsp_free(void)
{
if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
+ omap_dsp_release_mem();
clk_disable(mcbsp_dspxor_ck);
clk_disable(mcbsp_dsp_ck);
clk_disable(mcbsp_api_ck);
@@ -1024,6 +1033,8 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type);
EXPORT_SYMBOL(omap_mcbsp_free);
EXPORT_SYMBOL(omap_mcbsp_start);
EXPORT_SYMBOL(omap_mcbsp_stop);
+EXPORT_SYMBOL(omap_mcbsp_pollread);
+EXPORT_SYMBOL(omap_mcbsp_pollwrite);
EXPORT_SYMBOL(omap_mcbsp_xmit_word);
EXPORT_SYMBOL(omap_mcbsp_recv_word);
EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index c816f29154c..c75d7089f98 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -10,6 +10,7 @@ config AVR32
# With EMBEDDED=n, we get lots of stuff automatically selected
# that we usually don't need on AVR32.
select EMBEDDED
+ select HAVE_IDE
select HAVE_OPROFILE
select HAVE_KPROBES
help
@@ -82,6 +83,7 @@ config PLATFORM_AT32AP
select SUBARCH_AVR32B
select MMU
select PERFORMANCE_COUNTERS
+ select HAVE_GPIO_LIB
#
# CPU types
diff --git a/arch/avr32/kernel/ocd.c b/arch/avr32/kernel/ocd.c
index c4f023294d7..1b0245d4e0c 100644
--- a/arch/avr32/kernel/ocd.c
+++ b/arch/avr32/kernel/ocd.c
@@ -90,25 +90,29 @@ static struct dentry *ocd_debugfs_DC;
static struct dentry *ocd_debugfs_DS;
static struct dentry *ocd_debugfs_count;
-static u64 ocd_DC_get(void *data)
+static int ocd_DC_get(void *data, u64 *val)
{
- return ocd_read(DC);
+ *val = ocd_read(DC);
+ return 0;
}
-static void ocd_DC_set(void *data, u64 val)
+static int ocd_DC_set(void *data, u64 val)
{
ocd_write(DC, val);
+ return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(fops_DC, ocd_DC_get, ocd_DC_set, "0x%08llx\n");
-static u64 ocd_DS_get(void *data)
+static int ocd_DS_get(void *data, u64 *val)
{
- return ocd_read(DS);
+ *val = ocd_read(DS);
+ return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(fops_DS, ocd_DS_get, NULL, "0x%08llx\n");
-static u64 ocd_count_get(void *data)
+static int ocd_count_get(void *data, u64 *val)
{
- return ocd_count;
+ *val = ocd_count;
+ return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(fops_count, ocd_count_get, NULL, "%lld\n");
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
index 4b4c1884e1c..e66a07a928c 100644
--- a/arch/avr32/kernel/setup.c
+++ b/arch/avr32/kernel/setup.c
@@ -489,7 +489,8 @@ static void __init setup_bootmem(void)
/* Reserve space for the bootmem bitmap... */
reserve_bootmem_node(NODE_DATA(node),
PFN_PHYS(bootmap_pfn),
- bootmap_size);
+ bootmap_size,
+ BOOTMEM_DEFAULT);
/* ...and any other reserved regions. */
for (res = reserved; res; res = res->sibling) {
@@ -505,7 +506,8 @@ static void __init setup_bootmem(void)
&& res->end < PFN_PHYS(max_pfn))
reserve_bootmem_node(
NODE_DATA(node), res->start,
- res->end - res->start + 1);
+ res->end - res->start + 1,
+ BOOTMEM_DEFAULT);
}
node_set_online(node);
diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S
index 75c81f2dd0b..478bda4c4a0 100644
--- a/arch/avr32/kernel/syscall_table.S
+++ b/arch/avr32/kernel/syscall_table.S
@@ -293,6 +293,6 @@ sys_call_table:
.long sys_shmctl
.long sys_utimensat
.long sys_signalfd
- .long sys_timerfd /* 280 */
+ .long sys_ni_syscall /* 280, was sys_timerfd */
.long sys_eventfd
.long sys_ni_syscall /* r8 is saturated at nr_syscalls */
diff --git a/arch/avr32/lib/delay.c b/arch/avr32/lib/delay.c
index b3bc0b56e2c..9aa8800830f 100644
--- a/arch/avr32/lib/delay.c
+++ b/arch/avr32/lib/delay.c
@@ -12,13 +12,15 @@
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/timex.h>
#include <linux/param.h>
#include <linux/types.h>
+#include <linux/init.h>
#include <asm/processor.h>
#include <asm/sysreg.h>
-int read_current_timer(unsigned long *timer_value)
+int __devinit read_current_timer(unsigned long *timer_value)
{
*timer_value = sysreg_read(COUNT);
return 0;
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index 14e61f05e1f..7678fee9a88 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -1186,6 +1186,59 @@ err_dup_modedb:
#endif
/* --------------------------------------------------------------------
+ * PWM
+ * -------------------------------------------------------------------- */
+static struct resource atmel_pwm0_resource[] __initdata = {
+ PBMEM(0xfff01400),
+ IRQ(24),
+};
+static struct clk atmel_pwm0_mck = {
+ .name = "mck",
+ .parent = &pbb_clk,
+ .mode = pbb_clk_mode,
+ .get_rate = pbb_clk_get_rate,
+ .index = 5,
+};
+
+struct platform_device *__init at32_add_device_pwm(u32 mask)
+{
+ struct platform_device *pdev;
+
+ if (!mask)
+ return NULL;
+
+ pdev = platform_device_alloc("atmel_pwm", 0);
+ if (!pdev)
+ return NULL;
+
+ if (platform_device_add_resources(pdev, atmel_pwm0_resource,
+ ARRAY_SIZE(atmel_pwm0_resource)))
+ goto out_free_pdev;
+
+ if (platform_device_add_data(pdev, &mask, sizeof(mask)))
+ goto out_free_pdev;
+
+ if (mask & (1 << 0))
+ select_peripheral(PA(28), PERIPH_A, 0);
+ if (mask & (1 << 1))
+ select_peripheral(PA(29), PERIPH_A, 0);
+ if (mask & (1 << 2))
+ select_peripheral(PA(21), PERIPH_B, 0);
+ if (mask & (1 << 3))
+ select_peripheral(PA(22), PERIPH_B, 0);
+
+ atmel_pwm0_mck.dev = &pdev->dev;
+
+ platform_device_add(pdev);
+
+ return pdev;
+
+out_free_pdev:
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* --------------------------------------------------------------------
* SSC
* -------------------------------------------------------------------- */
static struct resource ssc0_resource[] = {
@@ -1646,6 +1699,7 @@ struct clk *at32_clock_list[] = {
&atmel_usart1_usart,
&atmel_usart2_usart,
&atmel_usart3_usart,
+ &atmel_pwm0_mck,
#if defined(CONFIG_CPU_AT32AP7000)
&macb0_hclk,
&macb0_pclk,
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index d61a02da898..38a8fa31c0b 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -24,11 +24,11 @@
#define MAX_NR_PIO_DEVICES 8
struct pio_device {
+ struct gpio_chip chip;
void __iomem *regs;
const struct platform_device *pdev;
struct clk *clk;
u32 pinmux_mask;
- u32 gpio_mask;
char name[8];
};
@@ -64,7 +64,8 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
goto fail;
}
- if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
+ if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask)
+ || gpiochip_is_requested(&pio->chip, pin_index))) {
printk("%s: pin %u is busy\n", pio->name, pin_index);
goto fail;
}
@@ -79,9 +80,6 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
if (!(flags & AT32_GPIOF_PULLUP))
pio_writel(pio, PUDR, mask);
- /* gpio_request NOT allowed */
- set_bit(pin_index, &pio->gpio_mask);
-
return;
fail:
@@ -130,9 +128,6 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags)
pio_writel(pio, PER, mask);
- /* gpio_request now allowed */
- clear_bit(pin_index, &pio->gpio_mask);
-
return;
fail:
@@ -166,96 +161,50 @@ fail:
/* GPIO API */
-int gpio_request(unsigned int gpio, const char *label)
+static int direction_input(struct gpio_chip *chip, unsigned offset)
{
- struct pio_device *pio;
- unsigned int pin;
-
- pio = gpio_to_pio(gpio);
- if (!pio)
- return -ENODEV;
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 mask = 1 << offset;
- pin = gpio & 0x1f;
- if (test_and_set_bit(pin, &pio->gpio_mask))
- return -EBUSY;
+ if (!(pio_readl(pio, PSR) & mask))
+ return -EINVAL;
+ pio_writel(pio, ODR, mask);
return 0;
}
-EXPORT_SYMBOL(gpio_request);
-void gpio_free(unsigned int gpio)
+static int gpio_get(struct gpio_chip *chip, unsigned offset)
{
- struct pio_device *pio;
- unsigned int pin;
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
- pio = gpio_to_pio(gpio);
- if (!pio) {
- printk(KERN_ERR
- "gpio: attempted to free invalid pin %u\n", gpio);
- return;
- }
-
- pin = gpio & 0x1f;
- if (!test_and_clear_bit(pin, &pio->gpio_mask))
- printk(KERN_ERR "gpio: freeing free or non-gpio pin %s-%u\n",
- pio->name, pin);
+ return (pio_readl(pio, PDSR) >> offset) & 1;
}
-EXPORT_SYMBOL(gpio_free);
-int gpio_direction_input(unsigned int gpio)
-{
- struct pio_device *pio;
- unsigned int pin;
-
- pio = gpio_to_pio(gpio);
- if (!pio)
- return -ENODEV;
-
- pin = gpio & 0x1f;
- pio_writel(pio, ODR, 1 << pin);
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_input);
+static void gpio_set(struct gpio_chip *chip, unsigned offset, int value);
-int gpio_direction_output(unsigned int gpio, int value)
+static int direction_output(struct gpio_chip *chip, unsigned offset, int value)
{
- struct pio_device *pio;
- unsigned int pin;
-
- pio = gpio_to_pio(gpio);
- if (!pio)
- return -ENODEV;
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 mask = 1 << offset;
- gpio_set_value(gpio, value);
-
- pin = gpio & 0x1f;
- pio_writel(pio, OER, 1 << pin);
+ if (!(pio_readl(pio, PSR) & mask))
+ return -EINVAL;
+ gpio_set(chip, offset, value);
+ pio_writel(pio, OER, mask);
return 0;
}
-EXPORT_SYMBOL(gpio_direction_output);
-int gpio_get_value(unsigned int gpio)
+static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
- struct pio_device *pio = &pio_dev[gpio >> 5];
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 mask = 1 << offset;
- return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1;
-}
-EXPORT_SYMBOL(gpio_get_value);
-
-void gpio_set_value(unsigned int gpio, int value)
-{
- struct pio_device *pio = &pio_dev[gpio >> 5];
- u32 mask;
-
- mask = 1 << (gpio & 0x1f);
if (value)
pio_writel(pio, SODR, mask);
else
pio_writel(pio, CODR, mask);
}
-EXPORT_SYMBOL(gpio_set_value);
/*--------------------------------------------------------------------------*/
@@ -339,6 +288,63 @@ gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
/*--------------------------------------------------------------------------*/
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/seq_file.h>
+
+/*
+ * This shows more info than the generic gpio dump code:
+ * pullups, deglitching, open drain drive.
+ */
+static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip)
+{
+ struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ u32 psr, osr, imr, pdsr, pusr, ifsr, mdsr;
+ unsigned i;
+ u32 mask;
+ char bank;
+
+ psr = pio_readl(pio, PSR);
+ osr = pio_readl(pio, OSR);
+ imr = pio_readl(pio, IMR);
+ pdsr = pio_readl(pio, PDSR);
+ pusr = pio_readl(pio, PUSR);
+ ifsr = pio_readl(pio, IFSR);
+ mdsr = pio_readl(pio, MDSR);
+
+ bank = 'A' + pio->pdev->id;
+
+ for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
+ const char *label;
+
+ label = gpiochip_is_requested(chip, i);
+ if (!label)
+ continue;
+
+ seq_printf(s, " gpio-%-3d P%c%-2d (%-12s) %s %s %s",
+ chip->base + i, bank, i,
+ label,
+ (osr & mask) ? "out" : "in ",
+ (mask & pdsr) ? "hi" : "lo",
+ (mask & pusr) ? " " : "up");
+ if (ifsr & mask)
+ seq_printf(s, " deglitch");
+ if ((osr & mdsr) & mask)
+ seq_printf(s, " open-drain");
+ if (imr & mask)
+ seq_printf(s, " irq-%d edge-both",
+ gpio_to_irq(chip->base + i));
+ seq_printf(s, "\n");
+ }
+}
+
+#else
+#define pio_bank_show NULL
+#endif
+
+
+/*--------------------------------------------------------------------------*/
+
static int __init pio_probe(struct platform_device *pdev)
{
struct pio_device *pio = NULL;
@@ -349,6 +355,18 @@ static int __init pio_probe(struct platform_device *pdev)
pio = &pio_dev[pdev->id];
BUG_ON(!pio->regs);
+ pio->chip.label = pio->name;
+ pio->chip.base = pdev->id * 32;
+ pio->chip.ngpio = 32;
+
+ pio->chip.direction_input = direction_input;
+ pio->chip.get = gpio_get;
+ pio->chip.direction_output = direction_output;
+ pio->chip.set = gpio_set;
+ pio->chip.dbg_show = pio_bank_show;
+
+ gpiochip_add(&pio->chip);
+
gpio_irq_setup(pio, irq, gpio_irq_base);
platform_set_drvdata(pdev, pio);
@@ -406,12 +424,6 @@ void __init at32_init_pio(struct platform_device *pdev)
pio->pdev = pdev;
pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
- /*
- * request_gpio() is only valid for pins that have been
- * explicitly configured as GPIO and not previously requested
- */
- pio->gpio_mask = ~0UL;
-
/* start with irqs disabled and acked */
pio_writel(pio, IDR, ~0UL);
(void) pio_readl(pio, ISR);
diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h
index 50fa3aca32c..7795116a483 100644
--- a/arch/avr32/mach-at32ap/pio.h
+++ b/arch/avr32/mach-at32ap/pio.h
@@ -19,7 +19,7 @@
#define PIO_OSR 0x0018
#define PIO_IFER 0x0020
#define PIO_IFDR 0x0024
-#define PIO_ISFR 0x0028
+#define PIO_IFSR 0x0028
#define PIO_SODR 0x0030
#define PIO_CODR 0x0034
#define PIO_ODSR 0x0038
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index ba21e33b8b1..589c6aca480 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -24,6 +24,7 @@ config RWSEM_XCHGADD_ALGORITHM
config BLACKFIN
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
config ZONE_DMA
@@ -544,7 +545,7 @@ config EXCPT_IRQ_SYSC_L1
default y
help
If enabled, the entire ASM lowlevel exception and interrupt entry code
- (STORE/RESTORE CONTEXT) is linked into L1 instruction memory.
+ (STORE/RESTORE CONTEXT) is linked into L1 instruction memory.
(less latency)
config DO_IRQ_L1
@@ -904,29 +905,38 @@ config ARCH_SUSPEND_POSSIBLE
depends on !SMP
choice
- prompt "Select PM Wakeup Event Source"
- default PM_WAKEUP_GPIO_BY_SIC_IWR
+ prompt "Default Power Saving Mode"
depends on PM
- help
- If you have a GPIO already configured as input with the corresponding PORTx_MASK
- bit set - "Specify Wakeup Event by SIC_IWR value"
+ default PM_BFIN_SLEEP_DEEPER
+config PM_BFIN_SLEEP_DEEPER
+ bool "Sleep Deeper"
+ help
+ Sleep "Deeper" Mode (High Power Savings) - This mode reduces dynamic
+ power dissipation by disabling the clock to the processor core (CCLK).
+ Furthermore, Standby sets the internal power supply voltage (VDDINT)
+ to 0.85 V to provide the greatest power savings, while preserving the
+ processor state.
+ The PLL and system clock (SCLK) continue to operate at a very low
+ frequency of about 3.3 MHz. To preserve data integrity in the SDRAM,
+ the SDRAM is put into Self Refresh Mode. Typically an external event
+ such as GPIO interrupt or RTC activity wakes up the processor.
+ Various Peripherals such as UART, SPORT, PPI may not function as
+ normal during Sleep Deeper, due to the reduced SCLK frequency.
+ When in the sleep mode, system DMA access to L1 memory is not supported.
+
+config PM_BFIN_SLEEP
+ bool "Sleep"
+ help
+ Sleep Mode (High Power Savings) - The sleep mode reduces power
+ dissipation by disabling the clock to the processor core (CCLK).
+ The PLL and system clock (SCLK), however, continue to operate in
+ this mode. Typically an external event or RTC activity will wake
+ up the processor. When in the sleep mode,
+ system DMA access to L1 memory is not supported.
+endchoice
-config PM_WAKEUP_GPIO_BY_SIC_IWR
- bool "Specify Wakeup Event by SIC_IWR value"
config PM_WAKEUP_BY_GPIO
bool "Cause Wakeup Event by GPIO"
-config PM_WAKEUP_GPIO_API
- bool "Configure Wakeup Event by PM GPIO API"
-
-endchoice
-
-config PM_WAKEUP_SIC_IWR
- hex "Wakeup Events (SIC_IWR)"
- depends on PM_WAKEUP_GPIO_BY_SIC_IWR
- default 0x8 if (BF537 || BF536 || BF534)
- default 0x80 if (BF533 || BF532 || BF531)
- default 0x80 if (BF54x)
- default 0x80 if (BF52x)
config PM_WAKEUP_GPIO_NUMBER
int "Wakeup GPIO number"
diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug
index 59b87a483c6..c61bdebb997 100644
--- a/arch/blackfin/Kconfig.debug
+++ b/arch/blackfin/Kconfig.debug
@@ -164,7 +164,7 @@ config DUAL_CORE_TEST_MODULE
config CPLB_INFO
bool "Display the CPLB information"
help
- Display the CPLB information.
+ Display the CPLB information via /proc/cplbinfo.
config ACCESS_CHECK
bool "Check the user pointer address"
diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
index 0edc402fef5..fe254f886a6 100644
--- a/arch/blackfin/Makefile
+++ b/arch/blackfin/Makefile
@@ -119,6 +119,7 @@ archclean:
$(Q)$(MAKE) $(clean)=$(boot)
+INSTALL_PATH ?= /tftpboot
boot := arch/$(ARCH)/boot
BOOT_TARGETS = vmImage
PHONY += $(BOOT_TARGETS) install
diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
index 9b7123cf27a..198f4123af4 100644
--- a/arch/blackfin/configs/BF533-STAMP_defconfig
+++ b/arch/blackfin/configs/BF533-STAMP_defconfig
@@ -216,8 +216,6 @@ CONFIG_MEM_SIZE=128
CONFIG_MEM_ADD_WIDTH=11
CONFIG_ENET_FLASH_PIN=0
CONFIG_BOOT_LOAD=0x1000
-
-
CONFIG_BFIN_SCRATCH_REG_RETN=y
# CONFIG_BFIN_SCRATCH_REG_RETE is not set
# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
@@ -483,7 +481,7 @@ CONFIG_MTD=y
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
#
# User Modules And Translation Layers
@@ -500,8 +498,8 @@ CONFIG_MTD_BLOCK=y
#
# RAM/ROM/Flash chip drivers
#
-# CONFIG_MTD_CFI is not set
-CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_CFI=m
+# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=m
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
@@ -515,8 +513,9 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
-# CONFIG_MTD_CFI_AMDSTD is not set
+CONFIG_MTD_CFI_AMDSTD=m
# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=m
CONFIG_MTD_RAM=y
CONFIG_MTD_ROM=m
# CONFIG_MTD_ABSENT is not set
@@ -526,6 +525,11 @@ CONFIG_MTD_ROM=m
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_BF5xx=m
+CONFIG_BFIN_FLASH_BANK_0=0x7BB0
+CONFIG_BFIN_FLASH_BANK_1=0x7BB0
+CONFIG_BFIN_FLASH_BANK_2=0x7BB0
+CONFIG_BFIN_FLASH_BANK_3=0x7BB0
# CONFIG_MTD_UCLINUX is not set
# CONFIG_MTD_PLATRAM is not set
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index fa9debe8d5f..5453bc3664f 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -104,6 +104,16 @@ int request_dma(unsigned int channel, char *device_id)
mutex_unlock(&(dma_ch[channel].dmalock));
+#ifdef CONFIG_BF54x
+ if (channel >= CH_UART2_RX && channel <= CH_UART3_TX &&
+ strncmp(device_id, "BFIN_UART", 9) == 0)
+ dma_ch[channel].regs->peripheral_map |=
+ (channel - CH_UART2_RX + 0xC);
+ else
+ dma_ch[channel].regs->peripheral_map |=
+ (channel - CH_UART2_RX + 0x6);
+#endif
+
dma_ch[channel].device_id = device_id;
dma_ch[channel].irq_callback = NULL;
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index 6bbe0a2fccb..08788f7bbfb 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -186,7 +186,7 @@ static struct str_ident {
char name[RESOURCE_LABEL_SIZE];
} str_ident[MAX_RESOURCES];
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && !defined(CONFIG_BF54x)
static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
@@ -696,9 +696,8 @@ static int bfin_gpio_wakeup_type(unsigned gpio, unsigned char type)
return 0;
}
-u32 gpio_pm_setup(void)
+u32 bfin_pm_setup(void)
{
- u32 sic_iwr = 0;
u16 bank, mask, i, gpio;
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
@@ -723,7 +722,8 @@ u32 gpio_pm_setup(void)
gpio = i;
while (mask) {
- if (mask & 1) {
+ if ((mask & 1) && (wakeup_flags_map[gpio] !=
+ PM_WAKE_IGNORE)) {
reserved_gpio_map[gpio_bank(gpio)] |=
gpio_bit(gpio);
bfin_gpio_wakeup_type(gpio,
@@ -734,21 +734,17 @@ u32 gpio_pm_setup(void)
mask >>= 1;
}
- sic_iwr |= 1 <<
- (sic_iwr_irqs[bank] - (IRQ_CORETMR + 1));
+ bfin_internal_set_wake(sic_iwr_irqs[bank], 1);
gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)];
}
}
AWA_DUMMY_READ(maskb_set);
- if (sic_iwr)
- return sic_iwr;
- else
- return IWR_ENABLE_ALL;
+ return 0;
}
-void gpio_pm_restore(void)
+void bfin_pm_restore(void)
{
u16 bank, mask, i;
@@ -768,7 +764,7 @@ void gpio_pm_restore(void)
reserved_gpio_map[bank] =
gpio_bank_saved[bank].reserved;
-
+ bfin_internal_set_wake(sic_iwr_irqs[bank], 0);
}
gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb;
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
index e2e2b5079f5..dc6e8a7a8bd 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
@@ -26,6 +26,10 @@
#include <asm/cplb.h>
#include <asm/cplbinit.h>
+#if ANOMALY_05000263
+# error the MPU will not function safely while Anomaly 05000263 applies
+#endif
+
struct cplb_entry icplb_tbl[MAX_CPLBS];
struct cplb_entry dcplb_tbl[MAX_CPLBS];
diff --git a/arch/blackfin/kernel/init_task.c b/arch/blackfin/kernel/init_task.c
index 673c860ffc2..c640154030e 100644
--- a/arch/blackfin/kernel/init_task.c
+++ b/arch/blackfin/kernel/init_task.c
@@ -57,5 +57,5 @@ EXPORT_SYMBOL(init_task);
* "init_task" linker map entry.
*/
union thread_union init_thread_union
- __attribute__ ((__section__(".data.init_task"))) = {
+ __attribute__ ((__section__(".init_task.data"))) = {
INIT_THREAD_INFO(init_task)};
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 023dc80af18..6b8459c6616 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -31,7 +31,6 @@
#include <linux/smp_lock.h>
#include <linux/unistd.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/err.h>
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 462cae89375..8229b1090eb 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -1,30 +1,11 @@
/*
- * File: arch/blackfin/kernel/setup.c
- * Based on:
- * Author:
+ * arch/blackfin/kernel/setup.c
*
- * Created:
- * Description:
+ * Copyright 2004-2006 Analog Devices Inc.
*
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.org/
*
- * Bugs: Enter bugs at http://blackfin.uclinux.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.
- *
- * 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, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Licensed under the GPL-2 or later.
*/
#include <linux/delay.h>
@@ -34,6 +15,7 @@
#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/tty.h>
+#include <linux/pfn.h>
#include <linux/ext2_fs.h>
#include <linux/cramfs_fs.h>
@@ -47,6 +29,8 @@
#include <asm/fixed_code.h>
#include <asm/early_printk.h>
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
u16 _bfin_swrst;
unsigned long memory_start, memory_end, physical_mem_end;
@@ -67,6 +51,29 @@ EXPORT_SYMBOL(mtd_size);
char __initdata command_line[COMMAND_LINE_SIZE];
+/* boot memmap, for parsing "memmap=" */
+#define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */
+#define BFIN_MEMMAP_RAM 1
+#define BFIN_MEMMAP_RESERVED 2
+struct bfin_memmap {
+ int nr_map;
+ struct bfin_memmap_entry {
+ unsigned long long addr; /* start of memory segment */
+ unsigned long long size;
+ unsigned long type;
+ } map[BFIN_MEMMAP_MAX];
+} bfin_memmap __initdata;
+
+/* for memmap sanitization */
+struct change_member {
+ struct bfin_memmap_entry *pentry; /* pointer to original entry */
+ unsigned long long addr; /* address for this change point */
+};
+static struct change_member change_point_list[2*BFIN_MEMMAP_MAX] __initdata;
+static struct change_member *change_point[2*BFIN_MEMMAP_MAX] __initdata;
+static struct bfin_memmap_entry *overlap_list[BFIN_MEMMAP_MAX] __initdata;
+static struct bfin_memmap_entry new_map[BFIN_MEMMAP_MAX] __initdata;
+
void __init bf53x_cache_init(void)
{
#if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE)
@@ -123,12 +130,224 @@ void __init bf53x_relocate_l1_mem(void)
}
+/* add_memory_region to memmap */
+static void __init add_memory_region(unsigned long long start,
+ unsigned long long size, int type)
+{
+ int i;
+
+ i = bfin_memmap.nr_map;
+
+ if (i == BFIN_MEMMAP_MAX) {
+ printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+ return;
+ }
+
+ bfin_memmap.map[i].addr = start;
+ bfin_memmap.map[i].size = size;
+ bfin_memmap.map[i].type = type;
+ bfin_memmap.nr_map++;
+}
+
+/*
+ * Sanitize the boot memmap, removing overlaps.
+ */
+static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
+{
+ struct change_member *change_tmp;
+ unsigned long current_type, last_type;
+ unsigned long long last_addr;
+ int chgidx, still_changing;
+ int overlap_entries;
+ int new_entry;
+ int old_nr, new_nr, chg_nr;
+ int i;
+
+ /*
+ Visually we're performing the following (1,2,3,4 = memory types)
+
+ Sample memory map (w/overlaps):
+ ____22__________________
+ ______________________4_
+ ____1111________________
+ _44_____________________
+ 11111111________________
+ ____________________33__
+ ___________44___________
+ __________33333_________
+ ______________22________
+ ___________________2222_
+ _________111111111______
+ _____________________11_
+ _________________4______
+
+ Sanitized equivalent (no overlap):
+ 1_______________________
+ _44_____________________
+ ___1____________________
+ ____22__________________
+ ______11________________
+ _________1______________
+ __________3_____________
+ ___________44___________
+ _____________33_________
+ _______________2________
+ ________________1_______
+ _________________4______
+ ___________________2____
+ ____________________33__
+ ______________________4_
+ */
+ /* if there's only one memory region, don't bother */
+ if (*pnr_map < 2)
+ return -1;
+
+ old_nr = *pnr_map;
+
+ /* bail out if we find any unreasonable addresses in memmap */
+ for (i = 0; i < old_nr; i++)
+ if (map[i].addr + map[i].size < map[i].addr)
+ return -1;
+
+ /* create pointers for initial change-point information (for sorting) */
+ for (i = 0; i < 2*old_nr; i++)
+ change_point[i] = &change_point_list[i];
+
+ /* record all known change-points (starting and ending addresses),
+ omitting those that are for empty memory regions */
+ chgidx = 0;
+ for (i = 0; i < old_nr; i++) {
+ if (map[i].size != 0) {
+ change_point[chgidx]->addr = map[i].addr;
+ change_point[chgidx++]->pentry = &map[i];
+ change_point[chgidx]->addr = map[i].addr + map[i].size;
+ change_point[chgidx++]->pentry = &map[i];
+ }
+ }
+ chg_nr = chgidx; /* true number of change-points */
+
+ /* sort change-point list by memory addresses (low -> high) */
+ still_changing = 1;
+ while (still_changing) {
+ still_changing = 0;
+ for (i = 1; i < chg_nr; i++) {
+ /* if <current_addr> > <last_addr>, swap */
+ /* or, if current=<start_addr> & last=<end_addr>, swap */
+ if ((change_point[i]->addr < change_point[i-1]->addr) ||
+ ((change_point[i]->addr == change_point[i-1]->addr) &&
+ (change_point[i]->addr == change_point[i]->pentry->addr) &&
+ (change_point[i-1]->addr != change_point[i-1]->pentry->addr))
+ ) {
+ change_tmp = change_point[i];
+ change_point[i] = change_point[i-1];
+ change_point[i-1] = change_tmp;
+ still_changing = 1;
+ }
+ }
+ }
+
+ /* create a new memmap, removing overlaps */
+ overlap_entries = 0; /* number of entries in the overlap table */
+ new_entry = 0; /* index for creating new memmap entries */
+ last_type = 0; /* start with undefined memory type */
+ last_addr = 0; /* start with 0 as last starting address */
+ /* loop through change-points, determining affect on the new memmap */
+ for (chgidx = 0; chgidx < chg_nr; chgidx++) {
+ /* keep track of all overlapping memmap entries */
+ if (change_point[chgidx]->addr == change_point[chgidx]->pentry->addr) {
+ /* add map entry to overlap list (> 1 entry implies an overlap) */
+ overlap_list[overlap_entries++] = change_point[chgidx]->pentry;
+ } else {
+ /* remove entry from list (order independent, so swap with last) */
+ for (i = 0; i < overlap_entries; i++) {
+ if (overlap_list[i] == change_point[chgidx]->pentry)
+ overlap_list[i] = overlap_list[overlap_entries-1];
+ }
+ overlap_entries--;
+ }
+ /* if there are overlapping entries, decide which "type" to use */
+ /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
+ current_type = 0;
+ for (i = 0; i < overlap_entries; i++)
+ if (overlap_list[i]->type > current_type)
+ current_type = overlap_list[i]->type;
+ /* continue building up new memmap based on this information */
+ if (current_type != last_type) {
+ if (last_type != 0) {
+ new_map[new_entry].size =
+ change_point[chgidx]->addr - last_addr;
+ /* move forward only if the new size was non-zero */
+ if (new_map[new_entry].size != 0)
+ if (++new_entry >= BFIN_MEMMAP_MAX)
+ break; /* no more space left for new entries */
+ }
+ if (current_type != 0) {
+ new_map[new_entry].addr = change_point[chgidx]->addr;
+ new_map[new_entry].type = current_type;
+ last_addr = change_point[chgidx]->addr;
+ }
+ last_type = current_type;
+ }
+ }
+ new_nr = new_entry; /* retain count for new entries */
+
+ /* copy new mapping into original location */
+ memcpy(map, new_map, new_nr*sizeof(struct bfin_memmap_entry));
+ *pnr_map = new_nr;
+
+ return 0;
+}
+
+static void __init print_memory_map(char *who)
+{
+ int i;
+
+ for (i = 0; i < bfin_memmap.nr_map; i++) {
+ printk(KERN_DEBUG " %s: %016Lx - %016Lx ", who,
+ bfin_memmap.map[i].addr,
+ bfin_memmap.map[i].addr + bfin_memmap.map[i].size);
+ switch (bfin_memmap.map[i].type) {
+ case BFIN_MEMMAP_RAM:
+ printk("(usable)\n");
+ break;
+ case BFIN_MEMMAP_RESERVED:
+ printk("(reserved)\n");
+ break;
+ default: printk("type %lu\n", bfin_memmap.map[i].type);
+ break;
+ }
+ }
+}
+
+static __init int parse_memmap(char *arg)
+{
+ unsigned long long start_at, mem_size;
+
+ if (!arg)
+ return -EINVAL;
+
+ mem_size = memparse(arg, &arg);
+ if (*arg == '@') {
+ start_at = memparse(arg+1, &arg);
+ add_memory_region(start_at, mem_size, BFIN_MEMMAP_RAM);
+ } else if (*arg == '$') {
+ start_at = memparse(arg+1, &arg);
+ add_memory_region(start_at, mem_size, BFIN_MEMMAP_RESERVED);
+ }
+
+ return 0;
+}
+
/*
* Initial parsing of the command line. Currently, we support:
* - Controlling the linux memory size: mem=xxx[KMG]
* - Controlling the physical memory size: max_mem=xxx[KMG][$][#]
* $ -> reserved memory is dcacheable
* # -> reserved memory is icacheable
+ * - "memmap=XXX[KkmM][@][$]XXX[KkmM]" defines a memory region
+ * @ from <start> to <start>+<mem>, type RAM
+ * $ from <start> to <start>+<mem>, type RESERVED
+ *
*/
static __init void parse_cmdline_early(char *cmdline_p)
{
@@ -136,7 +355,6 @@ static __init void parse_cmdline_early(char *cmdline_p)
unsigned int memsize;
for (;;) {
if (c == ' ') {
-
if (!memcmp(to, "mem=", 4)) {
to += 4;
memsize = memparse(to, &to);
@@ -162,6 +380,9 @@ static __init void parse_cmdline_early(char *cmdline_p)
} else if (!memcmp(to, "earlyprintk=", 12)) {
to += 12;
setup_early_printk(to);
+ } else if (!memcmp(to, "memmap=", 7)) {
+ to += 7;
+ parse_memmap(to);
}
}
c = *(to++);
@@ -170,75 +391,36 @@ static __init void parse_cmdline_early(char *cmdline_p)
}
}
-void __init setup_arch(char **cmdline_p)
+/*
+ * Setup memory defaults from user config.
+ * The physical memory layout looks like:
+ *
+ * [_rambase, _ramstart]: kernel image
+ * [memory_start, memory_end]: dynamic memory managed by kernel
+ * [memory_end, _ramend]: reserved memory
+ * [meory_mtd_start(memory_end),
+ * memory_mtd_start + mtd_size]: rootfs (if any)
+ * [_ramend - DMA_UNCACHED_REGION,
+ * _ramend]: uncached DMA region
+ * [_ramend, physical_mem_end]: memory not managed by kernel
+ *
+ */
+static __init void memory_setup(void)
{
- int bootmap_size;
- unsigned long l1_length, sclk, cclk;
#ifdef CONFIG_MTD_UCLINUX
unsigned long mtd_phys = 0;
#endif
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
-
-#if defined(CONFIG_CMDLINE_BOOL)
- strncpy(&command_line[0], CONFIG_CMDLINE, sizeof(command_line));
- command_line[sizeof(command_line) - 1] = 0;
-#endif
-
- /* Keep a copy of command line */
- *cmdline_p = &command_line[0];
- memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
- boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
-
- /* setup memory defaults from the user config */
- physical_mem_end = 0;
- _ramend = CONFIG_MEM_SIZE * 1024 * 1024;
-
- parse_cmdline_early(&command_line[0]);
-
- cclk = get_cclk();
- sclk = get_sclk();
-
-#if !defined(CONFIG_BFIN_KERNEL_CLOCK)
- if (ANOMALY_05000273 && cclk == sclk)
- panic("ANOMALY 05000273, SCLK can not be same as CCLK");
-#endif
+ _rambase = (unsigned long)_stext;
+ _ramstart = (unsigned long)_end;
-#ifdef BF561_FAMILY
- if (ANOMALY_05000266) {
- bfin_read_IMDMA_D0_IRQ_STATUS();
- bfin_read_IMDMA_D1_IRQ_STATUS();
+ if (DMA_UNCACHED_REGION > (_ramend - _ramstart)) {
+ console_init();
+ panic("DMA region exceeds memory limit: %lu.\n",
+ _ramend - _ramstart);
}
-#endif
-
- printk(KERN_INFO "Hardware Trace ");
- if (bfin_read_TBUFCTL() & 0x1 )
- printk("Active ");
- else
- printk("Off ");
- if (bfin_read_TBUFCTL() & 0x2)
- printk("and Enabled\n");
- else
- printk("and Disabled\n");
-
-
-#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
- /* we need to initialize the Flashrom device here since we might
- * do things with flash early on in the boot
- */
- flash_probe();
-#endif
-
- if (physical_mem_end == 0)
- physical_mem_end = _ramend;
-
- /* by now the stack is part of the init task */
memory_end = _ramend - DMA_UNCACHED_REGION;
- _ramstart = (unsigned long)__bss_stop;
- _rambase = (unsigned long)_stext;
#ifdef CONFIG_MPU
/* Round up to multiple of 4MB. */
memory_start = (_ramstart + 0x3fffff) & ~0x3fffff;
@@ -292,7 +474,7 @@ void __init setup_arch(char **cmdline_p)
}
/* Relocate MTD image to the top of memory after the uncached memory area */
- dma_memcpy((char *)memory_end, __bss_stop, mtd_size);
+ dma_memcpy((char *)memory_end, _end, mtd_size);
memory_mtd_start = memory_end;
_ebss = memory_mtd_start; /* define _ebss for compatible */
@@ -319,13 +501,175 @@ void __init setup_arch(char **cmdline_p)
#endif
#if !defined(CONFIG_MTD_UCLINUX)
- memory_end -= SIZE_4K; /*In case there is no valid CPLB behind memory_end make sure we don't get to close*/
+ /*In case there is no valid CPLB behind memory_end make sure we don't get to close*/
+ memory_end -= SIZE_4K;
#endif
+
init_mm.start_code = (unsigned long)_stext;
init_mm.end_code = (unsigned long)_etext;
init_mm.end_data = (unsigned long)_edata;
init_mm.brk = (unsigned long)0;
+ printk(KERN_INFO "Board Memory: %ldMB\n", physical_mem_end >> 20);
+ printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20);
+
+ printk(KERN_INFO "Memory map:\n"
+ KERN_INFO " text = 0x%p-0x%p\n"
+ KERN_INFO " rodata = 0x%p-0x%p\n"
+ KERN_INFO " bss = 0x%p-0x%p\n"
+ KERN_INFO " data = 0x%p-0x%p\n"
+ KERN_INFO " stack = 0x%p-0x%p\n"
+ KERN_INFO " init = 0x%p-0x%p\n"
+ KERN_INFO " available = 0x%p-0x%p\n"
+#ifdef CONFIG_MTD_UCLINUX
+ KERN_INFO " rootfs = 0x%p-0x%p\n"
+#endif
+#if DMA_UNCACHED_REGION > 0
+ KERN_INFO " DMA Zone = 0x%p-0x%p\n"
+#endif
+ , _stext, _etext,
+ __start_rodata, __end_rodata,
+ __bss_start, __bss_stop,
+ _sdata, _edata,
+ (void *)&init_thread_union,
+ (void *)((int)(&init_thread_union) + 0x2000),
+ __init_begin, __init_end,
+ (void *)_ramstart, (void *)memory_end
+#ifdef CONFIG_MTD_UCLINUX
+ , (void *)memory_mtd_start, (void *)(memory_mtd_start + mtd_size)
+#endif
+#if DMA_UNCACHED_REGION > 0
+ , (void *)(_ramend - DMA_UNCACHED_REGION), (void *)(_ramend)
+#endif
+ );
+}
+
+static __init void setup_bootmem_allocator(void)
+{
+ int bootmap_size;
+ int i;
+ unsigned long min_pfn, max_pfn;
+ unsigned long curr_pfn, last_pfn, size;
+
+ /* mark memory between memory_start and memory_end usable */
+ add_memory_region(memory_start,
+ memory_end - memory_start, BFIN_MEMMAP_RAM);
+ /* sanity check for overlap */
+ sanitize_memmap(bfin_memmap.map, &bfin_memmap.nr_map);
+ print_memory_map("boot memmap");
+
+ min_pfn = PAGE_OFFSET >> PAGE_SHIFT;
+ max_pfn = memory_end >> PAGE_SHIFT;
+
+ /*
+ * give all the memory to the bootmap allocator, tell it to put the
+ * boot mem_map at the start of memory.
+ */
+ bootmap_size = init_bootmem_node(NODE_DATA(0),
+ memory_start >> PAGE_SHIFT, /* map goes here */
+ min_pfn, max_pfn);
+
+ /* register the memmap regions with the bootmem allocator */
+ for (i = 0; i < bfin_memmap.nr_map; i++) {
+ /*
+ * Reserve usable memory
+ */
+ if (bfin_memmap.map[i].type != BFIN_MEMMAP_RAM)
+ continue;
+ /*
+ * We are rounding up the start address of usable memory:
+ */
+ curr_pfn = PFN_UP(bfin_memmap.map[i].addr);
+ if (curr_pfn >= max_pfn)
+ continue;
+ /*
+ * ... and at the end of the usable range downwards:
+ */
+ last_pfn = PFN_DOWN(bfin_memmap.map[i].addr +
+ bfin_memmap.map[i].size);
+
+ if (last_pfn > max_pfn)
+ last_pfn = max_pfn;
+
+ /*
+ * .. finally, did all the rounding and playing
+ * around just make the area go away?
+ */
+ if (last_pfn <= curr_pfn)
+ continue;
+
+ size = last_pfn - curr_pfn;
+ free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+ }
+
+ /* reserve memory before memory_start, including bootmap */
+ reserve_bootmem(PAGE_OFFSET,
+ memory_start + bootmap_size + PAGE_SIZE - 1 - PAGE_OFFSET,
+ BOOTMEM_DEFAULT);
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+ unsigned long l1_length, sclk, cclk;
+
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+
+#if defined(CONFIG_CMDLINE_BOOL)
+ strncpy(&command_line[0], CONFIG_CMDLINE, sizeof(command_line));
+ command_line[sizeof(command_line) - 1] = 0;
+#endif
+
+ /* Keep a copy of command line */
+ *cmdline_p = &command_line[0];
+ memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+ boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
+
+ /* setup memory defaults from the user config */
+ physical_mem_end = 0;
+ _ramend = CONFIG_MEM_SIZE * 1024 * 1024;
+
+ memset(&bfin_memmap, 0, sizeof(bfin_memmap));
+
+ parse_cmdline_early(&command_line[0]);
+
+ if (physical_mem_end == 0)
+ physical_mem_end = _ramend;
+
+ memory_setup();
+
+ cclk = get_cclk();
+ sclk = get_sclk();
+
+#if !defined(CONFIG_BFIN_KERNEL_CLOCK)
+ if (ANOMALY_05000273 && cclk == sclk)
+ panic("ANOMALY 05000273, SCLK can not be same as CCLK");
+#endif
+
+#ifdef BF561_FAMILY
+ if (ANOMALY_05000266) {
+ bfin_read_IMDMA_D0_IRQ_STATUS();
+ bfin_read_IMDMA_D1_IRQ_STATUS();
+ }
+#endif
+ printk(KERN_INFO "Hardware Trace ");
+ if (bfin_read_TBUFCTL() & 0x1)
+ printk("Active ");
+ else
+ printk("Off ");
+ if (bfin_read_TBUFCTL() & 0x2)
+ printk("and Enabled\n");
+ else
+ printk("and Disabled\n");
+
+#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
+ /* we need to initialize the Flashrom device here since we might
+ * do things with flash early on in the boot
+ */
+ flash_probe();
+#endif
+
_bfin_swrst = bfin_read_SWRST();
if (_bfin_swrst & RESET_DOUBLE)
@@ -335,7 +679,7 @@ void __init setup_arch(char **cmdline_p)
else if (_bfin_swrst & RESET_SOFTWARE)
printk(KERN_NOTICE "Reset caused by Software reset\n");
- printk(KERN_INFO "Blackfin support (C) 2004-2007 Analog Devices, Inc.\n");
+ printk(KERN_INFO "Blackfin support (C) 2004-2008 Analog Devices, Inc.\n");
if (bfin_compiled_revid() == 0xffff)
printk(KERN_INFO "Compiled for ADSP-%s Rev any\n", CPU);
else if (bfin_compiled_revid() == -1)
@@ -361,55 +705,8 @@ void __init setup_arch(char **cmdline_p)
if (ANOMALY_05000273 && (cclk >> 1) <= sclk)
printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n");
- printk(KERN_INFO "Board Memory: %ldMB\n", physical_mem_end >> 20);
- printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20);
-
- printk(KERN_INFO "Memory map:\n"
- KERN_INFO " text = 0x%p-0x%p\n"
- KERN_INFO " rodata = 0x%p-0x%p\n"
- KERN_INFO " data = 0x%p-0x%p\n"
- KERN_INFO " stack = 0x%p-0x%p\n"
- KERN_INFO " init = 0x%p-0x%p\n"
- KERN_INFO " bss = 0x%p-0x%p\n"
- KERN_INFO " available = 0x%p-0x%p\n"
-#ifdef CONFIG_MTD_UCLINUX
- KERN_INFO " rootfs = 0x%p-0x%p\n"
-#endif
-#if DMA_UNCACHED_REGION > 0
- KERN_INFO " DMA Zone = 0x%p-0x%p\n"
-#endif
- , _stext, _etext,
- __start_rodata, __end_rodata,
- _sdata, _edata,
- (void *)&init_thread_union, (void *)((int)(&init_thread_union) + 0x2000),
- __init_begin, __init_end,
- __bss_start, __bss_stop,
- (void *)_ramstart, (void *)memory_end
-#ifdef CONFIG_MTD_UCLINUX
- , (void *)memory_mtd_start, (void *)(memory_mtd_start + mtd_size)
-#endif
-#if DMA_UNCACHED_REGION > 0
- , (void *)(_ramend - DMA_UNCACHED_REGION), (void *)(_ramend)
-#endif
- );
+ setup_bootmem_allocator();
- /*
- * give all the memory to the bootmap allocator, tell it to put the
- * boot mem_map at the start of memory
- */
- bootmap_size = init_bootmem_node(NODE_DATA(0), memory_start >> PAGE_SHIFT, /* map goes here */
- PAGE_OFFSET >> PAGE_SHIFT,
- memory_end >> PAGE_SHIFT);
- /*
- * free the usable memory, we have to make sure we do not free
- * the bootmem bitmap so we then reserve it after freeing it :-)
- */
- free_bootmem(memory_start, memory_end - memory_start);
-
- reserve_bootmem(memory_start, bootmap_size);
- /*
- * get kmalloc into gear
- */
paging_init();
/* check the size of the l1 area */
@@ -450,15 +747,15 @@ void __init setup_arch(char **cmdline_p)
static int __init topology_init(void)
{
-#if defined (CONFIG_BF561)
- static struct cpu cpu[2];
- register_cpu(&cpu[0], 0);
- register_cpu(&cpu[1], 1);
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ struct cpu *c = &per_cpu(cpu_devices, cpu);
+
+ register_cpu(c, cpu);
+ }
+
return 0;
-#else
- static struct cpu cpu[1];
- return register_cpu(cpu, 0);
-#endif
}
subsys_initcall(topology_init);
@@ -700,7 +997,7 @@ static void c_stop(struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index 5bd64e341df..9bdc8f99183 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -137,9 +137,6 @@ irqreturn_t timer_interrupt(int irq, void *dummy)
do_timer(1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
profile_tick(CPU_PROFILING);
/*
@@ -161,6 +158,11 @@ irqreturn_t timer_interrupt(int irq, void *dummy)
last_rtc_update = xtime.tv_sec - 600;
}
write_sequnlock(&xtime_lock);
+
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(get_irq_regs()));
+#endif
+
return IRQ_HANDLED;
}
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 66b5f3e3ae2..56a67ab698c 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -126,15 +126,13 @@ static void decode_address(char *buf, unsigned long address)
struct vm_area_struct *vma = vml->vma;
if (address >= vma->vm_start && address < vma->vm_end) {
+ char _tmpbuf[256];
char *name = p->comm;
struct file *file = vma->vm_file;
- if (file) {
- char _tmpbuf[256];
- name = d_path(file->f_dentry,
- file->f_vfsmnt,
- _tmpbuf,
- sizeof(_tmpbuf));
- }
+
+ if (file)
+ name = d_path(&file->f_path, _tmpbuf,
+ sizeof(_tmpbuf));
/* FLAT does not have its text aligned to the start of
* the map while FDPIC ELF does ...
@@ -649,7 +647,7 @@ void dump_bfin_process(struct pt_regs *fp)
if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)
printk(KERN_NOTICE "HW Error context\n");
else if (context & 0x0020)
- printk(KERN_NOTICE "Defered Exception context\n");
+ printk(KERN_NOTICE "Deferred Exception context\n");
else if (context & 0x3FC0)
printk(KERN_NOTICE "Interrupt context\n");
else if (context & 0x4000)
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 858722421b4..aed832540b3 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -41,6 +41,9 @@ _jiffies = _jiffies_64;
SECTIONS
{
. = CONFIG_BOOT_LOAD;
+ /* Neither the text, ro_data or bss section need to be aligned
+ * So pack them back to back
+ */
.text :
{
__text = .;
@@ -58,22 +61,25 @@ SECTIONS
*(__ex_table)
___stop___ex_table = .;
- . = ALIGN(4);
__etext = .;
}
- RO_DATA(PAGE_SIZE)
+ /* Just in case the first read only is a 32-bit access */
+ RO_DATA(4)
+
+ .bss :
+ {
+ . = ALIGN(4);
+ ___bss_start = .;
+ *(.bss .bss.*)
+ *(COMMON)
+ ___bss_stop = .;
+ }
.data :
{
- /* make sure the init_task is aligned to the
- * kernel thread size so we can locate the kernel
- * stack properly and quickly.
- */
__sdata = .;
- . = ALIGN(THREAD_SIZE);
- *(.data.init_task)
-
+ /* This gets done first, so the glob doesn't suck it in */
. = ALIGN(32);
*(.data.cacheline_aligned)
@@ -81,10 +87,22 @@ SECTIONS
*(.data.*)
CONSTRUCTORS
+ /* make sure the init_task is aligned to the
+ * kernel thread size so we can locate the kernel
+ * stack properly and quickly.
+ */
. = ALIGN(THREAD_SIZE);
+ *(.init_task.data)
+
__edata = .;
}
+ /* The init section should be last, so when we free it, it goes into
+ * the general memory pool, and (hopefully) will decrease fragmentation
+ * a tiny bit. The init section has a _requirement_ that it be
+ * PAGE_SIZE aligned
+ */
+ . = ALIGN(PAGE_SIZE);
___init_begin = .;
.init.text :
@@ -179,16 +197,7 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
___init_end = .;
- .bss :
- {
- . = ALIGN(4);
- ___bss_start = .;
- *(.bss .bss.*)
- *(COMMON)
- . = ALIGN(4);
- ___bss_stop = .;
- __end = .;
- }
+ __end =.;
STABS_DEBUG
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index f8c411a24af..337515fba61 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -37,11 +37,13 @@
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
#include <linux/usb/isp1362.h>
#endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/usb/sl811.h>
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
#include <linux/usb/musb.h>
+#endif
#include <asm/cplb.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
@@ -517,6 +519,14 @@ static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
.bits_per_word = 16,
};
#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -634,6 +644,15 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.mode = SPI_MODE_0,
},
#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
};
/* SPI controller data */
diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
index a72c7a620fa..97378b0a975 100644
--- a/arch/blackfin/mach-bf533/boards/H8606.c
+++ b/arch/blackfin/mach-bf533/boards/H8606.c
@@ -38,7 +38,7 @@
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
#include <linux/usb/isp1362.h>
#endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/irq.h>
#include <asm/dma.h>
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index 21df2f37549..886f260d935 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -34,7 +34,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/usb/isp1362.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/irq.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index c37dd45c880..2b09aa39f56 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -34,8 +34,10 @@
#include <linux/mtd/partitions.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
#include <linux/usb/isp1362.h>
-#include <linux/pata_platform.h>
+#endif
+#include <linux/ata_platform.h>
#include <linux/irq.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
@@ -134,6 +136,13 @@ static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
};
#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
{
@@ -168,6 +177,15 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.controller_data = &ad1836_spi_chip_info,
},
#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
};
/* SPI (0) */
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index ac52b040b33..a645f6fd091 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -38,7 +38,7 @@
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
#include <linux/usb/isp1362.h>
#endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/irq.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
@@ -226,6 +226,13 @@ static struct bfin5xx_spi_chip spi_mmc_chip_info = {
};
#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
{
@@ -312,6 +319,15 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.mode = SPI_MODE_2,
},
#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
};
/* SPI (0) */
@@ -423,9 +439,9 @@ static struct platform_device bfin_pata_device = {
#include <linux/gpio_keys.h>
static struct gpio_keys_button bfin_gpio_keys_table[] = {
- {BTN_0, GPIO_PF5, 1, "gpio-keys: BTN0"},
- {BTN_1, GPIO_PF6, 1, "gpio-keys: BTN1"},
- {BTN_2, GPIO_PF8, 1, "gpio-keys: BTN2"},
+ {BTN_0, GPIO_PF5, 0, "gpio-keys: BTN0"},
+ {BTN_1, GPIO_PF6, 0, "gpio-keys: BTN1"},
+ {BTN_2, GPIO_PF8, 0, "gpio-keys: BTN2"},
};
static struct gpio_keys_platform_data bfin_gpio_keys_data = {
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c
index 8703b67d5ec..f7c1f964f13 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c
@@ -36,7 +36,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/usb/isp1362.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/irq.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
index 3e52f3f5bd5..8a3397db1d2 100644
--- a/arch/blackfin/mach-bf537/boards/generic_board.c
+++ b/arch/blackfin/mach-bf537/boards/generic_board.c
@@ -38,7 +38,7 @@
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
#include <linux/usb/isp1362.h>
#endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/usb/sl811.h>
diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c
index b8bbba85af5..d71e0be3392 100644
--- a/arch/blackfin/mach-bf537/boards/minotaur.c
+++ b/arch/blackfin/mach-bf537/boards/minotaur.c
@@ -10,7 +10,7 @@
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
#include <linux/usb_isp1362.h>
#endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/usb_sl811.h>
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index 772541548b7..9e2277e0d25 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -38,7 +38,7 @@
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
#include <linux/usb/isp1362.h>
#endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/usb/sl811.h>
@@ -487,6 +487,13 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
};
#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -593,6 +600,15 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.controller_data = &spi_ad7877_chip_info,
},
#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
};
/* SPI controller data */
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 14860f04d1b..916e963e83b 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -37,7 +37,9 @@
#include <linux/spi/flash.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
#include <linux/usb/musb.h>
+#endif
#include <asm/bfin5xx_spi.h>
#include <asm/cplb.h>
#include <asm/dma.h>
@@ -420,6 +422,13 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
};
#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
static struct spi_board_info bf54x_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -445,6 +454,15 @@ static struct spi_board_info bf54x_spi_board_info[] __initdata = {
.controller_data = &spi_ad7877_chip_info,
},
#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
};
/* SPI (0) */
@@ -631,7 +649,7 @@ static struct platform_device *ezkit_devices[] __initdata = {
&ezkit_flash_device,
};
-static int __init stamp_init(void)
+static int __init ezkit_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
@@ -644,4 +662,4 @@ static int __init stamp_init(void)
return 0;
}
-arch_initcall(stamp_init);
+arch_initcall(ezkit_init);
diff --git a/arch/blackfin/mach-bf548/dma.c b/arch/blackfin/mach-bf548/dma.c
index 957bf1366ef..374803a8d2e 100644
--- a/arch/blackfin/mach-bf548/dma.c
+++ b/arch/blackfin/mach-bf548/dma.c
@@ -1,5 +1,5 @@
/*
- * File: arch/blackfin/mach-bf561/dma.c
+ * File: arch/blackfin/mach-bf548/dma.c
* Based on:
* Author:
*
@@ -7,7 +7,7 @@
* Description: This file contains the simple DMA Implementation for Blackfin
*
* Modified:
- * Copyright 2004-2007 Analog Devices Inc.
+ * Copyright 2004-2008 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index 3a79a9061bd..bf9e738a7c6 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -34,7 +34,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/usb/isp1362.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/irq.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 7601c3be1b5..43c1b098281 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -35,7 +35,7 @@
#include <linux/spi/spi.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
#include <asm/portmux.h>
@@ -92,6 +92,68 @@ void __exit bfin_isp1761_exit(void)
arch_initcall(bfin_isp1761_init);
#endif
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+#include <linux/usb/isp1362.h>
+
+static struct resource isp1362_hcd_resources[] = {
+ {
+ .start = 0x2c060000,
+ .end = 0x2c060000,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0x2c060004,
+ .end = 0x2c060004,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_PF8,
+ .end = IRQ_PF8,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct isp1362_platform_data isp1362_priv = {
+ .sel15Kres = 1,
+ .clknotstop = 0,
+ .oc_enable = 0,
+ .int_act_high = 0,
+ .int_edge_triggered = 0,
+ .remote_wakeup_connected = 0,
+ .no_power_switching = 1,
+ .power_switching_mode = 0,
+};
+
+static struct platform_device isp1362_hcd_device = {
+ .name = "isp1362-hcd",
+ .id = 0,
+ .dev = {
+ .platform_data = &isp1362_priv,
+ },
+ .num_resources = ARRAY_SIZE(isp1362_hcd_resources),
+ .resource = isp1362_hcd_resources,
+};
+#endif
+
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+static struct resource net2272_bfin_resources[] = {
+ {
+ .start = 0x2C000000,
+ .end = 0x2C000000 + 0x7F,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_PF10,
+ .end = IRQ_PF10,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+ },
+};
+
+static struct platform_device net2272_bfin_device = {
+ .name = "net2272",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(net2272_bfin_resources),
+ .resource = net2272_bfin_resources,
+};
+#endif
+
/*
* USB-LAN EzExtender board
* Driver needs to know address, irq and flag pin.
@@ -204,6 +266,13 @@ static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
.bits_per_word = 16,
};
#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
#endif
/* SPI (0) */
@@ -248,6 +317,15 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.controller_data = &ad1836_spi_chip_info,
},
#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
};
#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
@@ -340,6 +418,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
&ax88180_device,
#endif
+#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
+ &net2272_bfin_device,
+#endif
+
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
&bfin_spi0_device,
#endif
@@ -359,6 +441,11 @@ static struct platform_device *ezkit_devices[] __initdata = {
#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
&i2c_gpio_device,
#endif
+
+#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
+ &isp1362_hcd_device,
+#endif
+
&ezkit_flash_device,
};
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile
index 8636d4284bd..15e33ca1ce8 100644
--- a/arch/blackfin/mach-common/Makefile
+++ b/arch/blackfin/mach-common/Makefile
@@ -4,8 +4,6 @@
obj-y := \
cache.o cacheinit.o entry.o \
- interrupt.o lock.o irqpanic.o arch_checks.o
+ interrupt.o lock.o irqpanic.o arch_checks.o ints-priority.o
-obj-$(CONFIG_BFIN_SINGLE_CORE) += ints-priority-sc.o
-obj-$(CONFIG_BFIN_DUAL_CORE) += ints-priority-dc.o
obj-$(CONFIG_PM) += pm.o dpmc.o
diff --git a/arch/blackfin/mach-common/dpmc.S b/arch/blackfin/mach-common/dpmc.S
index b82c096e198..b80ddd8b232 100644
--- a/arch/blackfin/mach-common/dpmc.S
+++ b/arch/blackfin/mach-common/dpmc.S
@@ -191,6 +191,9 @@ ENTRY(_sleep_mode)
call _test_pll_locked;
R0 = IWR_ENABLE(0);
+ R1 = IWR_DISABLE_ALL;
+ R2 = IWR_DISABLE_ALL;
+
call _set_sic_iwr;
P0.H = hi(PLL_CTL);
@@ -237,6 +240,10 @@ ENTRY(_deep_sleep)
CLI R4;
+ R0 = IWR_ENABLE(0);
+ R1 = IWR_DISABLE_ALL;
+ R2 = IWR_DISABLE_ALL;
+
call _set_sic_iwr;
call _set_dram_srfs;
@@ -261,6 +268,9 @@ ENTRY(_deep_sleep)
call _test_pll_locked;
R0 = IWR_ENABLE(0);
+ R1 = IWR_DISABLE_ALL;
+ R2 = IWR_DISABLE_ALL;
+
call _set_sic_iwr;
P0.H = hi(PLL_CTL);
@@ -286,7 +296,13 @@ ENTRY(_sleep_deeper)
CLI R4;
P3 = R0;
+ P4 = R1;
+ P5 = R2;
+
R0 = IWR_ENABLE(0);
+ R1 = IWR_DISABLE_ALL;
+ R2 = IWR_DISABLE_ALL;
+
call _set_sic_iwr;
call _set_dram_srfs; /* Set SDRAM Self Refresh */
@@ -327,6 +343,8 @@ ENTRY(_sleep_deeper)
call _test_pll_locked;
R0 = P3;
+ R1 = P4;
+ R3 = P5;
call _set_sic_iwr; /* Set Awake from IDLE */
P0.H = hi(PLL_CTL);
@@ -340,6 +358,9 @@ ENTRY(_sleep_deeper)
call _test_pll_locked;
R0 = IWR_ENABLE(0);
+ R1 = IWR_DISABLE_ALL;
+ R2 = IWR_DISABLE_ALL;
+
call _set_sic_iwr; /* Set Awake from IDLE PLL */
P0.H = hi(VR_CTL);
@@ -417,14 +438,23 @@ ENTRY(_unset_dram_srfs)
RTS;
ENTRY(_set_sic_iwr)
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
P0.H = hi(SIC_IWR0);
P0.L = lo(SIC_IWR0);
+ P1.H = hi(SIC_IWR1);
+ P1.L = lo(SIC_IWR1);
+ [P1] = R1;
+#if defined(CONFIG_BF54x)
+ P1.H = hi(SIC_IWR2);
+ P1.L = lo(SIC_IWR2);
+ [P1] = R2;
+#endif
#else
P0.H = hi(SIC_IWR);
P0.L = lo(SIC_IWR);
#endif
[P0] = R0;
+
SSYNC;
RTS;
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 56ff51bc8c2..2cbb7a0bc38 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -121,6 +121,7 @@ ENTRY(_ex_icplb_miss)
(R7:6,P5:4) = [sp++];
ASTAT = [sp++];
SAVE_ALL_SYS
+ DEBUG_HWTRACE_SAVE(p5, r7)
#ifdef CONFIG_MPU
R0 = SEQSTAT;
R1 = SP;
@@ -132,14 +133,13 @@ ENTRY(_ex_icplb_miss)
#else
call __cplb_hdr;
#endif
- DEBUG_START_HWTRACE(p5, r7)
+ DEBUG_HWTRACE_RESTORE(p5, r7)
RESTORE_ALL_SYS
SP = EX_SCRATCH_REG;
rtx;
ENDPROC(_ex_icplb_miss)
ENTRY(_ex_syscall)
- DEBUG_START_HWTRACE(p5, r7)
(R7:6,P5:4) = [sp++];
ASTAT = [sp++];
raise 15; /* invoked by TRAP #0, for sys call */
@@ -178,7 +178,6 @@ ENTRY(_ex_single_step)
ENDPROC(_ex_single_step)
ENTRY(_bfin_return_from_exception)
- DEBUG_START_HWTRACE(p5, r7)
#if ANOMALY_05000257
R7=LC0;
LC0=R7;
@@ -200,10 +199,9 @@ ENTRY(_handle_bad_cplb)
* need to make a CPLB exception look like a normal exception
*/
- DEBUG_START_HWTRACE(p5, r7)
RESTORE_ALL_SYS
[--sp] = ASTAT;
- [--sp] = (R7:6, P5:4);
+ [--sp] = (R7:6,P5:4);
ENTRY(_ex_replaceable)
nop;
@@ -253,7 +251,6 @@ ENTRY(_ex_trap_c)
R6 = SEQSTAT;
[P5] = R6;
- DEBUG_START_HWTRACE(p5, r7)
(R7:6,P5:4) = [sp++];
ASTAT = [sp++];
SP = EX_SCRATCH_REG;
@@ -382,8 +379,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
sp.h = _exception_stack_top;
/* Try to deal with syscalls quickly. */
[--sp] = ASTAT;
- [--sp] = (R7:6, P5:4);
- DEBUG_STOP_HWTRACE(p5, r7)
+ [--sp] = (R7:6,P5:4);
r7 = SEQSTAT; /* reason code is in bit 5:0 */
r6.l = lo(SEQSTAT_EXCAUSE);
r6.h = hi(SEQSTAT_EXCAUSE);
@@ -1373,7 +1369,7 @@ ENTRY(_sys_call_table)
.long _sys_epoll_pwait
.long _sys_utimensat
.long _sys_signalfd
- .long _sys_timerfd
+ .long _sys_ni_syscall
.long _sys_eventfd /* 350 */
.long _sys_pread64
.long _sys_pwrite64
diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c
deleted file mode 100644
index 8d18d6b163b..00000000000
--- a/arch/blackfin/mach-common/ints-priority-dc.c
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * File: arch/blackfin/mach-common/ints-priority-dc.c
- * Based on:
- * Author:
- *
- * Created: ?
- * Description: Set up the interrupt priorities
- *
- * Modified:
- * 1996 Roman Zippel
- * 1999 D. Jeff Dionne <jeff@uclinux.org>
- * 2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca>
- * 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
- * 2003 Metrowerks/Motorola
- * 2003 Bas Vermeulen <bas@buyways.nl>
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.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.
- *
- * 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, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/module.h>
-#include <linux/kernel_stat.h>
-#include <linux/seq_file.h>
-#include <linux/irq.h>
-#ifdef CONFIG_KGDB
-#include <linux/kgdb.h>
-#endif
-#include <asm/traps.h>
-#include <asm/blackfin.h>
-#include <asm/gpio.h>
-#include <asm/irq_handler.h>
-
-/*
- * NOTES:
- * - we have separated the physical Hardware interrupt from the
- * levels that the LINUX kernel sees (see the description in irq.h)
- * -
- */
-
-/* Initialize this to an actual value to force it into the .data
- * section so that we know it is properly initialized at entry into
- * the kernel but before bss is initialized to zero (which is where
- * it would live otherwise). The 0x1f magic represents the IRQs we
- * cannot actually mask out in hardware.
- */
-unsigned long irq_flags = 0x1f;
-
-/* The number of spurious interrupts */
-atomic_t num_spurious;
-
-struct ivgx {
- /* irq number for request_irq, available in mach-bf561/irq.h */
- int irqno;
- /* corresponding bit in the SICA_ISR0 register */
- int isrflag0;
- /* corresponding bit in the SICA_ISR1 register */
- int isrflag1;
-} ivg_table[NR_PERI_INTS];
-
-struct ivg_slice {
- /* position of first irq in ivg_table for given ivg */
- struct ivgx *ifirst;
- struct ivgx *istop;
-} ivg7_13[IVG13 - IVG7 + 1];
-
-static void search_IAR(void);
-
-/*
- * Search SIC_IAR and fill tables with the irqvalues
- * and their positions in the SIC_ISR register.
- */
-static void __init search_IAR(void)
-{
- unsigned ivg, irq_pos = 0;
- for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) {
- int irqn;
-
- ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos];
-
- for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
- int iar_shift = (irqn & 7) * 4;
- if (ivg ==
- (0xf &
- bfin_read32((unsigned long *)SICA_IAR0 +
- (irqn >> 3)) >> iar_shift)) {
- ivg_table[irq_pos].irqno = IVG7 + irqn;
- ivg_table[irq_pos].isrflag0 =
- (irqn < 32 ? (1 << irqn) : 0);
- ivg_table[irq_pos].isrflag1 =
- (irqn < 32 ? 0 : (1 << (irqn - 32)));
- ivg7_13[ivg].istop++;
- irq_pos++;
- }
- }
- }
-}
-
-/*
- * This is for BF561 internal IRQs
- */
-
-static void ack_noop(unsigned int irq)
-{
- /* Dummy function. */
-}
-
-static void bf561_core_mask_irq(unsigned int irq)
-{
- irq_flags &= ~(1 << irq);
- if (!irqs_disabled())
- local_irq_enable();
-}
-
-static void bf561_core_unmask_irq(unsigned int irq)
-{
- irq_flags |= 1 << irq;
- /*
- * If interrupts are enabled, IMASK must contain the same value
- * as irq_flags. Make sure that invariant holds. If interrupts
- * are currently disabled we need not do anything; one of the
- * callers will take care of setting IMASK to the proper value
- * when reenabling interrupts.
- * local_irq_enable just does "STI irq_flags", so it's exactly
- * what we need.
- */
- if (!irqs_disabled())
- local_irq_enable();
- return;
-}
-
-static void bf561_internal_mask_irq(unsigned int irq)
-{
- unsigned long irq_mask;
- if ((irq - (IRQ_CORETMR + 1)) < 32) {
- irq_mask = (1 << (irq - (IRQ_CORETMR + 1)));
- bfin_write_SICA_IMASK0(bfin_read_SICA_IMASK0() & ~irq_mask);
- } else {
- irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32));
- bfin_write_SICA_IMASK1(bfin_read_SICA_IMASK1() & ~irq_mask);
- }
-}
-
-static void bf561_internal_unmask_irq(unsigned int irq)
-{
- unsigned long irq_mask;
-
- if ((irq - (IRQ_CORETMR + 1)) < 32) {
- irq_mask = (1 << (irq - (IRQ_CORETMR + 1)));
- bfin_write_SICA_IMASK0(bfin_read_SICA_IMASK0() | irq_mask);
- } else {
- irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32));
- bfin_write_SICA_IMASK1(bfin_read_SICA_IMASK1() | irq_mask);
- }
- SSYNC();
-}
-
-static struct irq_chip bf561_core_irqchip = {
- .ack = ack_noop,
- .mask = bf561_core_mask_irq,
- .unmask = bf561_core_unmask_irq,
-};
-
-static struct irq_chip bf561_internal_irqchip = {
- .ack = ack_noop,
- .mask = bf561_internal_mask_irq,
- .unmask = bf561_internal_unmask_irq,
-};
-
-static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
-static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
-
-static void bf561_gpio_ack_irq(unsigned int irq)
-{
- u16 gpionr = irq - IRQ_PF0;
-
- if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
- set_gpio_data(gpionr, 0);
- SSYNC();
- }
-}
-
-static void bf561_gpio_mask_ack_irq(unsigned int irq)
-{
- u16 gpionr = irq - IRQ_PF0;
-
- if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
- set_gpio_data(gpionr, 0);
- SSYNC();
- }
-
- set_gpio_maska(gpionr, 0);
- SSYNC();
-}
-
-static void bf561_gpio_mask_irq(unsigned int irq)
-{
- set_gpio_maska(irq - IRQ_PF0, 0);
- SSYNC();
-}
-
-static void bf561_gpio_unmask_irq(unsigned int irq)
-{
- set_gpio_maska(irq - IRQ_PF0, 1);
- SSYNC();
-}
-
-static unsigned int bf561_gpio_irq_startup(unsigned int irq)
-{
- unsigned int ret;
- char buf[8];
- u16 gpionr = irq - IRQ_PF0;
-
- if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
- snprintf(buf, sizeof buf, "IRQ %d", irq);
- ret = gpio_request(gpionr, buf);
- if (ret)
- return ret;
-
- }
-
- gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
- bf561_gpio_unmask_irq(irq);
-
- return ret;
-
-}
-
-static void bf561_gpio_irq_shutdown(unsigned int irq)
-{
- bf561_gpio_mask_irq(irq);
- gpio_free(irq - IRQ_PF0);
- gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0);
-}
-
-static int bf561_gpio_irq_type(unsigned int irq, unsigned int type)
-{
-
- unsigned int ret;
- char buf[8];
- u16 gpionr = irq - IRQ_PF0;
-
-
- if (type == IRQ_TYPE_PROBE) {
- /* only probe unenabled GPIO interrupt lines */
- if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))
- return 0;
- type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
-
- }
-
- if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
- IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-
- if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
- snprintf(buf, sizeof buf, "IRQ %d", irq);
- ret = gpio_request(gpionr, buf);
- if (ret)
- return ret;
-
- }
-
- gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
- } else {
- gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
- return 0;
- }
-
-
- set_gpio_dir(gpionr, 0);
- set_gpio_inen(gpionr, 1);
-
-
- if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
- gpio_edge_triggered[gpio_bank(gpionr)] |= gpio_bit(gpionr);
- set_gpio_edge(gpionr, 1);
- } else {
- set_gpio_edge(gpionr, 0);
- gpio_edge_triggered[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
- }
-
- if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
- == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
- set_gpio_both(gpionr, 1);
- else
- set_gpio_both(gpionr, 0);
-
- if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
- set_gpio_polar(gpionr, 1); /* low or falling edge denoted by one */
- else
- set_gpio_polar(gpionr, 0); /* high or rising edge denoted by zero */
-
- SSYNC();
-
- if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
- set_irq_handler(irq, handle_edge_irq);
- else
- set_irq_handler(irq, handle_level_irq);
-
- return 0;
-}
-
-static struct irq_chip bf561_gpio_irqchip = {
- .ack = bf561_gpio_ack_irq,
- .mask = bf561_gpio_mask_irq,
- .mask_ack = bf561_gpio_mask_ack_irq,
- .unmask = bf561_gpio_unmask_irq,
- .set_type = bf561_gpio_irq_type,
- .startup = bf561_gpio_irq_startup,
- .shutdown = bf561_gpio_irq_shutdown
-};
-
-static void bf561_demux_gpio_irq(unsigned int inta_irq,
- struct irq_desc *intb_desc)
-{
- int irq, flag_d, mask;
- u16 gpio;
-
- switch (inta_irq) {
- case IRQ_PROG0_INTA:
- irq = IRQ_PF0;
- break;
- case IRQ_PROG1_INTA:
- irq = IRQ_PF16;
- break;
- case IRQ_PROG2_INTA:
- irq = IRQ_PF32;
- break;
- default:
- dump_stack();
- return;
- }
-
- gpio = irq - IRQ_PF0;
-
- flag_d = get_gpiop_data(gpio);
- mask = flag_d & (gpio_enabled[gpio_bank(gpio)] &
- get_gpiop_maska(gpio));
-
- do {
- if (mask & 1) {
- struct irq_desc *desc = irq_desc + irq;
- desc->handle_irq(irq, desc);
- }
- irq++;
- mask >>= 1;
- } while (mask);
-
-
-}
-
-void __init init_exception_vectors(void)
-{
- SSYNC();
-
- /* cannot program in software:
- * evt0 - emulation (jtag)
- * evt1 - reset
- */
- bfin_write_EVT2(evt_nmi);
- bfin_write_EVT3(trap);
- bfin_write_EVT5(evt_ivhw);
- bfin_write_EVT6(evt_timer);
- bfin_write_EVT7(evt_evt7);
- bfin_write_EVT8(evt_evt8);
- bfin_write_EVT9(evt_evt9);
- bfin_write_EVT10(evt_evt10);
- bfin_write_EVT11(evt_evt11);
- bfin_write_EVT12(evt_evt12);
- bfin_write_EVT13(evt_evt13);
- bfin_write_EVT14(evt14_softirq);
- bfin_write_EVT15(evt_system_call);
- CSYNC();
-}
-
-/*
- * This function should be called during kernel startup to initialize
- * the BFin IRQ handling routines.
- */
-int __init init_arch_irq(void)
-{
- int irq;
- unsigned long ilat = 0;
- /* Disable all the peripheral intrs - page 4-29 HW Ref manual */
- bfin_write_SICA_IMASK0(SIC_UNMASK_ALL);
- bfin_write_SICA_IMASK1(SIC_UNMASK_ALL);
- SSYNC();
-
- bfin_write_SICA_IWR0(IWR_ENABLE_ALL);
- bfin_write_SICA_IWR1(IWR_ENABLE_ALL);
-
- local_irq_disable();
-
- init_exception_buff();
-
- for (irq = 0; irq <= SYS_IRQS; irq++) {
- if (irq <= IRQ_CORETMR)
- set_irq_chip(irq, &bf561_core_irqchip);
- else
- set_irq_chip(irq, &bf561_internal_irqchip);
-
- if ((irq != IRQ_PROG0_INTA) &&
- (irq != IRQ_PROG1_INTA) &&
- (irq != IRQ_PROG2_INTA))
- set_irq_handler(irq, handle_simple_irq);
- else
- set_irq_chained_handler(irq, bf561_demux_gpio_irq);
- }
-
- for (irq = IRQ_PF0; irq <= IRQ_PF47; irq++) {
- set_irq_chip(irq, &bf561_gpio_irqchip);
- /* if configured as edge, then will be changed to do_edge_IRQ */
- set_irq_handler(irq, handle_level_irq);
- }
-
- bfin_write_IMASK(0);
- CSYNC();
- ilat = bfin_read_ILAT();
- CSYNC();
- bfin_write_ILAT(ilat);
- CSYNC();
-
- printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");
- /* IMASK=xxx is equivalent to STI xx or irq_flags=xx,
- * local_irq_enable()
- */
- program_IAR();
- /* Therefore it's better to setup IARs before interrupts enabled */
- search_IAR();
-
- /* Enable interrupts IVG7-15 */
- irq_flags = irq_flags | IMASK_IVG15 |
- IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
- IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
-
- return 0;
-}
-
-#ifdef CONFIG_DO_IRQ_L1
-__attribute__((l1_text))
-#endif
-void do_irq(int vec, struct pt_regs *fp)
-{
- if (vec == EVT_IVTMR_P) {
- vec = IRQ_CORETMR;
- } else {
- struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
- struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
- unsigned long sic_status0, sic_status1;
-
- SSYNC();
- sic_status0 = bfin_read_SICA_IMASK0() & bfin_read_SICA_ISR0();
- sic_status1 = bfin_read_SICA_IMASK1() & bfin_read_SICA_ISR1();
-
- for (;; ivg++) {
- if (ivg >= ivg_stop) {
- atomic_inc(&num_spurious);
- return;
- } else if ((sic_status0 & ivg->isrflag0) ||
- (sic_status1 & ivg->isrflag1))
- break;
- }
- vec = ivg->irqno;
- }
- asm_do_IRQ(vec, fp);
-
-#ifdef CONFIG_KGDB
- kgdb_process_breakpoint();
-#endif
-}
diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority.c
index dec42acb5de..880595afe98 100644
--- a/arch/blackfin/mach-common/ints-priority-sc.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -1,5 +1,5 @@
/*
- * File: arch/blackfin/mach-common/ints-priority-sc.c
+ * File: arch/blackfin/mach-common/ints-priority.c
* Based on:
* Author:
*
@@ -13,7 +13,7 @@
* 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
* 2003 Metrowerks/Motorola
* 2003 Bas Vermeulen <bas@buyways.nl>
- * Copyright 2004-2007 Analog Devices Inc.
+ * Copyright 2004-2008 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
@@ -69,6 +69,10 @@ unsigned long irq_flags = 0x1f;
/* The number of spurious interrupts */
atomic_t num_spurious;
+#ifdef CONFIG_PM
+unsigned long bfin_sic_iwr[3]; /* Up to 3 SIC_IWRx registers */
+#endif
+
struct ivgx {
/* irq number for request_irq, available in mach-bf533/irq.h */
unsigned int irqno;
@@ -98,8 +102,7 @@ static void __init search_IAR(void)
for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
int iar_shift = (irqn & 7) * 4;
- if (ivg ==
- (0xf &
+ if (ivg == (0xf &
#ifndef CONFIG_BF52x
bfin_read32((unsigned long *)SIC_IAR0 +
(irqn >> 3)) >> iar_shift)) {
@@ -179,6 +182,27 @@ static void bfin_internal_unmask_irq(unsigned int irq)
SSYNC();
}
+#ifdef CONFIG_PM
+int bfin_internal_set_wake(unsigned int irq, unsigned int state)
+{
+ unsigned bank, bit;
+ unsigned long flags;
+ bank = (irq - (IRQ_CORETMR + 1)) / 32;
+ bit = (irq - (IRQ_CORETMR + 1)) % 32;
+
+ local_irq_save(flags);
+
+ if (state)
+ bfin_sic_iwr[bank] |= (1 << bit);
+ else
+ bfin_sic_iwr[bank] &= ~(1 << bit);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+#endif
+
static struct irq_chip bfin_core_irqchip = {
.ack = ack_noop,
.mask = bfin_core_mask_irq,
@@ -189,6 +213,9 @@ static struct irq_chip bfin_internal_irqchip = {
.ack = ack_noop,
.mask = bfin_internal_mask_irq,
.unmask = bfin_internal_unmask_irq,
+#ifdef CONFIG_PM
+ .set_wake = bfin_internal_set_wake,
+#endif
};
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
@@ -206,8 +233,7 @@ static void bfin_generic_error_mask_irq(unsigned int irq)
if (!error_int_mask) {
local_irq_disable();
bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
- ~(1 <<
- (IRQ_GENERIC_ERROR -
+ ~(1 << (IRQ_GENERIC_ERROR -
(IRQ_CORETMR + 1))));
SSYNC();
local_irq_enable();
@@ -232,7 +258,7 @@ static struct irq_chip bfin_generic_error_irqchip = {
};
static void bfin_demux_error_irq(unsigned int int_err_irq,
- struct irq_desc *intb_desc)
+ struct irq_desc *inta_desc)
{
int irq = 0;
@@ -404,16 +430,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
return 0;
}
+ set_gpio_inen(gpionr, 0);
set_gpio_dir(gpionr, 0);
- set_gpio_inen(gpionr, 1);
-
- if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
- gpio_edge_triggered[gpio_bank(gpionr)] |= gpio_bit(gpionr);
- set_gpio_edge(gpionr, 1);
- } else {
- set_gpio_edge(gpionr, 0);
- gpio_edge_triggered[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
- }
if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
== (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
@@ -426,6 +444,18 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
else
set_gpio_polar(gpionr, 0); /* high or rising edge denoted by zero */
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+ set_gpio_edge(gpionr, 1);
+ set_gpio_inen(gpionr, 1);
+ gpio_edge_triggered[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+ set_gpio_data(gpionr, 0);
+
+ } else {
+ set_gpio_edge(gpionr, 0);
+ gpio_edge_triggered[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+ set_gpio_inen(gpionr, 1);
+ }
+
SSYNC();
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
@@ -436,6 +466,20 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
return 0;
}
+#ifdef CONFIG_PM
+int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+{
+ unsigned gpio = irq_to_gpio(irq);
+
+ if (state)
+ gpio_pm_wakeup_request(gpio, PM_WAKE_IGNORE);
+ else
+ gpio_pm_wakeup_free(gpio);
+
+ return 0;
+}
+#endif
+
static struct irq_chip bfin_gpio_irqchip = {
.ack = bfin_gpio_ack_irq,
.mask = bfin_gpio_mask_irq,
@@ -443,30 +487,87 @@ static struct irq_chip bfin_gpio_irqchip = {
.unmask = bfin_gpio_unmask_irq,
.set_type = bfin_gpio_irq_type,
.startup = bfin_gpio_irq_startup,
- .shutdown = bfin_gpio_irq_shutdown
+ .shutdown = bfin_gpio_irq_shutdown,
+#ifdef CONFIG_PM
+ .set_wake = bfin_gpio_set_wake,
+#endif
};
-static void bfin_demux_gpio_irq(unsigned int intb_irq,
- struct irq_desc *intb_desc)
+static void bfin_demux_gpio_irq(unsigned int inta_irq,
+ struct irq_desc *desc)
{
- u16 i;
- struct irq_desc *desc;
+ unsigned int i, gpio, mask, irq, search = 0;
- for (i = 0; i < MAX_BLACKFIN_GPIOS; i += 16) {
- int irq = IRQ_PF0 + i;
- int flag_d = get_gpiop_data(i);
- int mask =
- flag_d & (gpio_enabled[gpio_bank(i)] & get_gpiop_maska(i));
+ switch (inta_irq) {
+#if defined(CONFIG_BF53x)
+ case IRQ_PROG_INTA:
+ irq = IRQ_PF0;
+ search = 1;
+ break;
+# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
+ case IRQ_MAC_RX:
+ irq = IRQ_PH0;
+ break;
+# endif
+#elif defined(CONFIG_BF52x)
+ case IRQ_PORTF_INTA:
+ irq = IRQ_PF0;
+ break;
+ case IRQ_PORTG_INTA:
+ irq = IRQ_PG0;
+ break;
+ case IRQ_PORTH_INTA:
+ irq = IRQ_PH0;
+ break;
+#elif defined(CONFIG_BF561)
+ case IRQ_PROG0_INTA:
+ irq = IRQ_PF0;
+ break;
+ case IRQ_PROG1_INTA:
+ irq = IRQ_PF16;
+ break;
+ case IRQ_PROG2_INTA:
+ irq = IRQ_PF32;
+ break;
+#endif
+ default:
+ BUG();
+ return;
+ }
- while (mask) {
- if (mask & 1) {
- desc = irq_desc + irq;
- desc->handle_irq(irq, desc);
+ if (search) {
+ for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
+ irq += i;
+
+ mask = get_gpiop_data(i) &
+ (gpio_enabled[gpio_bank(i)] &
+ get_gpiop_maska(i));
+
+ while (mask) {
+ if (mask & 1) {
+ desc = irq_desc + irq;
+ desc->handle_irq(irq, desc);
+ }
+ irq++;
+ mask >>= 1;
}
- irq++;
- mask >>= 1;
}
+ } else {
+ gpio = irq_to_gpio(irq);
+ mask = get_gpiop_data(gpio) &
+ (gpio_enabled[gpio_bank(gpio)] &
+ get_gpiop_maska(gpio));
+
+ do {
+ if (mask & 1) {
+ desc = irq_desc + irq;
+ desc->handle_irq(irq, desc);
+ }
+ irq++;
+ mask >>= 1;
+ } while (mask);
}
+
}
#else /* CONFIG_BF54x */
@@ -711,6 +812,74 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
return 0;
}
+#ifdef CONFIG_PM
+u32 pint_saved_masks[NR_PINT_SYS_IRQS];
+u32 pint_wakeup_masks[NR_PINT_SYS_IRQS];
+
+int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+{
+ u32 pint_irq;
+ u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ u32 bank = PINT_2_BANK(pint_val);
+ u32 pintbit = PINT_BIT(pint_val);
+
+ switch (bank) {
+ case 0:
+ pint_irq = IRQ_PINT0;
+ break;
+ case 2:
+ pint_irq = IRQ_PINT2;
+ break;
+ case 3:
+ pint_irq = IRQ_PINT3;
+ break;
+ case 1:
+ pint_irq = IRQ_PINT1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ bfin_internal_set_wake(pint_irq, state);
+
+ if (state)
+ pint_wakeup_masks[bank] |= pintbit;
+ else
+ pint_wakeup_masks[bank] &= ~pintbit;
+
+ return 0;
+}
+
+u32 bfin_pm_setup(void)
+{
+ u32 val, i;
+
+ for (i = 0; i < NR_PINT_SYS_IRQS; i++) {
+ val = pint[i]->mask_clear;
+ pint_saved_masks[i] = val;
+ if (val ^ pint_wakeup_masks[i]) {
+ pint[i]->mask_clear = val;
+ pint[i]->mask_set = pint_wakeup_masks[i];
+ }
+ }
+
+ return 0;
+}
+
+void bfin_pm_restore(void)
+{
+ u32 i, val;
+
+ for (i = 0; i < NR_PINT_SYS_IRQS; i++) {
+ val = pint_saved_masks[i];
+ if (val ^ pint_wakeup_masks[i]) {
+ pint[i]->mask_clear = pint[i]->mask_clear;
+ pint[i]->mask_set = val;
+ }
+ }
+}
+#endif
+
static struct irq_chip bfin_gpio_irqchip = {
.ack = bfin_gpio_ack_irq,
.mask = bfin_gpio_mask_irq,
@@ -718,17 +887,19 @@ static struct irq_chip bfin_gpio_irqchip = {
.unmask = bfin_gpio_unmask_irq,
.set_type = bfin_gpio_irq_type,
.startup = bfin_gpio_irq_startup,
- .shutdown = bfin_gpio_irq_shutdown
+ .shutdown = bfin_gpio_irq_shutdown,
+#ifdef CONFIG_PM
+ .set_wake = bfin_gpio_set_wake,
+#endif
};
-static void bfin_demux_gpio_irq(unsigned int intb_irq,
- struct irq_desc *intb_desc)
+static void bfin_demux_gpio_irq(unsigned int inta_irq,
+ struct irq_desc *desc)
{
u8 bank, pint_val;
u32 request, irq;
- struct irq_desc *desc;
- switch (intb_irq) {
+ switch (inta_irq) {
case IRQ_PINT0:
bank = 0;
break;
@@ -795,7 +966,7 @@ int __init init_arch_irq(void)
int irq;
unsigned long ilat = 0;
/* Disable all the peripheral intrs - page 4-29 HW Ref manual */
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
bfin_write_SIC_IMASK1(SIC_UNMASK_ALL);
bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
@@ -812,6 +983,8 @@ int __init init_arch_irq(void)
local_irq_disable();
+ init_exception_buff();
+
#ifdef CONFIG_BF54x
# ifdef CONFIG_PINTx_REASSIGN
pint[0]->assign = CONFIG_PINT0_ASSIGN;
@@ -874,6 +1047,19 @@ int __init init_arch_irq(void)
set_irq_chained_handler(irq,
bfin_demux_gpio_irq);
break;
+#elif defined(CONFIG_BF561)
+ case IRQ_PROG0_INTA:
+ set_irq_chained_handler(irq,
+ bfin_demux_gpio_irq);
+ break;
+ case IRQ_PROG1_INTA:
+ set_irq_chained_handler(irq,
+ bfin_demux_gpio_irq);
+ break;
+ case IRQ_PROG2_INTA:
+ set_irq_chained_handler(irq,
+ bfin_demux_gpio_irq);
+ break;
#endif
default:
set_irq_handler(irq, handle_simple_irq);
@@ -893,11 +1079,8 @@ int __init init_arch_irq(void)
}
#endif
-#ifndef CONFIG_BF54x
- for (irq = IRQ_PF0; irq < NR_IRQS; irq++) {
-#else
- for (irq = IRQ_PA0; irq < NR_IRQS; irq++) {
-#endif
+ for (irq = GPIO_IRQ_BASE; irq < NR_IRQS; irq++) {
+
set_irq_chip(irq, &bfin_gpio_irqchip);
/* if configured as edge, then will be changed to do_edge_IRQ */
set_irq_handler(irq, handle_level_irq);
@@ -936,7 +1119,7 @@ void do_irq(int vec, struct pt_regs *fp)
} else {
struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
unsigned long sic_status[3];
SSYNC();
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index 81930f7d06f..0be805ca423 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -4,7 +4,7 @@
* Author: Cliff Brake <cbrake@accelent.com> Copyright (c) 2001
*
* Created: 2001
- * Description: Power management for the bfin
+ * Description: Blackfin power management
*
* Modified: Nicolas Pitre - PXA250 support
* Copyright (c) 2002 Monta Vista Software, Inc.
@@ -12,7 +12,7 @@
* Copyright (c) 2002 Monta Vista Software, Inc.
* Dirk Behme <dirk.behme@de.bosch.com> - OMAP1510/1610
* Copyright 2004
- * Copyright 2004-2006 Analog Devices Inc.
+ * Copyright 2004-2008 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
@@ -67,42 +67,30 @@ void bfin_pm_suspend_standby_enter(void)
gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE);
#endif
-#if defined(CONFIG_PM_WAKEUP_BY_GPIO) || defined(CONFIG_PM_WAKEUP_GPIO_API)
- {
- u32 flags;
+ u32 flags;
- local_irq_save(flags);
+ local_irq_save(flags);
+ bfin_pm_setup();
- sleep_deeper(gpio_pm_setup()); /*Goto Sleep*/
-
- gpio_pm_restore();
-
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
- bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
- bfin_write_SIC_IWR1(IWR_ENABLE_ALL);
-# ifdef CONFIG_BF54x
- bfin_write_SIC_IWR2(IWR_ENABLE_ALL);
-# endif
+#ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
+ sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
#else
- bfin_write_SIC_IWR(IWR_ENABLE_ALL);
+ sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]);
#endif
- local_irq_restore(flags);
- }
-#endif
+ bfin_pm_restore();
-#if defined(CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR)
- sleep_deeper(CONFIG_PM_WAKEUP_SIC_IWR);
-# if defined(CONFIG_BF54x) || defined(CONFIG_BF52x)
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
bfin_write_SIC_IWR1(IWR_ENABLE_ALL);
-# ifdef CONFIG_BF54x
+# ifdef CONFIG_BF54x
bfin_write_SIC_IWR2(IWR_ENABLE_ALL);
-# endif
-# else
- bfin_write_SIC_IWR(IWR_ENABLE_ALL);
# endif
-#endif /* CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR */
+#else
+ bfin_write_SIC_IWR(IWR_ENABLE_ALL);
+#endif
+
+ local_irq_restore(flags);
}
/*
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c
index eb1a12ac9e3..1f516c55bde 100644
--- a/arch/blackfin/mm/init.c
+++ b/arch/blackfin/mm/init.c
@@ -138,8 +138,7 @@ void __init mem_init(void)
start_mem = PAGE_ALIGN(start_mem);
max_mapnr = num_physpages = MAP_NR(high_memory);
- printk(KERN_INFO "Kernel managed physical pages: %lu\n",
- num_physpages);
+ printk(KERN_DEBUG "Kernel managed physical pages: %lu\n", num_physpages);
/* This will put all memory onto the freelists. */
totalram_pages = free_all_bootmem();
@@ -153,8 +152,7 @@ void __init mem_init(void)
/* do not count in kernel image between _rambase and _ramstart */
reservedpages -= (_ramstart - _rambase) >> PAGE_SHIFT;
#if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263)
- reservedpages += (_ramend - memory_end - DMA_UNCACHED_REGION) >>
- PAGE_SHIFT;
+ reservedpages += (_ramend - memory_end - DMA_UNCACHED_REGION) >> PAGE_SHIFT;
#endif
codek = (_etext - _stext) >> 10;
@@ -163,11 +161,9 @@ void __init mem_init(void)
printk(KERN_INFO
"Memory available: %luk/%luk RAM, "
- "(%uk init code, %uk kernel code, "
- "%uk data, %uk dma, %uk reserved)\n",
+ "(%uk init code, %uk kernel code, %uk data, %uk dma, %uk reserved)\n",
(unsigned long) freepages << (PAGE_SHIFT-10), _ramend >> 10,
- initk, codek, datak, DMA_UNCACHED_REGION >> 10,
- (reservedpages << (PAGE_SHIFT-10)));
+ initk, codek, datak, DMA_UNCACHED_REGION >> 10, (reservedpages << (PAGE_SHIFT-10)));
/* Initialize the blackfin L1 Memory. */
l1sram_init();
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 7f0be4cd5e9..9389d38f222 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -13,10 +13,6 @@ config ZONE_DMA
bool
default y
-config NO_DMA
- bool
- default y
-
config RWSEM_GENERIC_SPINLOCK
bool
default y
@@ -24,6 +20,10 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_IOMAP
+ bool
+ default y
+
config ARCH_HAS_ILOG2_U32
bool
default n
@@ -44,16 +44,21 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
-config IRQ_PER_CPU
- bool
- default y
-
config NO_IOPORT
def_bool y
+config FORCE_MAX_ZONEORDER
+ int
+ default 6
+
config CRIS
bool
default y
+ select HAVE_IDE
+
+config HZ
+ int
+ default 100
source "init/Kconfig"
@@ -93,17 +98,15 @@ config ETRAX_FAST_TIMER
timers).
This is needed if CONFIG_ETRAX_SERIAL_FAST_TIMER is enabled.
-config PREEMPT
- bool "Preemptible Kernel"
+config ETRAX_KMALLOCED_MODULES
+ bool "Enable module allocation with kmalloc"
help
- This option reduces the latency of the kernel when reacting to
- real-time or interactive events by allowing a low priority process to
- be preempted even if it is in kernel mode executing a system call.
- This allows applications to run more reliably even when the system is
- under load.
+ Enable module allocation with kmalloc instead of vmalloc.
+
+config OOM_REBOOT
+ bool "Enable reboot at out of memory"
- Say Y here if you are building a kernel for a desktop, embedded
- or real-time system. Say N if you are unsure.
+source "kernel/Kconfig.preempt"
source mm/Kconfig
@@ -130,26 +133,127 @@ config SVINTO_SIM
help
Support the xsim ETRAX Simulator.
+config ETRAXFS
+ bool "ETRAX-FS-V32"
+ help
+ Support CRIS V32.
+
+config CRIS_MACH_ARTPEC3
+ bool "ARTPEC-3"
+ help
+ Support Axis ARTPEC-3.
+
endchoice
+config ETRAX_VCS_SIM
+ bool "VCS Simulator"
+ help
+ Setup hardware to be run in the VCS simulator.
+
config ETRAX_ARCH_V10
bool
default y if ETRAX100LX || ETRAX100LX_V2
default n if !(ETRAX100LX || ETRAX100LX_V2)
+config ETRAX_ARCH_V32
+ bool
+ default y if (ETRAXFS || CRIS_MACH_ARTPEC3)
+ default n if !(ETRAXFS || CRIS_MACH_ARTPEC3)
+
config ETRAX_DRAM_SIZE
int "DRAM size (dec, in MB)"
default "8"
help
Size of DRAM (decimal in MB) typically 2, 8 or 16.
+config ETRAX_VMEM_SIZE
+ int "Video memory size (dec, in MB)"
+ depends on ETRAX_ARCH_V32 && !ETRAXFS
+ default 8 if !ETRAXFS
+ help
+ Size of Video accessible memory (decimal, in MB).
+
config ETRAX_FLASH_BUSWIDTH
- int "Buswidth of flash in bytes"
+ int "Buswidth of NOR flash in bytes"
default "2"
help
- Width in bytes of the Flash bus (1, 2 or 4). Is usually 2.
+ Width in bytes of the NOR Flash bus (1, 2 or 4). Is usually 2.
+
+config ETRAX_NANDFLASH_BUSWIDTH
+ int "Buswidth of NAND flash in bytes"
+ default "1"
+ help
+ Width in bytes of the NAND flash (1 or 2).
+
+config ETRAX_FLASH1_SIZE
+ int "FLASH1 size (dec, in MB. 0 = Unknown)"
+ default "0"
+
+choice
+ prompt "Product debug-port"
+ default ETRAX_DEBUG_PORT0
+
+config ETRAX_DEBUG_PORT0
+ bool "Serial-0"
+ help
+ Choose a serial port for the ETRAX debug console. Default to
+ port 0.
+
+config ETRAX_DEBUG_PORT1
+ bool "Serial-1"
+ help
+ Use serial port 1 for the console.
+
+config ETRAX_DEBUG_PORT2
+ bool "Serial-2"
+ help
+ Use serial port 2 for the console.
+
+config ETRAX_DEBUG_PORT3
+ bool "Serial-3"
+ help
+ Use serial port 3 for the console.
+
+config ETRAX_DEBUG_PORT_NULL
+ bool "disabled"
+ help
+ Disable serial-port debugging.
+
+endchoice
+
+choice
+ prompt "Kernel GDB port"
+ depends on ETRAX_KGDB
+ default ETRAX_KGDB_PORT0
+ help
+ Choose a serial port for kernel debugging. NOTE: This port should
+ not be enabled under Drivers for built-in interfaces (as it has its
+ own initialization code) and should not be the same as the debug port.
+
+config ETRAX_KGDB_PORT0
+ bool "Serial-0"
+ help
+ Use serial port 0 for kernel debugging.
+
+config ETRAX_KGDB_PORT1
+ bool "Serial-1"
+ help
+ Use serial port 1 for kernel debugging.
+
+config ETRAX_KGDB_PORT2
+ bool "Serial-2"
+ help
+ Use serial port 2 for kernel debugging.
+
+config ETRAX_KGDB_PORT3
+ bool "Serial-3"
+ help
+ Use serial port 3 for kernel debugging.
+
+endchoice
source arch/cris/arch-v10/Kconfig
+source arch/cris/arch-v32/Kconfig
endmenu
@@ -157,8 +261,389 @@ source "net/Kconfig"
# bring in ETRAX built-in drivers
menu "Drivers for built-in interfaces"
-# arch/cris/arch is a symlink to correct arch (arch-v10 or arch-v32)
-source arch/cris/arch/drivers/Kconfig
+source arch/cris/arch-v10/drivers/Kconfig
+source arch/cris/arch-v32/drivers/Kconfig
+
+config ETRAX_AXISFLASHMAP
+ bool "Axis flash-map support"
+ select MTD
+ select MTD_CFI
+ select MTD_CFI_AMDSTD
+ select MTD_JEDECPROBE if ETRAX_ARCH_V32
+ select MTD_CHAR
+ select MTD_BLOCK
+ select MTD_PARTITIONS
+ select MTD_CONCAT
+ select MTD_COMPLEX_MAPPINGS
+ help
+ This option enables MTD mapping of flash devices. Needed to use
+ flash memories. If unsure, say Y.
+
+config ETRAX_RTC
+ bool "Real Time Clock support"
+ depends on ETRAX_I2C
+ help
+ Enables drivers for the Real-Time Clock battery-backed chips on
+ some products. The kernel reads the time when booting, and
+ the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a
+ rtc_time struct (see <file:include/asm-cris/rtc.h>) on the /dev/rtc
+ device. You can check the time with cat /proc/rtc, but
+ normal time reading should be done using libc function time and
+ friends.
+
+choice
+ prompt "RTC chip"
+ depends on ETRAX_RTC
+ default ETRAX_PCF8563 if ETRAX_ARCH_V32
+ default ETRAX_DS1302 if ETRAX_ARCH_V10
+
+config ETRAX_DS1302
+ depends on ETRAX_ARCH_V10
+ bool "DS1302"
+ help
+ Enables the driver for the DS1302 Real-Time Clock battery-backed
+ chip on some products.
+
+config ETRAX_PCF8563
+ bool "PCF8563"
+ help
+ Enables the driver for the PCF8563 Real-Time Clock battery-backed
+ chip on some products.
+
+endchoice
+
+config ETRAX_SYNCHRONOUS_SERIAL
+ bool "Synchronous serial-port support"
+ help
+ Select this to enable the synchronous serial port driver.
+
+config ETRAX_SYNCHRONOUS_SERIAL_PORT0
+ bool "Synchronous serial port 0 enabled"
+ depends on ETRAX_SYNCHRONOUS_SERIAL
+ help
+ Enabled synchronous serial port 0.
+
+config ETRAX_SYNCHRONOUS_SERIAL0_DMA
+ bool "Enable DMA on synchronous serial port 0."
+ depends on ETRAX_SYNCHRONOUS_SERIAL_PORT0
+ help
+ A synchronous serial port can run in manual or DMA mode.
+ Selecting this option will make it run in DMA mode.
+
+config ETRAX_SYNCHRONOUS_SERIAL_PORT1
+ bool "Synchronous serial port 1 enabled"
+ depends on ETRAX_SYNCHRONOUS_SERIAL && (ETRAXFS || ETRAX_ARCH_V10)
+ help
+ Enabled synchronous serial port 1.
+
+config ETRAX_SYNCHRONOUS_SERIAL1_DMA
+ bool "Enable DMA on synchronous serial port 1."
+ depends on ETRAX_SYNCHRONOUS_SERIAL_PORT1
+ help
+ A synchronous serial port can run in manual or DMA mode.
+ Selecting this option will make it run in DMA mode.
+
+choice
+ prompt "Network LED behavior"
+ depends on ETRAX_ETHERNET
+ default ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY
+
+config ETRAX_NETWORK_LED_ON_WHEN_LINK
+ bool "LED_on_when_link"
+ help
+ Selecting LED_on_when_link will light the LED when there is a
+ connection and will flash off when there is activity.
+
+ Selecting LED_on_when_activity will light the LED only when
+ there is activity.
+
+ This setting will also affect the behaviour of other activity LEDs
+ e.g. Bluetooth.
+
+config ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY
+ bool "LED_on_when_activity"
+ help
+ Selecting LED_on_when_link will light the LED when there is a
+ connection and will flash off when there is activity.
+
+ Selecting LED_on_when_activity will light the LED only when
+ there is activity.
+
+ This setting will also affect the behaviour of other activity LEDs
+ e.g. Bluetooth.
+
+endchoice
+
+choice
+ prompt "Ser0 DMA out channel"
+ depends on ETRAX_SERIAL_PORT0
+ default ETRAX_SERIAL_PORT0_DMA6_OUT if ETRAX_ARCH_V32
+ default ETRAX_SERIAL_PORT0_NO_DMA_OUT if ETRAX_ARCH_V10
+
+config ETRAX_SERIAL_PORT0_NO_DMA_OUT
+ bool "Ser0 uses no DMA for output"
+ help
+ Do not use DMA for ser0 output.
+
+config ETRAX_SERIAL_PORT0_DMA6_OUT
+ bool "Ser0 uses DMA6 for output"
+ depends on ETRAXFS
+ help
+ Enables the DMA6 output channel for ser0 (ttyS0).
+ If you do not enable DMA, an interrupt for each character will be
+ used when transmitting data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+config ETRAX_SERIAL_PORT0_DMA0_OUT
+ bool "Ser0 uses DMA0 for output"
+ depends on CRIS_MACH_ARTPEC3
+ help
+ Enables the DMA0 output channel for ser0 (ttyS0).
+ If you do not enable DMA, an interrupt for each character will be
+ used when transmitting data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+endchoice
+
+choice
+ prompt "Ser0 DMA in channel "
+ depends on ETRAX_SERIAL_PORT0
+ default ETRAX_SERIAL_PORT0_NO_DMA_IN if ETRAX_ARCH_V32
+ default ETRAX_SERIAL_PORT0_DMA7_IN if ETRAX_ARCH_V10
+ help
+ What DMA channel to use for ser0.
+
+config ETRAX_SERIAL_PORT0_NO_DMA_IN
+ bool "Ser0 uses no DMA for input"
+ help
+ Do not use DMA for ser0 input.
+
+config ETRAX_SERIAL_PORT0_DMA7_IN
+ bool "Ser0 uses DMA7 for input"
+ depends on ETRAXFS
+ help
+ Enables the DMA7 input channel for ser0 (ttyS0).
+ If you do not enable DMA, an interrupt for each character will be
+ used when receiving data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+config ETRAX_SERIAL_PORT0_DMA1_IN
+ bool "Ser0 uses DMA1 for input"
+ depends on CRIS_MACH_ARTPEC3
+ help
+ Enables the DMA1 input channel for ser0 (ttyS0).
+ If you do not enable DMA, an interrupt for each character will be
+ used when receiveing data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+endchoice
+
+choice
+ prompt "Ser1 DMA in channel "
+ depends on ETRAX_SERIAL_PORT1
+ default ETRAX_SERIAL_PORT1_NO_DMA_IN if ETRAX_ARCH_V32
+ default ETRAX_SERIAL_PORT1_DMA9_IN if ETRAX_ARCH_V10
+ help
+ What DMA channel to use for ser1.
+
+config ETRAX_SERIAL_PORT1_NO_DMA_IN
+ bool "Ser1 uses no DMA for input"
+ help
+ Do not use DMA for ser1 input.
+
+config ETRAX_SERIAL_PORT1_DMA5_IN
+ bool "Ser1 uses DMA5 for input"
+ depends on ETRAX_ARCH_V32
+ help
+ Enables the DMA5 input channel for ser1 (ttyS1).
+ If you do not enable DMA, an interrupt for each character will be
+ used when receiving data.
+ Normally you want this on, unless you use the DMA channel for
+ something else.
+
+config ETRAX_SERIAL_PORT1_DMA9_IN
+ depends on ETRAX_ARCH_V10
+ bool "Ser1 uses DMA9 for input"
+
+endchoice
+
+
+choice
+ prompt "Ser1 DMA out channel"
+ depends on ETRAX_SERIAL_PORT1
+ default ETRAX_SERIAL_PORT1_NO_DMA_OUT if ETRAX_ARCH_V32
+ default ETRAX_SERIAL_PORT1_DMA8_OUT if ETRAX_ARCH_V10
+ help
+ What DMA channel to use for ser1.
+
+config ETRAX_SERIAL_PORT1_NO_DMA_OUT
+ bool "Ser1 uses no DMA for output"
+ help
+ Do not use DMA for ser1 output.
+
+config ETRAX_SERIAL_PORT1_DMA8_OUT
+ depends on ETRAX_ARCH_V10
+ bool "Ser1 uses DMA8 for output"
+
+config ETRAX_SERIAL_PORT1_DMA4_OUT
+ depends on ETRAX_ARCH_V32
+ bool "Ser1 uses DMA4 for output"
+ help
+ Enables the DMA4 output channel for ser1 (ttyS1).
+ If you do not enable DMA, an interrupt for each character will be
+ used when transmitting data.
+ Normally you want this on, unless you use the DMA channel for
+ something else.
+
+endchoice
+
+choice
+ prompt "Ser2 DMA out channel"
+ depends on ETRAX_SERIAL_PORT2
+ default ETRAX_SERIAL_PORT2_NO_DMA_OUT if ETRAX_ARCH_V32
+ default ETRAX_SERIAL_PORT2_DMA2_OUT if ETRAX_ARCH_V10
+
+config ETRAX_SERIAL_PORT2_NO_DMA_OUT
+ bool "Ser2 uses no DMA for output"
+ help
+ Do not use DMA for ser2 output.
+
+config ETRAX_SERIAL_PORT2_DMA2_OUT
+ bool "Ser2 uses DMA2 for output"
+ depends on ETRAXFS || ETRAX_ARCH_V10
+ help
+ Enables the DMA2 output channel for ser2 (ttyS2).
+ If you do not enable DMA, an interrupt for each character will be
+ used when transmitting data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+config ETRAX_SERIAL_PORT2_DMA6_OUT
+ bool "Ser2 uses DMA6 for output"
+ depends on CRIS_MACH_ARTPEC3
+ help
+ Enables the DMA6 output channel for ser2 (ttyS2).
+ If you do not enable DMA, an interrupt for each character will be
+ used when transmitting data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+endchoice
+
+choice
+ prompt "Ser2 DMA in channel"
+ depends on ETRAX_SERIAL_PORT2
+ default ETRAX_SERIAL_PORT2_NO_DMA_IN if ETRAX_ARCH_V32
+ default ETRAX_SERIAL_PORT2_DMA3_IN if ETRAX_ARCH_V10
+ help
+ What DMA channel to use for ser2.
+
+config ETRAX_SERIAL_PORT2_NO_DMA_IN
+ bool "Ser2 uses no DMA for input"
+ help
+ Do not use DMA for ser2 input.
+
+config ETRAX_SERIAL_PORT2_DMA3_IN
+ bool "Ser2 uses DMA3 for input"
+ depends on ETRAXFS || ETRAX_ARCH_V10
+ help
+ Enables the DMA3 input channel for ser2 (ttyS2).
+ If you do not enable DMA, an interrupt for each character will be
+ used when receiving data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+config ETRAX_SERIAL_PORT2_DMA7_IN
+ bool "Ser2 uses DMA7 for input"
+ depends on CRIS_MACH_ARTPEC3
+ help
+ Enables the DMA7 input channel for ser2 (ttyS2).
+ If you do not enable DMA, an interrupt for each character will be
+ used when receiveing data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+endchoice
+
+choice
+ prompt "Ser3 DMA in channel"
+ depends on ETRAX_SERIAL_PORT3
+ default ETRAX_SERIAL_PORT3_NO_DMA_IN if ETRAX_ARCH_V32
+ default ETRAX_SERIAL_PORT3_DMA5_IN if ETRAX_ARCH_V10
+ help
+ What DMA channel to use for ser3.
+
+config ETRAX_SERIAL_PORT3_NO_DMA_IN
+ bool "Ser3 uses no DMA for input"
+ help
+ Do not use DMA for ser3 input.
+
+config ETRAX_SERIAL_PORT3_DMA5_IN
+ depends on ETRAX_ARCH_V10
+ bool "DMA 5"
+
+config ETRAX_SERIAL_PORT3_DMA9_IN
+ bool "Ser3 uses DMA9 for input"
+ depends on ETRAXFS
+ help
+ Enables the DMA9 input channel for ser3 (ttyS3).
+ If you do not enable DMA, an interrupt for each character will be
+ used when receiving data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+config ETRAX_SERIAL_PORT3_DMA3_IN
+ bool "Ser3 uses DMA3 for input"
+ depends on CRIS_MACH_ARTPEC3
+ help
+ Enables the DMA3 input channel for ser3 (ttyS3).
+ If you do not enable DMA, an interrupt for each character will be
+ used when receiveing data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+endchoice
+
+choice
+ prompt "Ser3 DMA out channel"
+ depends on ETRAX_SERIAL_PORT3
+ default ETRAX_SERIAL_PORT3_NO_DMA_OUT if ETRAX_ARCH_V32
+ default ETRAX_SERIAL_PORT3_DMA4_OUT if ETRAX_ARCH_V10
+
+config ETRAX_SERIAL_PORT3_NO_DMA_OUT
+ bool "Ser3 uses no DMA for output"
+ help
+ Do not use DMA for ser3 output.
+
+config ETRAX_SERIAL_PORT3_DMA4_OUT
+ depends on ETRAX_ARCH_V10
+ bool "DMA 4"
+
+config ETRAX_SERIAL_PORT3_DMA8_OUT
+ bool "Ser3 uses DMA8 for output"
+ depends on ETRAXFS
+ help
+ Enables the DMA8 output channel for ser3 (ttyS3).
+ If you do not enable DMA, an interrupt for each character will be
+ used when transmitting data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+config ETRAX_SERIAL_PORT3_DMA2_OUT
+ bool "Ser3 uses DMA2 for output"
+ depends on CRIS_MACH_ARTPEC3
+ help
+ Enables the DMA2 output channel for ser3 (ttyS3).
+ If you do not enable DMA, an interrupt for each character will be
+ used when transmitting data.
+ Normally you want to use DMA, unless you use the DMA channel for
+ something else.
+
+endchoice
endmenu
@@ -173,22 +658,10 @@ source "drivers/pnp/Kconfig"
source "drivers/block/Kconfig"
-source "drivers/md/Kconfig"
-
source "drivers/ide/Kconfig"
-source "drivers/scsi/Kconfig"
-
-source "drivers/ieee1394/Kconfig"
-
-source "drivers/message/i2o/Kconfig"
-
source "drivers/net/Kconfig"
-source "drivers/isdn/Kconfig"
-
-source "drivers/telephony/Kconfig"
-
source "drivers/i2c/Kconfig"
source "drivers/rtc/Kconfig"
@@ -200,17 +673,8 @@ source "drivers/input/Kconfig"
source "drivers/char/Kconfig"
-#source drivers/misc/Config.in
-source "drivers/media/Kconfig"
-
source "fs/Kconfig"
-source "sound/Kconfig"
-
-source "drivers/pcmcia/Kconfig"
-
-source "drivers/pci/Kconfig"
-
source "drivers/usb/Kconfig"
source "arch/cris/Kconfig.debug"
diff --git a/arch/cris/Makefile b/arch/cris/Makefile
index e6bf00c262e..838cd2ae03a 100644
--- a/arch/cris/Makefile
+++ b/arch/cris/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.28 2005/03/17 10:44:37 larsv Exp $
+#
# cris/Makefile
#
# This file is included by the global makefile so that you can add your own
@@ -10,28 +10,36 @@
# License. See the file "COPYING" in the main directory of this archive
# for more details.
-# A bug in ld prevents us from having a (constant-value) symbol in a
-# "ORIGIN =" or "LENGTH =" expression.
-
arch-y := v10
arch-$(CONFIG_ETRAX_ARCH_V10) := v10
arch-$(CONFIG_ETRAX_ARCH_V32) := v32
-# No config avaiable for make clean etc
+# No config available for make clean etc
+mach-y := fs
+mach-$(CONFIG_CRIS_MACH_ARTPEC3) := a3
+mach-$(CONFIG_ETRAXFS) := fs
+
ifneq ($(arch-y),)
SARCH := arch-$(arch-y)
else
SARCH :=
endif
+ifneq ($(mach-y),)
+MACH := mach-$(mach-y)
+else
+MACH :=
+endif
+
LD = $(CROSS_COMPILE)ld -mcrislinux
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
CPPFLAGS_vmlinux.lds = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)
-KBUILD_AFLAGS += -mlinux
-KBUILD_CFLAGS += -mlinux -march=$(arch-y) -pipe
+KBUILD_AFLAGS += -mlinux -march=$(arch-y) -Iinclude/asm/arch/mach -Iinclude/asm/arch
+
+KBUILD_CFLAGS += -mlinux -march=$(arch-y) -pipe -Iinclude/asm/arch/mach -Iinclude/asm/arch
ifdef CONFIG_FRAME_POINTER
KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
@@ -44,6 +52,9 @@ LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libgcc.a)
core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/
core-y += arch/$(ARCH)/$(SARCH)/kernel/ arch/$(ARCH)/$(SARCH)/mm/
+ifdef CONFIG_ETRAX_ARCH_V32
+core-y += arch/$(ARCH)/$(SARCH)/$(MACH)/
+endif
drivers-y += arch/$(ARCH)/$(SARCH)/drivers/
libs-y += arch/$(ARCH)/$(SARCH)/lib/ $(LIBGCC)
@@ -52,79 +63,69 @@ SRC_ARCH = $(srctree)/arch/$(ARCH)
# cris object files path
OBJ_ARCH = $(objtree)/arch/$(ARCH)
-target_boot_arch_dir = $(OBJ_ARCH)/$(SARCH)/boot
-target_boot_dir = $(OBJ_ARCH)/boot
-src_boot_dir = $(SRC_ARCH)/boot
-target_compressed_dir = $(OBJ_ARCH)/boot/compressed
-src_compressed_dir = $(SRC_ARCH)/boot/compressed
-target_rescue_dir = $(OBJ_ARCH)/boot/rescue
-src_rescue_dir = $(SRC_ARCH)/boot/rescue
-
-export target_boot_arch_dir target_boot_dir src_boot_dir target_compressed_dir src_compressed_dir target_rescue_dir src_rescue_dir
-
-vmlinux.bin: vmlinux
- $(OBJCOPY) $(OBJCOPYFLAGS) vmlinux vmlinux.bin
-
-timage: vmlinux.bin
- cat vmlinux.bin cramfs.img >timage
-
-simimage: timage
- cp vmlinux.bin simvmlinux.bin
-
-# the following will remake timage without compiling the kernel
-# it does of course require that all object files exist...
-
-cramfs:
-## cramfs - Creates a cramfs image
- mkcramfs -b 8192 -m romfs_meta.txt root cramfs.img
- cat vmlinux.bin cramfs.img >timage
+boot := arch/$(ARCH)/boot
+MACHINE := arch/$(ARCH)/$(SARCH)
-clinux: vmlinux.bin decompress.bin rescue.bin
+all: zImage
-decompress.bin: $(target_boot_dir)
- @$(MAKE) -f $(src_compressed_dir)/Makefile $(target_compressed_dir)/decompress.bin
+zImage Image: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
-$(target_rescue_dir)/rescue.bin: $(target_boot_dir)
- @$(MAKE) -f $(src_rescue_dir)/Makefile $(target_rescue_dir)/rescue.bin
-
-zImage: $(target_boot_dir) vmlinux.bin $(target_rescue_dir)/rescue.bin
-## zImage - Compressed kernel (gzip)
- @$(MAKE) -f $(src_boot_dir)/Makefile zImage
-
-$(target_boot_dir): $(target_boot_arch_dir)
- ln -sfn $< $@
-
-$(target_boot_arch_dir):
- mkdir -p $@
-
-compressed: zImage
-
-archmrproper:
-archclean:
- @if [ -d arch/$(ARCH)/boot ]; then \
- $(MAKE) $(clean)=arch/$(ARCH)/boot ; \
- fi
- rm -f timage vmlinux.bin decompress.bin rescue.bin cramfs.img
- rm -rf $(LD_SCRIPT).tmp
-
-archprepare: $(SRC_ARCH)/.links $(srctree)/include/asm-$(ARCH)/.arch
+archprepare: $(SRC_ARCH)/.links $(srctree)/include/asm-$(ARCH)/.arch FORCE
# Create some links to make all tools happy
$(SRC_ARCH)/.links:
@rm -rf $(SRC_ARCH)/drivers
- @ln -sfn $(SRC_ARCH)/$(SARCH)/drivers $(SRC_ARCH)/drivers
+ @ln -sfn $(SARCH)/drivers $(SRC_ARCH)/drivers
@rm -rf $(SRC_ARCH)/boot
- @ln -sfn $(SRC_ARCH)/$(SARCH)/boot $(SRC_ARCH)/boot
+ @ln -sfn $(SARCH)/boot $(SRC_ARCH)/boot
@rm -rf $(SRC_ARCH)/lib
- @ln -sfn $(SRC_ARCH)/$(SARCH)/lib $(SRC_ARCH)/lib
- @ln -sfn $(SRC_ARCH)/$(SARCH) $(SRC_ARCH)/arch
- @ln -sfn $(SRC_ARCH)/$(SARCH)/vmlinux.lds.S $(SRC_ARCH)/kernel/vmlinux.lds.S
- @ln -sfn $(SRC_ARCH)/$(SARCH)/kernel/asm-offsets.c $(SRC_ARCH)/kernel/asm-offsets.c
+ @ln -sfn $(SARCH)/lib $(SRC_ARCH)/lib
+ @rm -f $(SRC_ARCH)/arch/mach
+ @rm -rf $(SRC_ARCH)/arch
+ @ln -sfn $(SARCH) $(SRC_ARCH)/arch
+ifdef CONFIG_ETRAX_ARCH_V32
+ @ln -sfn ../$(SARCH)/$(MACH) $(SRC_ARCH)/arch/mach
+endif
+ @rm -rf $(SRC_ARCH)/kernel/vmlinux.lds.S
+ @ln -sfn ../$(SARCH)/vmlinux.lds.S $(SRC_ARCH)/kernel/vmlinux.lds.S
+ @rm -rf $(SRC_ARCH)/kernel/asm-offsets.c
+ @ln -sfn ../$(SARCH)/kernel/asm-offsets.c $(SRC_ARCH)/kernel/asm-offsets.c
@touch $@
# Create link to sub arch includes
$(srctree)/include/asm-$(ARCH)/.arch: $(wildcard include/config/arch/*.h)
- @echo ' Making $(srctree)/include/asm-$(ARCH)/arch -> $(srctree)/include/asm-$(ARCH)/$(SARCH) symlink'
- @rm -f include/asm-$(ARCH)/arch
- @ln -sf $(srctree)/include/asm-$(ARCH)/$(SARCH) $(srctree)/include/asm-$(ARCH)/arch
+ @echo ' SYMLINK include/asm-$(ARCH)/arch -> include/asm-$(ARCH)/$(SARCH)'
+ @rm -f $(srctree)/include/asm-$(ARCH)/arch/mach
+ @rm -f $(srctree)/include/asm-$(ARCH)/arch
+ @ln -sf $(SARCH) $(srctree)/include/asm-$(ARCH)/arch
+ifdef CONFIG_ETRAX_ARCH_V32
+ @ln -sf $(MACH) $(srctree)/include/asm-$(ARCH)/arch/mach
+endif
@touch $@
+
+archclean:
+ $(Q)if [ -e arch/$(ARCH)/boot ]; then \
+ $(MAKE) $(clean)=arch/$(ARCH)/boot; \
+ fi
+
+CLEAN_FILES += \
+ $(MACHINE)/boot/zImage \
+ $(MACHINE)/boot/compressed/decompress.bin \
+ $(MACHINE)/boot/compressed/piggy.gz \
+ $(MACHINE)/boot/rescue/rescue.bin \
+ $(SRC_ARCH)/.links \
+ $(srctree)/include/asm-$(ARCH)/.arch
+
+MRPROPER_FILES += \
+ $(SRC_ARCH)/drivers \
+ $(SRC_ARCH)/boot \
+ $(SRC_ARCH)/lib \
+ $(SRC_ARCH)/arch \
+ $(SRC_ARCH)/kernel/vmlinux.lds.S \
+ $(SRC_ARCH)/kernel/asm-offsets.c
+
+define archhelp
+ echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
+ echo '* Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
+endef
diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig
index f1ce6f64401..adc164e9933 100644
--- a/arch/cris/arch-v10/Kconfig
+++ b/arch/cris/arch-v10/Kconfig
@@ -1,3 +1,7 @@
+if ETRAX_ARCH_V10
+
+menu "CRIS v10 options"
+
# ETRAX 100LX v1 has a MMU "feature" requiring a low mapping
config CRIS_LOW_MAP
bool
@@ -226,69 +230,6 @@ config ETRAX_LED12R
For products with only one or two controllable LEDs,
set this to same as CONFIG_ETRAX_LED1G (normally 2).
-choice
- prompt "Product debug-port"
- depends on ETRAX_ARCH_V10
- default ETRAX_DEBUG_PORT0
-
-config ETRAX_DEBUG_PORT0
- bool "Serial-0"
- help
- Choose a serial port for the ETRAX debug console. Default to
- port 0.
-
-config ETRAX_DEBUG_PORT1
- bool "Serial-1"
- help
- Use serial port 1 for the console.
-
-config ETRAX_DEBUG_PORT2
- bool "Serial-2"
- help
- Use serial port 2 for the console.
-
-config ETRAX_DEBUG_PORT3
- bool "Serial-3"
- help
- Use serial port 3 for the console.
-
-config ETRAX_DEBUG_PORT_NULL
- bool "disabled"
- help
- Disable serial-port debugging.
-
-endchoice
-
-choice
- prompt "Kernel GDB port"
- depends on ETRAX_KGDB
- default ETRAX_KGDB_PORT0
- help
- Choose a serial port for kernel debugging. NOTE: This port should
- not be enabled under Drivers for built-in interfaces (as it has its
- own initialization code) and should not be the same as the debug port.
-
-config ETRAX_KGDB_PORT0
- bool "Serial-0"
- help
- Use serial port 0 for kernel debugging.
-
-config ETRAX_KGDB_PORT1
- bool "Serial-1"
- help
- Use serial port 1 for kernel debugging.
-
-config ETRAX_KGDB_PORT2
- bool "Serial-2"
- help
- Use serial port 2 for kernel debugging.
-
-config ETRAX_KGDB_PORT3
- bool "Serial-3"
- help
- Use serial port 3 for kernel debugging.
-
-endchoice
choice
prompt "Product rescue-port"
@@ -451,3 +392,7 @@ config ETRAX_POWERBUTTON_BIT
default "25"
help
Configure where power button is connected.
+
+endmenu
+
+endif
diff --git a/arch/cris/arch-v10/boot/Makefile b/arch/cris/arch-v10/boot/Makefile
index e5b10585110..20c83a53caf 100644
--- a/arch/cris/arch-v10/boot/Makefile
+++ b/arch/cris/arch-v10/boot/Makefile
@@ -1,13 +1,21 @@
#
-# arch/cris/boot/Makefile
+# arch/cris/arch-v10/boot/Makefile
#
-target = $(target_boot_dir)
-src = $(src_boot_dir)
-zImage: compressed/vmlinuz
+OBJCOPY = objcopy-cris
+OBJCOPYFLAGS = -O binary --remove-section=.bss
-compressed/vmlinuz:
- @$(MAKE) -f $(src)/compressed/Makefile $(target_compressed_dir)/vmlinuz
+subdir- := compressed rescue
+targets := Image
-clean:
- @$(MAKE) -f $(src)/compressed/Makefile clean
+$(obj)/Image: vmlinux FORCE
+ $(call if_changed,objcopy)
+ @echo ' Kernel: $@ is ready'
+
+$(obj)/compressed/vmlinux: $(obj)/Image FORCE
+ $(Q)$(MAKE) $(build)=$(obj)/compressed $@
+ $(Q)$(MAKE) $(build)=$(obj)/rescue $(obj)/rescue/rescue.bin
+
+$(obj)/zImage: $(obj)/compressed/vmlinux
+ @cp $< $@
+ @echo ' Kernel: $@ is ready'
diff --git a/arch/cris/arch-v10/boot/compressed/Makefile b/arch/cris/arch-v10/boot/compressed/Makefile
index 6584a44820f..4a031cb27eb 100644
--- a/arch/cris/arch-v10/boot/compressed/Makefile
+++ b/arch/cris/arch-v10/boot/compressed/Makefile
@@ -1,45 +1,35 @@
#
-# create a compressed vmlinuz image from the binary vmlinux.bin file
+# arch/cris/arch-v10/boot/compressed/Makefile
#
-target = $(target_compressed_dir)
-src = $(src_compressed_dir)
CC = gcc-cris -melf $(LINUXINCLUDE)
-CFLAGS = -O2
+ccflags-y += -O2
LD = ld-cris
+ldflags-y += -T $(obj)/decompress.ld
+OBJECTS = $(obj)/head.o $(obj)/misc.o
OBJCOPY = objcopy-cris
OBJCOPYFLAGS = -O binary --remove-section=.bss
-OBJECTS = $(target)/head.o $(target)/misc.o
-# files to compress
-SYSTEM = $(objtree)/vmlinux.bin
+quiet_cmd_image = BUILD $@
+cmd_image = cat $(obj)/decompress.bin $(obj)/piggy.gz > $@
-all: $(target_compressed_dir)/vmlinuz
+targets := vmlinux piggy.gz decompress.o decompress.bin
-$(target)/decompress.bin: $(OBJECTS)
- $(LD) -T $(src)/decompress.ld -o $(target)/decompress.o $(OBJECTS)
- $(OBJCOPY) $(OBJCOPYFLAGS) $(target)/decompress.o $(target)/decompress.bin
+$(obj)/decompress.o: $(OBJECTS) FORCE
+ $(call if_changed,ld)
-# Create vmlinuz image in top-level build directory
-$(target_compressed_dir)/vmlinuz: $(target) piggy.img $(target)/decompress.bin
- @echo " COMPR vmlinux.bin --> vmlinuz"
- @cat $(target)/decompress.bin piggy.img > $(target_compressed_dir)/vmlinuz
- @rm -f piggy.img
+$(obj)/decompress.bin: $(obj)/decompress.o FORCE
+ $(call if_changed,objcopy)
-$(target)/head.o: $(src)/head.S
- $(CC) -D__ASSEMBLY__ -traditional -c $< -o $@
+$(obj)/head.o: $(obj)/head.S .config
+ @$(CC) -D__ASSEMBLY__ -traditional -c $< -o $@
-$(target)/misc.o: $(src)/misc.c
- $(CC) -D__KERNEL__ -c $< -o $@
+$(obj)/misc.o: $(obj)/misc.c .config
+ @$(CC) -D__KERNEL__ -c $< -o $@
-# gzip the kernel image
+$(obj)/vmlinux: $(obj)/piggy.gz $(obj)/decompress.bin FORCE
+ $(call if_changed,image)
-piggy.img: $(SYSTEM)
- @cat $(SYSTEM) | gzip -f -9 > piggy.img
-
-$(target):
- mkdir -p $(target)
-
-clean:
- rm -f piggy.img $(objtree)/vmlinuz
+$(obj)/piggy.gz: $(obj)/../Image FORCE
+ $(call if_changed,gzip)
diff --git a/arch/cris/arch-v10/boot/compressed/misc.c b/arch/cris/arch-v10/boot/compressed/misc.c
index e205d2e7e08..9a43ab19391 100644
--- a/arch/cris/arch-v10/boot/compressed/misc.c
+++ b/arch/cris/arch-v10/boot/compressed/misc.c
@@ -1,15 +1,13 @@
/*
* misc.c
*
- * $Id: misc.c,v 1.6 2003/10/27 08:04:31 starvik Exp $
- *
- * This is a collection of several routines from gzip-1.0.3
+ * This is a collection of several routines from gzip-1.0.3
* adapted for Linux.
*
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
* puts by Nick Holloway 1993, better puts by Martin Mares 1995
* adaptation for Linux/CRIS Axis Communications AB, 1999
- *
+ *
*/
/* where the piggybacked kernel image expects itself to live.
diff --git a/arch/cris/arch-v10/boot/rescue/Makefile b/arch/cris/arch-v10/boot/rescue/Makefile
index 8be9b313031..2e5045b9e19 100644
--- a/arch/cris/arch-v10/boot/rescue/Makefile
+++ b/arch/cris/arch-v10/boot/rescue/Makefile
@@ -1,56 +1,38 @@
#
-# Makefile for rescue code
+# Makefile for rescue (bootstrap) code
#
-target = $(target_rescue_dir)
-src = $(src_rescue_dir)
CC = gcc-cris -mlinux $(LINUXINCLUDE)
-CFLAGS = -O2
+ccflags-y += -O2
+asflags-y += -traditional
LD = gcc-cris -mlinux -nostdlib
+ldflags-y += -T $(obj)/rescue.ld
OBJCOPY = objcopy-cris
OBJCOPYFLAGS = -O binary --remove-section=.bss
+obj-$(CONFIG_ETRAX_AXISFLASHMAP) = head.o
+OBJECT := $(obj)/head.o
-all: $(target)/rescue.bin $(target)/testrescue.bin $(target)/kimagerescue.bin
+targets := rescue.o rescue.bin
-$(target)/rescue.bin: $(target) $(target)/head.o
- $(LD) -T $(src)/rescue.ld -o $(target)/rescue.o $(target)/head.o
- $(OBJCOPY) $(OBJCOPYFLAGS) $(target)/rescue.o $(target)/rescue.bin
-# Place a copy in top-level build directory
- cp -p $(target)/rescue.bin $(objtree)
+$(obj)/rescue.o: $(OBJECT) FORCE
+ $(call if_changed,ld)
-$(target)/testrescue.bin: $(target) $(target)/testrescue.o
- $(OBJCOPY) $(OBJCOPYFLAGS) $(target)/testrescue.o tr.bin
+$(obj)/rescue.bin: $(obj)/rescue.o FORCE
+ $(call if_changed,objcopy)
+ cp -p $(obj)/rescue.bin $(objtree)
+
+$(obj)/testrescue.bin: $(obj)/testrescue.o
+ $(OBJCOPY) $(OBJCOPYFLAGS) $(obj)/testrescue.o tr.bin
# Pad it to 784 bytes
dd if=/dev/zero of=tmp2423 bs=1 count=784
cat tr.bin tmp2423 >testrescue_tmp.bin
- dd if=testrescue_tmp.bin of=$(target)/testrescue.bin bs=1 count=784
+ dd if=testrescue_tmp.bin of=$(obj)/testrescue.bin bs=1 count=784
rm tr.bin tmp2423 testrescue_tmp.bin
-$(target)/kimagerescue.bin: $(target) $(target)/kimagerescue.o
- $(OBJCOPY) $(OBJCOPYFLAGS) $(target)/kimagerescue.o ktr.bin
+$(obj)/kimagerescue.bin: $(obj)/kimagerescue.o
+ $(OBJCOPY) $(OBJCOPYFLAGS) $(obj)/kimagerescue.o ktr.bin
# Pad it to 784 bytes, that's what the rescue loader expects
dd if=/dev/zero of=tmp2423 bs=1 count=784
cat ktr.bin tmp2423 >kimagerescue_tmp.bin
- dd if=kimagerescue_tmp.bin of=$(target)/kimagerescue.bin bs=1 count=784
+ dd if=kimagerescue_tmp.bin of=$(obj)/kimagerescue.bin bs=1 count=784
rm ktr.bin tmp2423 kimagerescue_tmp.bin
-
-$(target):
- mkdir -p $(target)
-
-$(target)/head.o: $(src)/head.S
- $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
-
-$(target)/testrescue.o: $(src)/testrescue.S
- $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
-
-$(target)/kimagerescue.o: $(src)/kimagerescue.S
- $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
-
-clean:
- rm -f $(target)/*.o $(target)/*.bin
-
-fastdep:
-
-modules:
-
-modules-install:
diff --git a/arch/cris/arch-v10/boot/rescue/head.S b/arch/cris/arch-v10/boot/rescue/head.S
index f223cc0c00b..6ba7be8ac4a 100644
--- a/arch/cris/arch-v10/boot/rescue/head.S
+++ b/arch/cris/arch-v10/boot/rescue/head.S
@@ -1,5 +1,4 @@
-/* $Id: head.S,v 1.7 2005/03/07 12:11:06 starvik Exp $
- *
+/*
* Rescue code, made to reside at the beginning of the
* flash-memory. when it starts, it checks a partition
* table at the first sector after the rescue sector.
@@ -23,20 +22,20 @@
* Partition table format:
*
* Code transparency:
- *
+ *
* 2 bytes [opcode 'nop']
* 2 bytes [opcode 'di']
* 4 bytes [opcode 'ba <offset>', 8-bit or 16-bit version]
* 2 bytes [opcode 'nop', delay slot]
*
- * Table validation (at +10):
- *
+ * Table validation (at +10):
+ *
* 2 bytes [magic/version word for partitiontable - 0xef, 0xbe]
* 2 bytes [length of all entries plus the end marker]
* 4 bytes [checksum for the partitiontable itself]
*
- * Entries, each with the following format, last has offset -1:
- *
+ * Entries, each with the following format, last has offset -1:
+ *
* 4 bytes [offset in bytes, from start of flash]
* 4 bytes [length in bytes of partition]
* 4 bytes [checksum, simple longword sum]
@@ -47,9 +46,9 @@
* End marker
*
* 4 bytes [-1]
- *
+ *
* 10 bytes [0, padding]
- *
+ *
* Bit 0 in flags signifies RW or RO. The rescue code only bothers
* to check the checksum for RO partitions, since the others will
* change their data without updating the checksums. A 1 in bit 0
@@ -59,26 +58,29 @@
*
* During the wait for serial input, the status LED will flash so the
* user knows something went wrong.
- *
- * Copyright (C) 1999, 2000, 2001, 2002, 2003 Axis Communications AB
+ *
+ * Copyright (C) 1999-2007 Axis Communications AB
*/
+#ifdef CONFIG_ETRAX_AXISFLASHMAP
+
#define ASSEMBLER_MACROS_ONLY
#include <asm/arch/sv_addr_ag.h>
;; The partitiontable is looked for at the first sector after the boot
;; sector. Sector size is 65536 bytes in all flashes we use.
-
+
#define PTABLE_START CONFIG_ETRAX_PTABLE_SECTOR
#define PTABLE_MAGIC 0xbeef
;; The normal Etrax100 on-chip boot ROM does serial boot at 0x380000f0.
- ;; That is not where we put our downloaded serial boot-code. The length is
- ;; enough for downloading code that loads the rest of itself (after
- ;; having setup the DRAM etc). It is the same length as the on-chip
- ;; ROM loads, so the same host loader can be used to load a rescued
- ;; product as well as one booted through the Etrax serial boot code.
-
+ ;; That is not where we put our downloaded serial boot-code.
+ ;; The length is enough for downloading code that loads the rest
+ ;; of itself (after having setup the DRAM etc).
+ ;; It is the same length as the on-chip ROM loads, so the same
+ ;; host loader can be used to load a rescued product as well as
+ ;; one booted through the Etrax serial boot code.
+
#define CODE_START 0x40000000
#define CODE_LENGTH 784
@@ -102,7 +104,7 @@
#define SERRECC R_SERIAL2_REC_CTRL
#define SERRDAT R_SERIAL2_REC_DATA
#define SERSTAT R_SERIAL2_STATUS
-#endif
+#endif
#ifdef CONFIG_ETRAX_RESCUE_SER3
#define SERXOFF R_SERIAL3_XOFF
#define SERBAUD R_SERIAL3_BAUD
@@ -115,60 +117,61 @@
#define RAM_INIT_MAGIC 0x56902387
.text
-
+
;; This is the entry point of the rescue code
;; 0x80000000 if loaded in flash (as it should be)
- ;; since etrax actually starts at address 2 when booting from flash, we
+ ;; Since etrax actually starts at address 2 when booting from flash, we
;; put a nop (2 bytes) here first so we dont accidentally skip the di
- nop
+ nop
di
jump in_cache ; enter cached area instead
in_cache:
- ;; first put a jump test to give a possibility of upgrading the rescue code
- ;; without erasing/reflashing the sector. we put a longword of -1 here and if
- ;; it is not -1, we jump using the value as jump target. since we can always
- ;; change 1's to 0's without erasing the sector, it is possible to add new
+ ;; First put a jump test to give a possibility of upgrading the
+ ;; rescue code without erasing/reflashing the sector.
+ ;; We put a longword of -1 here and if it is not -1, we jump using
+ ;; the value as jump target. Since we can always change 1's to 0's
+ ;; without erasing the sector, it is possible to add new
;; code after this and altering the jumptarget in an upgrade.
jtcd: move.d [jumptarget], $r0
cmp.d 0xffffffff, $r0
beq no_newjump
nop
-
+
jump [$r0]
-jumptarget:
+jumptarget:
.dword 0xffffffff ; can be overwritten later to insert new code
-
+
no_newjump:
-#ifdef CONFIG_ETRAX_ETHERNET
+#ifdef CONFIG_ETRAX_ETHERNET
;; Start MII clock to make sure it is running when tranceiver is reset
move.d 0x3, $r0 ; enable = on, phy = mii_clk
move.d $r0, [R_NETWORK_GEN_CONFIG]
#endif
-
+
;; We need to setup the bus registers before we start using the DRAM
#include "../../lib/dram_init.S"
;; we now should go through the checksum-table and check the listed
;; partitions for errors.
-
+
move.d PTABLE_START, $r3
move.d [$r3], $r0
cmp.d NOP_DI, $r0 ; make sure the nop/di is there...
bne do_rescue
nop
-
+
;; skip the code transparency block (10 bytes).
addq 10, $r3
-
+
;; check for correct magic
-
+
move.w [$r3+], $r0
cmp.w PTABLE_MAGIC, $r0
bne do_rescue ; didn't recognize - trig rescue
@@ -186,11 +189,11 @@ no_newjump:
cmp.d $r0, $r4
bne do_rescue ; didn't match - trig rescue
nop
-
+
;; ptable is ok. validate each entry.
moveq -1, $r7
-
+
ploop: move.d [$r3+], $r1 ; partition offset (from ptable start)
bne notfirst ; check if it is the partition containing ptable
nop ; yes..
@@ -199,7 +202,7 @@ ploop: move.d [$r3+], $r1 ; partition offset (from ptable start)
sub.d $r8, $r2 ; minus the ptable length
ba bosse
nop
-notfirst:
+notfirst:
cmp.d -1, $r1 ; the end of the ptable ?
beq flash_ok ; if so, the flash is validated
move.d [$r3+], $r2 ; partition length
@@ -213,47 +216,46 @@ bosse: move.d [$r3+], $r5 ; checksum
bpl 1f
nop
move.d $r1, $r7 ; remember boot partition offset
-1:
-
+1:
add.d PTABLE_START, $r1
-
+
jsr checksum ; checksum the partition
-
+
cmp.d $r0, $r5
beq ploop ; checksums matched, go to next entry
nop
;; otherwise fall through to the rescue code.
-
+
do_rescue:
;; setup port PA and PB default initial directions and data
;; (so we can flash LEDs, and so that DTR and others are set)
-
+
move.b CONFIG_ETRAX_DEF_R_PORT_PA_DIR, $r0
move.b $r0, [R_PORT_PA_DIR]
move.b CONFIG_ETRAX_DEF_R_PORT_PA_DATA, $r0
move.b $r0, [R_PORT_PA_DATA]
-
+
move.b CONFIG_ETRAX_DEF_R_PORT_PB_DIR, $r0
move.b $r0, [R_PORT_PB_DIR]
move.b CONFIG_ETRAX_DEF_R_PORT_PB_DATA, $r0
move.b $r0, [R_PORT_PB_DATA]
;; setup the serial port at 115200 baud
-
+
moveq 0, $r0
- move.d $r0, [SERXOFF]
+ move.d $r0, [SERXOFF]
move.b 0x99, $r0
- move.b $r0, [SERBAUD] ; 115.2kbaud for both transmit and receive
+ move.b $r0, [SERBAUD] ; 115.2kbaud for both transmit and receive
- move.b 0x40, $r0 ; rec enable
- move.b $r0, [SERRECC]
+ move.b 0x40, $r0 ; rec enable
+ move.b $r0, [SERRECC]
moveq 0, $r1 ; "timer" to clock out a LED red flash
move.d CODE_START, $r3 ; destination counter
movu.w CODE_LENGTH, $r4; length
-
+
wait_ser:
addq 1, $r1
#ifndef CONFIG_ETRAX_NO_LEDS
@@ -272,20 +274,20 @@ wait_ser:
nop
1: not $r0 ; clear bit
and.d $r0, $r2
-2:
+2:
#ifdef CONFIG_ETRAX_PA_LEDS
- move.b $r2, [R_PORT_PA_DATA]
-#endif
+ move.b $r2, [R_PORT_PA_DATA]
+#endif
#ifdef CONFIG_ETRAX_PB_LEDS
- move.b $r2, [R_PORT_PB_DATA]
+ move.b $r2, [R_PORT_PB_DATA]
#endif
#ifdef CONFIG_ETRAX_90000000_LEDS
move.b $r2, [0x90000000]
#endif
#endif
-
+
;; check if we got something on the serial port
-
+
move.b [SERSTAT], $r0
btstq 0, $r0 ; data_avail
bpl wait_ser
@@ -295,14 +297,15 @@ wait_ser:
move.b [SERRDAT], $r0
move.b $r0, [$r3+]
-
+
subq 1, $r4 ; decrease length
bne wait_ser
nop
;; jump into downloaded code
- move.d RAM_INIT_MAGIC, $r8 ; Tell next product that DRAM is initialized
+ move.d RAM_INIT_MAGIC, $r8 ; Tell next product that DRAM is
+ ; initialized
jump CODE_START
flash_ok:
@@ -313,7 +316,8 @@ flash_ok:
nop
move.d PTABLE_START, $r7; otherwise use the ptable start
1:
- move.d RAM_INIT_MAGIC, $r8 ; Tell next product that DRAM is initialized
+ move.d RAM_INIT_MAGIC, $r8 ; Tell next product that DRAM is
+ ; initialized
jump $r7 ; boot!
@@ -327,7 +331,8 @@ checksum:
moveq 0, $r0
moveq CONFIG_ETRAX_FLASH1_SIZE, $r6
- ;; If the first physical flash memory is exceeded wrap to the second one.
+ ;; If the first physical flash memory is exceeded wrap to the
+ ;; second one
btstq 26, $r1 ; Are we addressing first flash?
bpl 1f
nop
@@ -351,3 +356,5 @@ checksum:
3: move.d MEM_CSE1_START, $r1 ; wrap to second flash
ba 2b
nop
+
+#endif
diff --git a/arch/cris/arch-v10/boot/rescue/kimagerescue.S b/arch/cris/arch-v10/boot/rescue/kimagerescue.S
index cbccd6316d3..55eeff8bb08 100644
--- a/arch/cris/arch-v10/boot/rescue/kimagerescue.S
+++ b/arch/cris/arch-v10/boot/rescue/kimagerescue.S
@@ -1,5 +1,4 @@
-/* $Id: kimagerescue.S,v 1.1 2001/12/17 13:59:27 bjornw Exp $
- *
+/*
* Rescue code to be prepended on a kimage and copied to the
* rescue serial port.
* This is called from the rescue code, it will copy received data to
@@ -7,13 +6,13 @@
*/
#define ASSEMBLER_MACROS_ONLY
-#include <asm/sv_addr_ag.h>
+#include <asm/arch/sv_addr_ag.h>
#define CODE_START 0x40004000
#define CODE_LENGTH 784
#define TIMEOUT_VALUE 1000
-
-
+
+
#ifdef CONFIG_ETRAX_RESCUE_SER0
#define SERXOFF R_SERIAL0_XOFF
#define SERBAUD R_SERIAL0_BAUD
@@ -34,7 +33,7 @@
#define SERRECC R_SERIAL2_REC_CTRL
#define SERRDAT R_SERIAL2_REC_DATA
#define SERSTAT R_SERIAL2_STATUS
-#endif
+#endif
#ifdef CONFIG_ETRAX_RESCUE_SER3
#define SERXOFF R_SERIAL3_XOFF
#define SERBAUD R_SERIAL3_BAUD
@@ -48,54 +47,55 @@
;; 0x80000000 if loaded in flash (as it should be)
;; since etrax actually starts at address 2 when booting from flash, we
;; put a nop (2 bytes) here first so we dont accidentally skip the di
-
- nop
+
+ nop
di
-#ifndef CONFIG_SVINTO_SIM
+#ifndef CONFIG_SVINTO_SIM
;; setup port PA and PB default initial directions and data
;; (so we can flash LEDs, and so that DTR and others are set)
-
+
move.b CONFIG_ETRAX_DEF_R_PORT_PA_DIR, $r0
move.b $r0, [R_PORT_PA_DIR]
move.b CONFIG_ETRAX_DEF_R_PORT_PA_DATA, $r0
move.b $r0, [R_PORT_PA_DATA]
-
+
move.b CONFIG_ETRAX_DEF_R_PORT_PB_DIR, $r0
move.b $r0, [R_PORT_PB_DIR]
move.b CONFIG_ETRAX_DEF_R_PORT_PB_DATA, $r0
move.b $r0, [R_PORT_PB_DATA]
-
+
;; We need to setup the bus registers before we start using the DRAM
#include "../../lib/dram_init.S"
-
+
#endif
;; Setup the stack to a suitably high address.
;; We assume 8 MB is the minimum DRAM in an eLinux
;; product and put the sp at the top for now.
move.d 0x40800000, $sp
-
+
;; setup the serial port at 115200 baud
-
+
moveq 0, $r0
- move.d $r0, [SERXOFF]
+ move.d $r0, [SERXOFF]
move.b 0x99, $r0
- move.b $r0, [SERBAUD] ; 115.2kbaud for both transmit and receive
+ move.b $r0, [SERBAUD] ; 115.2kbaud for both transmit
+ ; and receive
move.b 0x40, $r0 ; rec enable
- move.b $r0, [SERRECC]
+ move.b $r0, [SERRECC]
- moveq 0, $r1 ; "timer" to clock out a LED red flash
- move.d CODE_START, $r3 ; destination counter
+ moveq 0, $r1 ; "timer" to clock out a LED red flash
+ move.d CODE_START, $r3 ; destination counter
move.d CODE_LENGTH, $r4 ; length
move.d TIMEOUT_VALUE, $r5 ; "timeout" until jump
wait_ser:
addq 1, $r1
- subq 1, $r5 ; decrease timeout
- beq jump_start ; timed out
+ subq 1, $r5 ; decrease timeout
+ beq jump_start ; timed out
nop
#ifndef CONFIG_ETRAX_NO_LEDS
#ifdef CONFIG_ETRAX_PA_LEDS
@@ -111,21 +111,21 @@ wait_ser:
or.d $r0, $r2 ; set bit
ba 2f
nop
-1: not $r0 ; clear bit
+1: not $r0 ; clear bit
and.d $r0, $r2
-2:
+2:
#ifdef CONFIG_ETRAX_PA_LEDS
move.b $r2, [R_PORT_PA_DATA]
-#endif
+#endif
#ifdef CONFIG_ETRAX_PB_LEDS
move.b $r2, [R_PORT_PB_DATA]
#endif
#endif
-
+
;; check if we got something on the serial port
-
+
move.b [SERSTAT], $r0
- btstq 0, $r0 ; data_avail
+ btstq 0, $r0 ; data_avail
bpl wait_ser
nop
@@ -134,7 +134,7 @@ wait_ser:
move.b [SERRDAT], $r0
move.b $r0, [$r3+]
move.d TIMEOUT_VALUE, $r5 ; reset "timeout"
- subq 1, $r4 ; decrease length
+ subq 1, $r4 ; decrease length
bne wait_ser
nop
jump_start:
diff --git a/arch/cris/arch-v10/boot/rescue/testrescue.S b/arch/cris/arch-v10/boot/rescue/testrescue.S
index 566a9f34125..2d937f9afe2 100644
--- a/arch/cris/arch-v10/boot/rescue/testrescue.S
+++ b/arch/cris/arch-v10/boot/rescue/testrescue.S
@@ -1,13 +1,12 @@
-/* $Id: testrescue.S,v 1.1 2001/12/17 13:59:27 bjornw Exp $
- *
+/*
* Simple testcode to download by the rescue block.
- * Just lits some LEDs to show it was downloaded correctly.
- *
+ * Just lights some LEDs to show it was downloaded correctly.
+ *
* Copyright (C) 1999 Axis Communications AB
*/
#define ASSEMBLER_MACROS_ONLY
-#include <asm/sv_addr_ag.h>
+#include <asm/arch/sv_addr_ag.h>
.text
@@ -16,11 +15,10 @@
moveq -1, $r2
move.b $r2, [R_PORT_PA_DIR]
moveq 0, $r2
- move.b $r2, [R_PORT_PA_DATA]
+ move.b $r2, [R_PORT_PA_DATA]
endless:
nop
ba endless
nop
-
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index e3c0f292814..58f5864a668 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -1,3 +1,5 @@
+if ETRAX_ARCH_V10
+
config ETRAX_ETHERNET
bool "Ethernet support"
depends on ETRAX_ARCH_V10
@@ -7,37 +9,6 @@ config ETRAX_ETHERNET
This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
controller.
-choice
- prompt "Network LED behavior"
- depends on ETRAX_ETHERNET
- default ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY
-
-config ETRAX_NETWORK_LED_ON_WHEN_LINK
- bool "LED_on_when_link"
- help
- Selecting LED_on_when_link will light the LED when there is a
- connection and will flash off when there is activity.
-
- Selecting LED_on_when_activity will light the LED only when
- there is activity.
-
- This setting will also affect the behaviour of other activity LEDs
- e.g. Bluetooth.
-
-config ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY
- bool "LED_on_when_activity"
- help
- Selecting LED_on_when_link will light the LED when there is a
- connection and will flash off when there is activity.
-
- Selecting LED_on_when_activity will light the LED only when
- there is activity.
-
- This setting will also affect the behaviour of other activity LEDs
- e.g. Bluetooth.
-
-endchoice
-
config ETRAX_SERIAL
bool "Serial-port support"
depends on ETRAX_ARCH_V10
@@ -82,32 +53,6 @@ config ETRAX_SERIAL_PORT0
the same DMA channels.
choice
- prompt "Ser0 DMA out assignment"
- depends on ETRAX_SERIAL_PORT0
- default ETRAX_SERIAL_PORT0_DMA6_OUT
-
-config ETRAX_SERIAL_PORT0_NO_DMA_OUT
- bool "No DMA out"
-
-config ETRAX_SERIAL_PORT0_DMA6_OUT
- bool "DMA 6"
-
-endchoice
-
-choice
- prompt "Ser0 DMA in assignment"
- depends on ETRAX_SERIAL_PORT0
- default ETRAX_SERIAL_PORT0_DMA7_IN
-
-config ETRAX_SERIAL_PORT0_NO_DMA_IN
- bool "No DMA in"
-
-config ETRAX_SERIAL_PORT0_DMA7_IN
- bool "DMA 7"
-
-endchoice
-
-choice
prompt "Ser0 DTR, RI, DSR and CD assignment"
depends on ETRAX_SERIAL_PORT0
default ETRAX_SER0_DTR_RI_DSR_CD_ON_NONE
@@ -196,32 +141,6 @@ config ETRAX_SERIAL_PORT1
Enables the ETRAX 100 serial driver for ser1 (ttyS1).
choice
- prompt "Ser1 DMA out assignment"
- depends on ETRAX_SERIAL_PORT1
- default ETRAX_SERIAL_PORT1_DMA8_OUT
-
-config ETRAX_SERIAL_PORT1_NO_DMA_OUT
- bool "No DMA out"
-
-config ETRAX_SERIAL_PORT1_DMA8_OUT
- bool "DMA 8"
-
-endchoice
-
-choice
- prompt "Ser1 DMA in assignment"
- depends on ETRAX_SERIAL_PORT1
- default ETRAX_SERIAL_PORT1_DMA9_IN
-
-config ETRAX_SERIAL_PORT1_NO_DMA_IN
- bool "No DMA in"
-
-config ETRAX_SERIAL_PORT1_DMA9_IN
- bool "DMA 9"
-
-endchoice
-
-choice
prompt "Ser1 DTR, RI, DSR and CD assignment"
depends on ETRAX_SERIAL_PORT1
default ETRAX_SER1_DTR_RI_DSR_CD_ON_NONE
@@ -313,32 +232,6 @@ config ETRAX_SERIAL_PORT2
Enables the ETRAX 100 serial driver for ser2 (ttyS2).
choice
- prompt "Ser2 DMA out assignment"
- depends on ETRAX_SERIAL_PORT2
- default ETRAX_SERIAL_PORT2_DMA2_OUT
-
-config ETRAX_SERIAL_PORT2_NO_DMA_OUT
- bool "No DMA out"
-
-config ETRAX_SERIAL_PORT2_DMA2_OUT
- bool "DMA 2"
-
-endchoice
-
-choice
- prompt "Ser2 DMA in assignment"
- depends on ETRAX_SERIAL_PORT2
- default ETRAX_SERIAL_PORT2_DMA3_IN
-
-config ETRAX_SERIAL_PORT2_NO_DMA_IN
- bool "No DMA in"
-
-config ETRAX_SERIAL_PORT2_DMA3_IN
- bool "DMA 3"
-
-endchoice
-
-choice
prompt "Ser2 DTR, RI, DSR and CD assignment"
depends on ETRAX_SERIAL_PORT2
default ETRAX_SER2_DTR_RI_DSR_CD_ON_NONE
@@ -427,32 +320,6 @@ config ETRAX_SERIAL_PORT3
Enables the ETRAX 100 serial driver for ser3 (ttyS3).
choice
- prompt "Ser3 DMA out assignment"
- depends on ETRAX_SERIAL_PORT3
- default ETRAX_SERIAL_PORT3_DMA4_OUT
-
-config ETRAX_SERIAL_PORT3_NO_DMA_OUT
- bool "No DMA out"
-
-config ETRAX_SERIAL_PORT3_DMA4_OUT
- bool "DMA 4"
-
-endchoice
-
-choice
- prompt "Ser3 DMA in assignment"
- depends on ETRAX_SERIAL_PORT3
- default ETRAX_SERIAL_PORT3_DMA5_IN
-
-config ETRAX_SERIAL_PORT3_NO_DMA_IN
- bool "No DMA in"
-
-config ETRAX_SERIAL_PORT3_DMA5_IN
- bool "DMA 5"
-
-endchoice
-
-choice
prompt "Ser3 DTR, RI, DSR and CD assignment"
depends on ETRAX_SERIAL_PORT3
default ETRAX_SER3_DTR_RI_DSR_CD_ON_NONE
@@ -561,21 +428,6 @@ config ETRAX_USB_HOST_PORT2
depends on ETRAX_USB_HOST
default n
-config ETRAX_AXISFLASHMAP
- bool "Axis flash-map support"
- depends on ETRAX_ARCH_V10
- select MTD
- select MTD_CFI
- select MTD_CFI_AMDSTD
- select MTD_CHAR
- select MTD_BLOCK
- select MTD_PARTITIONS
- select MTD_CONCAT
- select MTD_COMPLEX_MAPPINGS
- help
- This option enables MTD mapping of flash devices. Needed to use
- flash memories. If unsure, say Y.
-
config ETRAX_PTABLE_SECTOR
int "Byte-offset of partition table sector"
depends on ETRAX_AXISFLASHMAP
@@ -729,37 +581,6 @@ config ETRAX_PB_CHANGEABLE_BITS
Bit set = changeable.
You probably want 00 here.
-config ETRAX_RTC
- bool "Real Time Clock support"
- depends on ETRAX_ARCH_V10
- help
- Enables drivers for the Real-Time Clock battery-backed chips on
- some products. The kernel reads the time when booting, and
- the date can be set using ioctl(fd, RTC_SET_TIME, &rt) with rt a
- rtc_time struct (see <file:include/asm-cris/rtc.h>) on the /dev/rtc
- device, major 121. You can check the time with cat /proc/rtc, but
- normal time reading should be done using libc function time and
- friends.
-
-choice
- prompt "RTC chip"
- depends on ETRAX_RTC
- default ETRAX_DS1302
-
-config ETRAX_DS1302
- bool "DS1302"
- help
- Enables the driver for the DS1302 Real-Time Clock battery-backed
- chip on some products.
-
-config ETRAX_PCF8563
- bool "PCF8563"
- help
- Enables the driver for the PCF8563 Real-Time Clock battery-backed
- chip on some products.
-
-endchoice
-
config ETRAX_DS1302_RST_ON_GENERIC_PORT
bool "DS1302 RST on Generic Port"
depends on ETRAX_DS1302
@@ -806,3 +627,5 @@ config ETRAX_DS1302_TRICKLE_CHARGE
1 = 2kohm, 2 = 4kohm, 3 = 4kohm
4 = 1 diode, 8 = 2 diodes
Allowed values are (increasing current): 0, 11, 10, 9, 7, 6, 5
+
+endif
diff --git a/arch/cris/arch-v10/drivers/Makefile b/arch/cris/arch-v10/drivers/Makefile
index 20258e36f38..44bf2e88c26 100644
--- a/arch/cris/arch-v10/drivers/Makefile
+++ b/arch/cris/arch-v10/drivers/Makefile
@@ -2,11 +2,11 @@
# Makefile for Etrax-specific drivers
#
-obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o
-obj-$(CONFIG_ETRAX_I2C) += i2c.o
-obj-$(CONFIG_ETRAX_I2C_EEPROM) += eeprom.o
-obj-$(CONFIG_ETRAX_GPIO) += gpio.o
-obj-$(CONFIG_ETRAX_DS1302) += ds1302.o
+obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o
+obj-$(CONFIG_ETRAX_I2C) += i2c.o
+obj-$(CONFIG_ETRAX_I2C_EEPROM) += eeprom.o
+obj-$(CONFIG_ETRAX_GPIO) += gpio.o
+obj-$(CONFIG_ETRAX_DS1302) += ds1302.o
obj-$(CONFIG_ETRAX_PCF8563) += pcf8563.o
-
+obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o
diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c
index ea3cf2e39a1..b3bdda93ffe 100644
--- a/arch/cris/arch-v10/drivers/axisflashmap.c
+++ b/arch/cris/arch-v10/drivers/axisflashmap.c
@@ -10,129 +10,6 @@
* tells us what other partitions to define. If there isn't, we use a default
* partition split defined below.
*
- * $Log: axisflashmap.c,v $
- * Revision 1.11 2004/11/15 10:27:14 starvik
- * Corrected typo (Thanks to Milton Miller <miltonm@bga.com>).
- *
- * Revision 1.10 2004/08/16 12:37:22 starvik
- * Merge of Linux 2.6.8
- *
- * Revision 1.8 2004/05/14 07:58:03 starvik
- * Merge of changes from 2.4
- *
- * Revision 1.6 2003/07/04 08:27:37 starvik
- * Merge of Linux 2.5.74
- *
- * Revision 1.5 2002/12/11 13:13:57 starvik
- * Added arch/ to v10 specific includes
- * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
- *
- * Revision 1.4 2002/11/20 11:56:10 starvik
- * Merge of Linux 2.5.48
- *
- * Revision 1.3 2002/11/13 14:54:13 starvik
- * Copied from linux 2.4
- *
- * Revision 1.28 2002/10/01 08:08:43 jonashg
- * The first partition ends at the start of the partition table.
- *
- * Revision 1.27 2002/08/21 09:23:13 jonashg
- * Speling.
- *
- * Revision 1.26 2002/08/21 08:35:20 jonashg
- * Cosmetic change to printouts.
- *
- * Revision 1.25 2002/08/21 08:15:42 jonashg
- * Made it compile even without CONFIG_MTD_CONCAT defined.
- *
- * Revision 1.24 2002/08/20 13:12:35 jonashg
- * * New approach to probing. Probe cse0 and cse1 separately and (mtd)concat
- * the results.
- * * Removed compile time tests concerning how the mtdram driver has been
- * configured. The user will know about the misconfiguration at runtime
- * instead. (The old approach made it impossible to use mtdram for anything
- * else than RAM boot).
- *
- * Revision 1.23 2002/05/13 12:12:28 johana
- * Allow compile without CONFIG_MTD_MTDRAM but warn at compiletime and
- * be informative at runtime.
- *
- * Revision 1.22 2002/05/13 10:24:44 johana
- * Added #if checks on MTDRAM CONFIG
- *
- * Revision 1.21 2002/05/06 16:05:20 johana
- * Removed debug printout.
- *
- * Revision 1.20 2002/05/06 16:03:00 johana
- * No more cramfs as root hack in generic code.
- * It's handled by axisflashmap using mtdram.
- *
- * Revision 1.19 2002/03/15 17:10:28 bjornw
- * Changed comment about cached access since we changed this before
- *
- * Revision 1.18 2002/03/05 17:06:15 jonashg
- * Try amd_flash probe before cfi_probe since amd_flash driver can handle two
- * (or more) flash chips of different model and the cfi driver cannot.
- *
- * Revision 1.17 2001/11/12 19:42:38 pkj
- * Fixed compiler warnings.
- *
- * Revision 1.16 2001/11/08 11:18:58 jonashg
- * Always read from uncached address to avoid problems with flushing
- * cachelines after write and MTD-erase. No performance loss have been
- * seen yet.
- *
- * Revision 1.15 2001/10/19 12:41:04 jonashg
- * Name of probe has changed in MTD.
- *
- * Revision 1.14 2001/09/21 07:14:10 jonashg
- * Made root filesystem (cramfs) use mtdblock driver when booting from flash.
- *
- * Revision 1.13 2001/08/15 13:57:35 jonashg
- * Entire MTD updated to the linux 2.4.7 version.
- *
- * Revision 1.12 2001/06/11 09:50:30 jonashg
- * Oops, 2MB is 0x200000 bytes.
- *
- * Revision 1.11 2001/06/08 11:39:44 jonashg
- * Changed sizes and offsets in axis_default_partitions to use
- * CONFIG_ETRAX_PTABLE_SECTOR.
- *
- * Revision 1.10 2001/05/29 09:42:03 jonashg
- * Use macro for end marker length instead of sizeof.
- *
- * Revision 1.9 2001/05/29 08:52:52 jonashg
- * Gave names to the magic fours (size of the ptable end marker).
- *
- * Revision 1.8 2001/05/28 15:36:20 jonashg
- * * Removed old comment about ptable location in flash (it's a CONFIG_ option).
- * * Variable ptable was initialized twice to the same value.
- *
- * Revision 1.7 2001/04/05 13:41:46 markusl
- * Updated according to review remarks
- *
- * Revision 1.6 2001/03/07 09:21:21 bjornw
- * No need to waste .data
- *
- * Revision 1.5 2001/03/06 16:27:01 jonashg
- * Probe the entire flash area for flash devices.
- *
- * Revision 1.4 2001/02/23 12:47:15 bjornw
- * Uncached flash in LOW_MAP moved from 0xe to 0x8
- *
- * Revision 1.3 2001/02/16 12:11:45 jonashg
- * MTD driver amd_flash is now included in MTD CVS repository.
- * (It's now in drivers/mtd).
- *
- * Revision 1.2 2001/02/09 11:12:22 jonashg
- * Support for AMD compatible non-CFI flash chips.
- * Only tested with Toshiba TC58FVT160 so far.
- *
- * Revision 1.1 2001/01/12 17:01:18 bjornw
- * * Added axisflashmap.c, a physical mapping for MTD that reads and understands
- * Axis partition-table format.
- *
- *
*/
#include <linux/module.h>
@@ -235,7 +112,7 @@ static struct map_info map_cse1 = {
};
/* If no partition-table was found, we use this default-set. */
-#define MAX_PARTITIONS 7
+#define MAX_PARTITIONS 7
#define NUM_DEFAULT_PARTITIONS 3
/*
@@ -300,6 +177,15 @@ static struct mtd_partition axis_partitions[MAX_PARTITIONS] = {
},
};
+#ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE
+/* Main flash device */
+static struct mtd_partition main_partition = {
+ .name = "main",
+ .size = 0,
+ .offset = 0
+};
+#endif
+
/*
* Probe a chip select for AMD-compatible (JEDEC) or CFI-compatible flash
* chips in that order (because the amd_flash-driver is faster).
@@ -316,15 +202,14 @@ static struct mtd_info *probe_cs(struct map_info *map_cs)
mtd_cs = do_map_probe("cfi_probe", map_cs);
#endif
#ifdef CONFIG_MTD_JEDECPROBE
- if (!mtd_cs) {
+ if (!mtd_cs)
mtd_cs = do_map_probe("jedec_probe", map_cs);
- }
#endif
return mtd_cs;
}
-/*
+/*
* Probe each chip select individually for flash chips. If there are chips on
* both cse0 and cse1, the mtd_info structs will be concatenated to one struct
* so that MTD partitions can cross chip boundries.
@@ -351,7 +236,7 @@ static struct mtd_info *flash_probe(void)
if (mtd_cse0 && mtd_cse1) {
#ifdef CONFIG_MTD_CONCAT
struct mtd_info *mtds[] = { mtd_cse0, mtd_cse1 };
-
+
/* Since the concatenation layer adds a small overhead we
* could try to figure out if the chips in cse0 and cse1 are
* identical and reprobe the whole cse0+cse1 window. But since
@@ -372,7 +257,7 @@ static struct mtd_info *flash_probe(void)
/* The best we can do now is to only use what we found
* at cse0.
- */
+ */
mtd_cse = mtd_cse0;
map_destroy(mtd_cse1);
}
@@ -395,7 +280,7 @@ static int __init init_axis_flash(void)
struct partitiontable_head *ptable_head = NULL;
struct partitiontable_entry *ptable;
int use_default_ptable = 1; /* Until proven otherwise. */
- const char *pmsg = " /dev/flash%d at 0x%08x, size 0x%08x\n";
+ const char pmsg[] = " /dev/flash%d at 0x%08x, size 0x%08x\n";
if (!(mymtd = flash_probe())) {
/* There's no reason to use this module if no flash chip can
@@ -435,7 +320,7 @@ static int __init init_axis_flash(void)
unsigned long offset = CONFIG_ETRAX_PTABLE_SECTOR;
unsigned char *p;
unsigned long csum = 0;
-
+
ptable = (struct partitiontable_entry *)
((unsigned long)ptable_head + sizeof(*ptable_head));
@@ -490,6 +375,16 @@ static int __init init_axis_flash(void)
pidx++;
}
+#ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE
+ if (mymtd) {
+ main_partition.size = mymtd->size;
+ err = add_mtd_partitions(mymtd, &main_partition, 1);
+ if (err)
+ panic("axisflashmap: Could not initialize "
+ "partition for whole main mtd device!\n");
+ }
+#endif
+
if (mymtd) {
if (use_default_ptable) {
printk(KERN_INFO " Using default partition table.\n");
@@ -499,9 +394,8 @@ static int __init init_axis_flash(void)
err = add_mtd_partitions(mymtd, axis_partitions, pidx);
}
- if (err) {
+ if (err)
panic("axisflashmap could not add MTD partitions!\n");
- }
}
if (!romfs_in_flash) {
@@ -515,25 +409,24 @@ static int __init init_axis_flash(void)
#else
struct mtd_info *mtd_ram;
- mtd_ram = kmalloc(sizeof(struct mtd_info),
- GFP_KERNEL);
- if (!mtd_ram) {
+ mtd_ram = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
+ if (!mtd_ram)
panic("axisflashmap couldn't allocate memory for "
"mtd_info!\n");
- }
printk(KERN_INFO " Adding RAM partition for romfs image:\n");
- printk(pmsg, pidx, romfs_start, romfs_length);
-
- err = mtdram_init_device(mtd_ram, (void*)romfs_start,
- romfs_length, "romfs");
- if (err) {
+ printk(pmsg, pidx, (unsigned)romfs_start,
+ (unsigned)romfs_length);
+
+ err = mtdram_init_device(mtd_ram,
+ (void *)romfs_start,
+ romfs_length,
+ "romfs");
+ if (err)
panic("axisflashmap could not initialize MTD RAM "
"device!\n");
- }
#endif
}
-
return err;
}
diff --git a/arch/cris/arch-v10/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c
index 1d1936a1813..c9aa3904be0 100644
--- a/arch/cris/arch-v10/drivers/ds1302.c
+++ b/arch/cris/arch-v10/drivers/ds1302.c
@@ -333,7 +333,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
ds1302_writereg(RTC_TRICKLECHARGER, tcs_val);
return 0;
}
- case RTC_VLOW_RD:
+ case RTC_VL_READ:
{
/* TODO:
* Implement voltage low detection support
@@ -342,7 +342,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
" is not supported\n");
return 0;
}
- case RTC_VLOW_SET:
+ case RTC_VL_CLR:
{
/* TODO:
* Nothing to do since Voltage Low detection is not supported
diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c
index be35a70798a..f1cac9dc75b 100644
--- a/arch/cris/arch-v10/drivers/eeprom.c
+++ b/arch/cris/arch-v10/drivers/eeprom.c
@@ -19,77 +19,6 @@
*! Sep 03 1999 Edgar Iglesias Added bail-out stuff if we get interrupted
*! in the spin-lock.
*!
-*! $Log: eeprom.c,v $
-*! Revision 1.12 2005/06/19 17:06:46 starvik
-*! Merge of Linux 2.6.12.
-*!
-*! Revision 1.11 2005/01/26 07:14:46 starvik
-*! Applied diff from kernel janitors (Nish Aravamudan).
-*!
-*! Revision 1.10 2003/09/11 07:29:48 starvik
-*! Merge of Linux 2.6.0-test5
-*!
-*! Revision 1.9 2003/07/04 08:27:37 starvik
-*! Merge of Linux 2.5.74
-*!
-*! Revision 1.8 2003/04/09 05:20:47 starvik
-*! Merge of Linux 2.5.67
-*!
-*! Revision 1.6 2003/02/10 07:19:28 starvik
-*! Removed misplaced ;
-*!
-*! Revision 1.5 2002/12/11 13:13:57 starvik
-*! Added arch/ to v10 specific includes
-*! Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
-*!
-*! Revision 1.4 2002/11/20 11:56:10 starvik
-*! Merge of Linux 2.5.48
-*!
-*! Revision 1.3 2002/11/18 13:16:06 starvik
-*! Linux 2.5 port of latest 2.4 drivers
-*!
-*! Revision 1.8 2001/06/15 13:24:29 jonashg
-*! * Added verification of pointers from userspace in read and write.
-*! * Made busy counter volatile.
-*! * Added define for initial write delay.
-*! * Removed warnings by using loff_t instead of unsigned long.
-*!
-*! Revision 1.7 2001/06/14 15:26:54 jonashg
-*! Removed test because condition is always true.
-*!
-*! Revision 1.6 2001/06/14 15:18:20 jonashg
-*! Kb -> kB (makes quite a difference if you don't know if you have 2k or 16k).
-*!
-*! Revision 1.5 2001/06/14 14:39:51 jonashg
-*! Forgot to use name when registering the driver.
-*!
-*! Revision 1.4 2001/06/14 14:35:47 jonashg
-*! * Gave driver a name and used it in printk's.
-*! * Cleanup.
-*!
-*! Revision 1.3 2001/03/19 16:04:46 markusl
-*! Fixed init of fops struct
-*!
-*! Revision 1.2 2001/03/19 10:35:07 markusl
-*! 2.4 port of eeprom driver
-*!
-*! Revision 1.8 2000/05/18 10:42:25 edgar
-*! Make sure to end write cycle on _every_ write
-*!
-*! Revision 1.7 2000/01/17 17:41:01 johana
-*! Adjusted probing and return -ENOSPC when writing outside EEPROM
-*!
-*! Revision 1.6 2000/01/17 15:50:36 johana
-*! Added adaptive timing adjustments and fixed autoprobing for 2k and 16k(?)
-*! EEPROMs
-*!
-*! Revision 1.5 1999/09/03 15:07:37 edgar
-*! Added bail-out check to the spinlock
-*!
-*! Revision 1.4 1999/09/03 12:11:17 bjornw
-*! Proper atomicity (need to use spinlocks, not if's). users -> busy.
-*!
-*!
*! (c) 1999 Axis Communications AB, Lund, Sweden
*!*****************************************************************************/
@@ -103,10 +32,10 @@
#include <asm/uaccess.h>
#include "i2c.h"
-#define D(x)
+#define D(x)
/* If we should use adaptive timing or not: */
-//#define EEPROM_ADAPTIVE_TIMING
+/* #define EEPROM_ADAPTIVE_TIMING */
#define EEPROM_MAJOR_NR 122 /* use a LOCAL/EXPERIMENTAL major for now */
#define EEPROM_MINOR_NR 0
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index 0d347a70583..68a998bd106 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -1,138 +1,11 @@
-/* $Id: gpio.c,v 1.17 2005/06/19 17:06:46 starvik Exp $
- *
+/*
* Etrax general port I/O device
*
- * Copyright (c) 1999, 2000, 2001, 2002 Axis Communications AB
+ * Copyright (c) 1999-2007 Axis Communications AB
*
* Authors: Bjorn Wesen (initial version)
* Ola Knutsson (LED handling)
* Johan Adolfsson (read/set directions, write, port G)
- *
- * $Log: gpio.c,v $
- * Revision 1.17 2005/06/19 17:06:46 starvik
- * Merge of Linux 2.6.12.
- *
- * Revision 1.16 2005/03/07 13:02:29 starvik
- * Protect driver global states with spinlock
- *
- * Revision 1.15 2005/01/05 06:08:55 starvik
- * No need to do local_irq_disable after local_irq_save.
- *
- * Revision 1.14 2004/12/13 12:21:52 starvik
- * Added I/O and DMA allocators from Linux 2.4
- *
- * Revision 1.12 2004/08/24 07:19:59 starvik
- * Whitespace cleanup
- *
- * Revision 1.11 2004/05/14 07:58:03 starvik
- * Merge of changes from 2.4
- *
- * Revision 1.9 2003/09/11 07:29:48 starvik
- * Merge of Linux 2.6.0-test5
- *
- * Revision 1.8 2003/07/04 08:27:37 starvik
- * Merge of Linux 2.5.74
- *
- * Revision 1.7 2003/01/10 07:44:07 starvik
- * init_ioremap is now called by kernel before drivers are initialized
- *
- * Revision 1.6 2002/12/11 13:13:57 starvik
- * Added arch/ to v10 specific includes
- * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
- *
- * Revision 1.5 2002/11/20 11:56:11 starvik
- * Merge of Linux 2.5.48
- *
- * Revision 1.4 2002/11/18 10:10:05 starvik
- * Linux 2.5 port of latest gpio.c from Linux 2.4
- *
- * Revision 1.20 2002/10/16 21:16:24 johana
- * Added support for PA high level interrupt.
- * That gives 2ms response time with iodtest for high levels and 2-12 ms
- * response time on low levels if the check is not made in
- * process.c:cpu_idle() as well.
- *
- * Revision 1.19 2002/10/14 18:27:33 johana
- * Implemented alarm handling so select() now works.
- * Latency is around 6-9 ms with a etrax_gpio_wake_up_check() in
- * cpu_idle().
- * Otherwise I get 15-18 ms (same as doing the poll in userspace -
- * but less overhead).
- * TODO? Perhaps we should add the check in IMMEDIATE_BH (or whatever it
- * is in 2.4) as well?
- * TODO? Perhaps call request_irq()/free_irq() only when needed?
- * Increased version to 2.5
- *
- * Revision 1.18 2002/10/11 15:02:00 johana
- * Mask inverted 8 bit value in setget_input().
- *
- * Revision 1.17 2002/06/17 15:53:01 johana
- * Added IO_READ_INBITS, IO_READ_OUTBITS, IO_SETGET_INPUT and IO_SETGET_OUTPUT
- * that take a pointer as argument and thus can handle 32 bit ports (G)
- * correctly.
- * These should be used instead of IO_READBITS, IO_SETINPUT and IO_SETOUTPUT.
- * (especially if Port G bit 31 is used)
- *
- * Revision 1.16 2002/06/17 09:59:51 johana
- * Returning 32 bit values in the ioctl return value doesn't work if bit
- * 31 is set (could happen for port G), so mask it of with 0x7FFFFFFF.
- * A new set of ioctl's will be added.
- *
- * Revision 1.15 2002/05/06 13:19:13 johana
- * IO_SETINPUT returns mask with bit set = inputs for PA and PB as well.
- *
- * Revision 1.14 2002/04/12 12:01:53 johana
- * Use global r_port_g_data_shadow.
- * Moved gpio_init_port_g() closer to gpio_init() and marked it __init.
- *
- * Revision 1.13 2002/04/10 12:03:55 johana
- * Added support for port G /dev/gpiog (minor 3).
- * Changed indentation on switch cases.
- * Fixed other spaces to tabs.
- *
- * Revision 1.12 2001/11/12 19:42:15 pkj
- * * Corrected return values from gpio_leds_ioctl().
- * * Fixed compiler warnings.
- *
- * Revision 1.11 2001/10/30 14:39:12 johana
- * Added D() around gpio_write printk.
- *
- * Revision 1.10 2001/10/25 10:24:42 johana
- * Added IO_CFG_WRITE_MODE ioctl and write method that can do fast
- * bittoggling in the kernel. (This speeds up programming an FPGA with 450kB
- * from ~60 seconds to 4 seconds).
- * Added save_flags/cli/restore_flags in ioctl.
- *
- * Revision 1.9 2001/05/04 14:16:07 matsfg
- * Corrected spelling error
- *
- * Revision 1.8 2001/04/27 13:55:26 matsfg
- * Moved initioremap.
- * Turns off all LEDS on init.
- * Added support for shutdown and powerbutton.
- *
- * Revision 1.7 2001/04/04 13:30:08 matsfg
- * Added bitset and bitclear for leds. Calls init_ioremap to set up memmapping
- *
- * Revision 1.6 2001/03/26 16:03:06 bjornw
- * Needs linux/config.h
- *
- * Revision 1.5 2001/03/26 14:22:03 bjornw
- * Namechange of some config options
- *
- * Revision 1.4 2001/02/27 13:52:48 bjornw
- * malloc.h -> slab.h
- *
- * Revision 1.3 2001/01/24 15:06:48 bjornw
- * gpio_wq correct type
- *
- * Revision 1.2 2001/01/18 16:07:30 bjornw
- * 2.4 port
- *
- * Revision 1.1 2001/01/18 15:55:16 bjornw
- * Verbatim copy of etraxgpio.c from elinux 2.0 added
- *
- *
*/
@@ -165,7 +38,7 @@ static int dp_cnt;
#else
#define DP(x)
#endif
-
+
static char gpio_name[] = "etrax gpio";
#if 0
@@ -173,9 +46,9 @@ static wait_queue_head_t *gpio_wq;
#endif
static int gpio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
-static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
- loff_t *off);
+ unsigned int cmd, unsigned long arg);
+static ssize_t gpio_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *off);
static int gpio_open(struct inode *inode, struct file *filp);
static int gpio_release(struct inode *inode, struct file *filp);
static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
@@ -201,22 +74,22 @@ struct gpio_private {
/* linked list of alarms to check for */
-static struct gpio_private *alarmlist = 0;
+static struct gpio_private *alarmlist;
-static int gpio_some_alarms = 0; /* Set if someone uses alarm */
-static unsigned long gpio_pa_irq_enabled_mask = 0;
+static int gpio_some_alarms; /* Set if someone uses alarm */
+static unsigned long gpio_pa_irq_enabled_mask;
static DEFINE_SPINLOCK(gpio_lock); /* Protect directions etc */
/* Port A and B use 8 bit access, but Port G is 32 bit */
#define NUM_PORTS (GPIO_MINOR_B+1)
-static volatile unsigned char *ports[NUM_PORTS] = {
- R_PORT_PA_DATA,
+static volatile unsigned char *ports[NUM_PORTS] = {
+ R_PORT_PA_DATA,
R_PORT_PB_DATA,
};
static volatile unsigned char *shads[NUM_PORTS] = {
- &port_pa_data_shadow,
+ &port_pa_data_shadow,
&port_pb_data_shadow
};
@@ -236,29 +109,29 @@ static volatile unsigned char *shads[NUM_PORTS] = {
#endif
-static unsigned char changeable_dir[NUM_PORTS] = {
+static unsigned char changeable_dir[NUM_PORTS] = {
CONFIG_ETRAX_PA_CHANGEABLE_DIR,
- CONFIG_ETRAX_PB_CHANGEABLE_DIR
+ CONFIG_ETRAX_PB_CHANGEABLE_DIR
};
-static unsigned char changeable_bits[NUM_PORTS] = {
+static unsigned char changeable_bits[NUM_PORTS] = {
CONFIG_ETRAX_PA_CHANGEABLE_BITS,
- CONFIG_ETRAX_PB_CHANGEABLE_BITS
+ CONFIG_ETRAX_PB_CHANGEABLE_BITS
};
-static volatile unsigned char *dir[NUM_PORTS] = {
- R_PORT_PA_DIR,
- R_PORT_PB_DIR
+static volatile unsigned char *dir[NUM_PORTS] = {
+ R_PORT_PA_DIR,
+ R_PORT_PB_DIR
};
static volatile unsigned char *dir_shadow[NUM_PORTS] = {
- &port_pa_dir_shadow,
- &port_pb_dir_shadow
+ &port_pa_dir_shadow,
+ &port_pb_dir_shadow
};
/* All bits in port g that can change dir. */
static const unsigned long int changeable_dir_g_mask = 0x01FFFF01;
-/* Port G is 32 bit, handle it special, some bits are both inputs
+/* Port G is 32 bit, handle it special, some bits are both inputs
and outputs at the same time, only some of the bits can change direction
and some of them in groups of 8 bit. */
static unsigned long changeable_dir_g;
@@ -269,18 +142,17 @@ static unsigned long dir_g_shadow; /* 1=output */
#define USE_PORTS(priv) ((priv)->minor <= GPIO_MINOR_B)
-
-static unsigned int
-gpio_poll(struct file *file,
- poll_table *wait)
+static unsigned int gpio_poll(struct file *file, poll_table *wait)
{
unsigned int mask = 0;
- struct gpio_private *priv = (struct gpio_private *)file->private_data;
+ struct gpio_private *priv = file->private_data;
unsigned long data;
- spin_lock(&gpio_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
poll_wait(file, &priv->alarm_wq, wait);
if (priv->minor == GPIO_MINOR_A) {
- unsigned long flags;
unsigned long tmp;
data = *R_PORT_PA_DATA;
/* PA has support for high level interrupt -
@@ -288,27 +160,25 @@ gpio_poll(struct file *file,
*/
tmp = ~data & priv->highalarm & 0xFF;
tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
- local_irq_save(flags);
+
gpio_pa_irq_enabled_mask |= tmp;
*R_IRQ_MASK1_SET = tmp;
- local_irq_restore(flags);
-
} else if (priv->minor == GPIO_MINOR_B)
data = *R_PORT_PB_DATA;
else if (priv->minor == GPIO_MINOR_G)
data = *R_PORT_G_DATA;
else {
- spin_unlock(&gpio_lock);
- return 0;
+ mask = 0;
+ goto out;
}
-
+
if ((data & priv->highalarm) ||
(~data & priv->lowalarm)) {
mask = POLLIN|POLLRDNORM;
}
- spin_unlock(&gpio_lock);
-
+out:
+ spin_unlock_irqrestore(&gpio_lock, flags);
DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
return mask;
@@ -316,16 +186,19 @@ gpio_poll(struct file *file,
int etrax_gpio_wake_up_check(void)
{
- struct gpio_private *priv = alarmlist;
+ struct gpio_private *priv;
unsigned long data = 0;
int ret = 0;
- spin_lock(&gpio_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+ priv = alarmlist;
while (priv) {
- if (USE_PORTS(priv)) {
+ if (USE_PORTS(priv))
data = *priv->port;
- } else if (priv->minor == GPIO_MINOR_G) {
+ else if (priv->minor == GPIO_MINOR_G)
data = *R_PORT_G_DATA;
- }
+
if ((data & priv->highalarm) ||
(~data & priv->lowalarm)) {
DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor));
@@ -334,12 +207,12 @@ int etrax_gpio_wake_up_check(void)
}
priv = priv->next;
}
- spin_unlock(&gpio_lock);
+ spin_unlock_irqrestore(&gpio_lock, flags);
return ret;
}
static irqreturn_t
-gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+gpio_poll_timer_interrupt(int irq, void *dev_id)
{
if (gpio_some_alarms) {
etrax_gpio_wake_up_check();
@@ -349,10 +222,13 @@ gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
static irqreturn_t
-gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+gpio_interrupt(int irq, void *dev_id)
{
unsigned long tmp;
- spin_lock(&gpio_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
/* Find what PA interrupts are active */
tmp = (*R_IRQ_READ1);
@@ -363,75 +239,70 @@ gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*R_IRQ_MASK1_CLR = tmp;
gpio_pa_irq_enabled_mask &= ~tmp;
- spin_unlock(&gpio_lock);
+ spin_unlock_irqrestore(&gpio_lock, flags);
- if (gpio_some_alarms) {
+ if (gpio_some_alarms)
return IRQ_RETVAL(etrax_gpio_wake_up_check());
- }
+
return IRQ_NONE;
}
+static void gpio_write_bit(struct gpio_private *priv,
+ unsigned char data, int bit)
+{
+ *priv->port = *priv->shadow &= ~(priv->clk_mask);
+ if (data & 1 << bit)
+ *priv->port = *priv->shadow |= priv->data_mask;
+ else
+ *priv->port = *priv->shadow &= ~(priv->data_mask);
+
+ /* For FPGA: min 5.0ns (DCC) before CCLK high */
+ *priv->port = *priv->shadow |= priv->clk_mask;
+}
-static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
- loff_t *off)
+static void gpio_write_byte(struct gpio_private *priv, unsigned char data)
{
- struct gpio_private *priv = (struct gpio_private *)file->private_data;
- unsigned char data, clk_mask, data_mask, write_msb;
- unsigned long flags;
+ int i;
- spin_lock(&gpio_lock);
+ if (priv->write_msb)
+ for (i = 7; i >= 0; i--)
+ gpio_write_bit(priv, data, i);
+ else
+ for (i = 0; i <= 7; i++)
+ gpio_write_bit(priv, data, i);
+}
+static ssize_t gpio_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ struct gpio_private *priv = file->private_data;
+ unsigned long flags;
ssize_t retval = count;
- if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
- retval = -EFAULT;
- goto out;
- }
-
- if (!access_ok(VERIFY_READ, buf, count)) {
- retval = -EFAULT;
- goto out;
- }
- clk_mask = priv->clk_mask;
- data_mask = priv->data_mask;
+
+ if (priv->minor != GPIO_MINOR_A && priv->minor != GPIO_MINOR_B)
+ return -EFAULT;
+
+ if (!access_ok(VERIFY_READ, buf, count))
+ return -EFAULT;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
/* It must have been configured using the IO_CFG_WRITE_MODE */
/* Perhaps a better error code? */
- if (clk_mask == 0 || data_mask == 0) {
+ if (priv->clk_mask == 0 || priv->data_mask == 0) {
retval = -EPERM;
goto out;
}
- write_msb = priv->write_msb;
- D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
- while (count--) {
- int i;
- data = *buf++;
- if (priv->write_msb) {
- for (i = 7; i >= 0;i--) {
- local_irq_save(flags);
- *priv->port = *priv->shadow &= ~clk_mask;
- if (data & 1<<i)
- *priv->port = *priv->shadow |= data_mask;
- else
- *priv->port = *priv->shadow &= ~data_mask;
- /* For FPGA: min 5.0ns (DCC) before CCLK high */
- *priv->port = *priv->shadow |= clk_mask;
- local_irq_restore(flags);
- }
- } else {
- for (i = 0; i <= 7;i++) {
- local_irq_save(flags);
- *priv->port = *priv->shadow &= ~clk_mask;
- if (data & 1<<i)
- *priv->port = *priv->shadow |= data_mask;
- else
- *priv->port = *priv->shadow &= ~data_mask;
- /* For FPGA: min 5.0ns (DCC) before CCLK high */
- *priv->port = *priv->shadow |= clk_mask;
- local_irq_restore(flags);
- }
- }
- }
+
+ D(printk(KERN_DEBUG "gpio_write: %02X to data 0x%02X "
+ "clk 0x%02X msb: %i\n",
+ count, priv->data_mask, priv->clk_mask, priv->write_msb));
+
+ while (count--)
+ gpio_write_byte(priv, *buf++);
+
out:
- spin_unlock(&gpio_lock);
+ spin_unlock_irqrestore(&gpio_lock, flags);
return retval;
}
@@ -442,22 +313,20 @@ gpio_open(struct inode *inode, struct file *filp)
{
struct gpio_private *priv;
int p = iminor(inode);
+ unsigned long flags;
if (p > GPIO_MINOR_LAST)
return -EINVAL;
- priv = kmalloc(sizeof(struct gpio_private),
- GFP_KERNEL);
+ priv = kzalloc(sizeof(struct gpio_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->minor = p;
- /* initialize the io/alarm struct and link it into our alarmlist */
+ /* initialize the io/alarm struct */
- priv->next = alarmlist;
- alarmlist = priv;
if (USE_PORTS(priv)) { /* A and B */
priv->port = ports[p];
priv->shadow = shads[p];
@@ -480,7 +349,13 @@ gpio_open(struct inode *inode, struct file *filp)
priv->data_mask = 0;
init_waitqueue_head(&priv->alarm_wq);
- filp->private_data = (void *)priv;
+ filp->private_data = priv;
+
+ /* link it into our alarmlist */
+ spin_lock_irqsave(&gpio_lock, flags);
+ priv->next = alarmlist;
+ alarmlist = priv;
+ spin_unlock_irqrestore(&gpio_lock, flags);
return 0;
}
@@ -490,11 +365,12 @@ gpio_release(struct inode *inode, struct file *filp)
{
struct gpio_private *p;
struct gpio_private *todel;
+ unsigned long flags;
- spin_lock(&gpio_lock);
+ spin_lock_irqsave(&gpio_lock, flags);
- p = alarmlist;
- todel = (struct gpio_private *)filp->private_data;
+ p = alarmlist;
+ todel = filp->private_data;
/* unlink from alarmlist and free the private structure */
@@ -512,123 +388,114 @@ gpio_release(struct inode *inode, struct file *filp)
while (p) {
if (p->highalarm | p->lowalarm) {
gpio_some_alarms = 1;
- spin_unlock(&gpio_lock);
- return 0;
+ goto out;
}
p = p->next;
}
gpio_some_alarms = 0;
- spin_unlock(&gpio_lock);
+out:
+ spin_unlock_irqrestore(&gpio_lock, flags);
return 0;
}
-/* Main device API. ioctl's to read/set/clear bits, as well as to
+/* Main device API. ioctl's to read/set/clear bits, as well as to
* set alarms to wait for using a subsequent select().
*/
-
unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
{
- /* Set direction 0=unchanged 1=input,
- * return mask with 1=input
- */
- unsigned long flags;
+ /* Set direction 0=unchanged 1=input,
+ * return mask with 1=input */
if (USE_PORTS(priv)) {
- local_irq_save(flags);
- *priv->dir = *priv->dir_shadow &=
+ *priv->dir = *priv->dir_shadow &=
~((unsigned char)arg & priv->changeable_dir);
- local_irq_restore(flags);
return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */
- } else if (priv->minor == GPIO_MINOR_G) {
- /* We must fiddle with R_GEN_CONFIG to change dir */
- local_irq_save(flags);
- if (((arg & dir_g_in_bits) != arg) &&
- (arg & changeable_dir_g)) {
- arg &= changeable_dir_g;
- /* Clear bits in genconfig to set to input */
- if (arg & (1<<0)) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g0dir);
- dir_g_in_bits |= (1<<0);
- dir_g_out_bits &= ~(1<<0);
- }
- if ((arg & 0x0000FF00) == 0x0000FF00) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g8_15dir);
- dir_g_in_bits |= 0x0000FF00;
- dir_g_out_bits &= ~0x0000FF00;
- }
- if ((arg & 0x00FF0000) == 0x00FF0000) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g16_23dir);
- dir_g_in_bits |= 0x00FF0000;
- dir_g_out_bits &= ~0x00FF0000;
- }
- if (arg & (1<<24)) {
- genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g24dir);
- dir_g_in_bits |= (1<<24);
- dir_g_out_bits &= ~(1<<24);
- }
- D(printk(KERN_INFO "gpio: SETINPUT on port G set "
- "genconfig to 0x%08lX "
- "in_bits: 0x%08lX "
- "out_bits: 0x%08lX\n",
- (unsigned long)genconfig_shadow,
- dir_g_in_bits, dir_g_out_bits));
- *R_GEN_CONFIG = genconfig_shadow;
- /* Must be a >120 ns delay before writing this again */
-
+ }
+
+ if (priv->minor != GPIO_MINOR_G)
+ return 0;
+
+ /* We must fiddle with R_GEN_CONFIG to change dir */
+ if (((arg & dir_g_in_bits) != arg) &&
+ (arg & changeable_dir_g)) {
+ arg &= changeable_dir_g;
+ /* Clear bits in genconfig to set to input */
+ if (arg & (1<<0)) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, g0dir);
+ dir_g_in_bits |= (1<<0);
+ dir_g_out_bits &= ~(1<<0);
}
- local_irq_restore(flags);
- return dir_g_in_bits;
+ if ((arg & 0x0000FF00) == 0x0000FF00) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, g8_15dir);
+ dir_g_in_bits |= 0x0000FF00;
+ dir_g_out_bits &= ~0x0000FF00;
+ }
+ if ((arg & 0x00FF0000) == 0x00FF0000) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, g16_23dir);
+ dir_g_in_bits |= 0x00FF0000;
+ dir_g_out_bits &= ~0x00FF0000;
+ }
+ if (arg & (1<<24)) {
+ genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, g24dir);
+ dir_g_in_bits |= (1<<24);
+ dir_g_out_bits &= ~(1<<24);
+ }
+ D(printk(KERN_DEBUG "gpio: SETINPUT on port G set "
+ "genconfig to 0x%08lX "
+ "in_bits: 0x%08lX "
+ "out_bits: 0x%08lX\n",
+ (unsigned long)genconfig_shadow,
+ dir_g_in_bits, dir_g_out_bits));
+ *R_GEN_CONFIG = genconfig_shadow;
+ /* Must be a >120 ns delay before writing this again */
+
}
- return 0;
+ return dir_g_in_bits;
} /* setget_input */
unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
{
- unsigned long flags;
if (USE_PORTS(priv)) {
- local_irq_save(flags);
- *priv->dir = *priv->dir_shadow |=
- ((unsigned char)arg & priv->changeable_dir);
- local_irq_restore(flags);
+ *priv->dir = *priv->dir_shadow |=
+ ((unsigned char)arg & priv->changeable_dir);
return *priv->dir_shadow;
- } else if (priv->minor == GPIO_MINOR_G) {
- /* We must fiddle with R_GEN_CONFIG to change dir */
- local_irq_save(flags);
- if (((arg & dir_g_out_bits) != arg) &&
- (arg & changeable_dir_g)) {
- /* Set bits in genconfig to set to output */
- if (arg & (1<<0)) {
- genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g0dir);
- dir_g_out_bits |= (1<<0);
- dir_g_in_bits &= ~(1<<0);
- }
- if ((arg & 0x0000FF00) == 0x0000FF00) {
- genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g8_15dir);
- dir_g_out_bits |= 0x0000FF00;
- dir_g_in_bits &= ~0x0000FF00;
- }
- if ((arg & 0x00FF0000) == 0x00FF0000) {
- genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g16_23dir);
- dir_g_out_bits |= 0x00FF0000;
- dir_g_in_bits &= ~0x00FF0000;
- }
- if (arg & (1<<24)) {
- genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g24dir);
- dir_g_out_bits |= (1<<24);
- dir_g_in_bits &= ~(1<<24);
- }
- D(printk(KERN_INFO "gpio: SETOUTPUT on port G set "
- "genconfig to 0x%08lX "
- "in_bits: 0x%08lX "
- "out_bits: 0x%08lX\n",
- (unsigned long)genconfig_shadow,
- dir_g_in_bits, dir_g_out_bits));
- *R_GEN_CONFIG = genconfig_shadow;
- /* Must be a >120 ns delay before writing this again */
+ }
+ if (priv->minor != GPIO_MINOR_G)
+ return 0;
+
+ /* We must fiddle with R_GEN_CONFIG to change dir */
+ if (((arg & dir_g_out_bits) != arg) &&
+ (arg & changeable_dir_g)) {
+ /* Set bits in genconfig to set to output */
+ if (arg & (1<<0)) {
+ genconfig_shadow |= IO_MASK(R_GEN_CONFIG, g0dir);
+ dir_g_out_bits |= (1<<0);
+ dir_g_in_bits &= ~(1<<0);
}
- local_irq_restore(flags);
- return dir_g_out_bits & 0x7FFFFFFF;
+ if ((arg & 0x0000FF00) == 0x0000FF00) {
+ genconfig_shadow |= IO_MASK(R_GEN_CONFIG, g8_15dir);
+ dir_g_out_bits |= 0x0000FF00;
+ dir_g_in_bits &= ~0x0000FF00;
+ }
+ if ((arg & 0x00FF0000) == 0x00FF0000) {
+ genconfig_shadow |= IO_MASK(R_GEN_CONFIG, g16_23dir);
+ dir_g_out_bits |= 0x00FF0000;
+ dir_g_in_bits &= ~0x00FF0000;
+ }
+ if (arg & (1<<24)) {
+ genconfig_shadow |= IO_MASK(R_GEN_CONFIG, g24dir);
+ dir_g_out_bits |= (1<<24);
+ dir_g_in_bits &= ~(1<<24);
+ }
+ D(printk(KERN_INFO "gpio: SETOUTPUT on port G set "
+ "genconfig to 0x%08lX "
+ "in_bits: 0x%08lX "
+ "out_bits: 0x%08lX\n",
+ (unsigned long)genconfig_shadow,
+ dir_g_in_bits, dir_g_out_bits));
+ *R_GEN_CONFIG = genconfig_shadow;
+ /* Must be a >120 ns delay before writing this again */
}
- return 0;
+ return dir_g_out_bits & 0x7FFFFFFF;
} /* setget_output */
static int
@@ -642,12 +509,11 @@ gpio_ioctl(struct inode *inode, struct file *file,
unsigned long val;
int ret = 0;
- struct gpio_private *priv = (struct gpio_private *)file->private_data;
- if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
+ struct gpio_private *priv = file->private_data;
+ if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE)
return -EINVAL;
- }
- spin_lock(&gpio_lock);
+ spin_lock_irqsave(&gpio_lock, flags);
switch (_IOC_NR(cmd)) {
case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
@@ -659,7 +525,6 @@ gpio_ioctl(struct inode *inode, struct file *file,
}
break;
case IO_SETBITS:
- local_irq_save(flags);
// set changeable bits with a 1 in arg
if (USE_PORTS(priv)) {
*priv->port = *priv->shadow |=
@@ -667,10 +532,8 @@ gpio_ioctl(struct inode *inode, struct file *file,
} else if (priv->minor == GPIO_MINOR_G) {
*R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits);
}
- local_irq_restore(flags);
break;
case IO_CLRBITS:
- local_irq_save(flags);
// clear changeable bits with a 1 in arg
if (USE_PORTS(priv)) {
*priv->port = *priv->shadow &=
@@ -678,7 +541,6 @@ gpio_ioctl(struct inode *inode, struct file *file,
} else if (priv->minor == GPIO_MINOR_G) {
*R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits);
}
- local_irq_restore(flags);
break;
case IO_HIGHALARM:
// set alarm when bits with 1 in arg go high
@@ -698,6 +560,8 @@ gpio_ioctl(struct inode *inode, struct file *file,
/* Must update gpio_some_alarms */
struct gpio_private *p = alarmlist;
int some_alarms;
+ spin_lock_irq(&gpio_lock);
+ p = alarmlist;
some_alarms = 0;
while (p) {
if (p->highalarm | p->lowalarm) {
@@ -707,6 +571,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
p = p->next;
}
gpio_some_alarms = some_alarms;
+ spin_unlock_irq(&gpio_lock);
}
break;
case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
@@ -766,7 +631,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
} else if (priv->minor == GPIO_MINOR_G) {
val = *R_PORT_G_DATA;
}
- if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
ret = -EFAULT;
break;
case IO_READ_OUTBITS:
@@ -776,33 +641,32 @@ gpio_ioctl(struct inode *inode, struct file *file,
} else if (priv->minor == GPIO_MINOR_G) {
val = port_g_data_shadow;
}
- if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
ret = -EFAULT;
break;
case IO_SETGET_INPUT:
/* bits set in *arg is set to input,
* *arg updated with current input pins.
*/
- if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
+ if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
{
ret = -EFAULT;
break;
}
val = setget_input(priv, val);
- if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
ret = -EFAULT;
break;
case IO_SETGET_OUTPUT:
/* bits set in *arg is set to output,
* *arg updated with current output pins.
*/
- if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
- {
+ if (copy_from_user(&val, (void __user *)arg, sizeof(val))) {
ret = -EFAULT;
break;
}
val = setget_output(priv, val);
- if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
ret = -EFAULT;
break;
default:
@@ -812,7 +676,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
ret = -EINVAL;
} /* switch */
- spin_unlock(&gpio_lock);
+ spin_unlock_irqrestore(&gpio_lock, flags);
return ret;
}
@@ -824,18 +688,18 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
switch (_IOC_NR(cmd)) {
case IO_LEDACTIVE_SET:
- green = ((unsigned char) arg) & 1;
- red = (((unsigned char) arg) >> 1) & 1;
- LED_ACTIVE_SET_G(green);
- LED_ACTIVE_SET_R(red);
+ green = ((unsigned char)arg) & 1;
+ red = (((unsigned char)arg) >> 1) & 1;
+ CRIS_LED_ACTIVE_SET_G(green);
+ CRIS_LED_ACTIVE_SET_R(red);
break;
case IO_LED_SETBIT:
- LED_BIT_SET(arg);
+ CRIS_LED_BIT_SET(arg);
break;
case IO_LED_CLRBIT:
- LED_BIT_CLR(arg);
+ CRIS_LED_BIT_CLR(arg);
break;
default:
@@ -845,7 +709,7 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
return 0;
}
-const struct file_operations gpio_fops = {
+static const struct file_operations gpio_fops = {
.owner = THIS_MODULE,
.poll = gpio_poll,
.ioctl = gpio_ioctl,
@@ -854,16 +718,18 @@ const struct file_operations gpio_fops = {
.release = gpio_release,
};
-
-void ioif_watcher(const unsigned int gpio_in_available,
- const unsigned int gpio_out_available,
- const unsigned char pa_available,
- const unsigned char pb_available)
+static void ioif_watcher(const unsigned int gpio_in_available,
+ const unsigned int gpio_out_available,
+ const unsigned char pa_available,
+ const unsigned char pb_available)
{
unsigned long int flags;
- D(printk("gpio.c: ioif_watcher called\n"));
- D(printk("gpio.c: G in: 0x%08x G out: 0x%08x PA: 0x%02x PB: 0x%02x\n",
- gpio_in_available, gpio_out_available, pa_available, pb_available));
+
+ D(printk(KERN_DEBUG "gpio.c: ioif_watcher called\n"));
+ D(printk(KERN_DEBUG "gpio.c: G in: 0x%08x G out: 0x%08x "
+ "PA: 0x%02x PB: 0x%02x\n",
+ gpio_in_available, gpio_out_available,
+ pa_available, pb_available));
spin_lock_irqsave(&gpio_lock, flags);
@@ -872,7 +738,7 @@ void ioif_watcher(const unsigned int gpio_in_available,
/* Initialise the dir_g_shadow etc. depending on genconfig */
/* 0=input 1=output */
- if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g0dir, out))
+ if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g0dir, out))
dir_g_shadow |= (1 << 0);
if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g8_15dir, out))
dir_g_shadow |= 0x0000FF00;
@@ -884,7 +750,8 @@ void ioif_watcher(const unsigned int gpio_in_available,
changeable_dir_g = changeable_dir_g_mask;
changeable_dir_g &= dir_g_out_bits;
changeable_dir_g &= dir_g_in_bits;
- /* Correct the bits that can change direction */
+
+ /* Correct the bits that can change direction */
dir_g_out_bits &= ~changeable_dir_g;
dir_g_out_bits |= dir_g_shadow;
dir_g_in_bits &= ~changeable_dir_g;
@@ -892,7 +759,8 @@ void ioif_watcher(const unsigned int gpio_in_available,
spin_unlock_irqrestore(&gpio_lock, flags);
- printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
+ printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX "
+ "val: %08lX\n",
dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);
printk(KERN_INFO "GPIO port G: dir: %08lX changeable: %08lX\n",
dir_g_shadow, changeable_dir_g);
@@ -900,16 +768,12 @@ void ioif_watcher(const unsigned int gpio_in_available,
/* main driver initialization routine, called from mem.c */
-static __init int
-gpio_init(void)
+static int __init gpio_init(void)
{
int res;
#if defined (CONFIG_ETRAX_CSP0_LEDS)
int i;
#endif
- printk("gpio init\n");
-
- /* do the formalities */
res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
if (res < 0) {
@@ -919,43 +783,45 @@ gpio_init(void)
/* Clear all leds */
#if defined (CONFIG_ETRAX_CSP0_LEDS) || defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS)
- LED_NETWORK_SET(0);
- LED_ACTIVE_SET(0);
- LED_DISK_READ(0);
- LED_DISK_WRITE(0);
+ CRIS_LED_NETWORK_SET(0);
+ CRIS_LED_ACTIVE_SET(0);
+ CRIS_LED_DISK_READ(0);
+ CRIS_LED_DISK_WRITE(0);
#if defined (CONFIG_ETRAX_CSP0_LEDS)
- for (i = 0; i < 32; i++) {
- LED_BIT_SET(i);
- }
+ for (i = 0; i < 32; i++)
+ CRIS_LED_BIT_SET(i);
#endif
#endif
/* The I/O interface allocation watcher will be called when
* registering it. */
if (cris_io_interface_register_watcher(ioif_watcher)){
- printk(KERN_WARNING "gpio_init: Failed to install IO if allocator watcher\n");
+ printk(KERN_WARNING "gpio_init: Failed to install IO "
+ "if allocator watcher\n");
}
- printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002, 2003, 2004 Axis Communications AB\n");
+ printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001-2008 "
+ "Axis Communications AB\n");
/* We call etrax_gpio_wake_up_check() from timer interrupt and
* from cpu_idle() in kernel/process.c
* The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
* in some tests.
- */
- if (request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
- IRQF_SHARED | IRQF_DISABLED,"gpio poll", NULL)) {
+ */
+ res = request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
+ IRQF_SHARED | IRQF_DISABLED, "gpio poll", gpio_name);
+ if (res) {
printk(KERN_CRIT "err: timer0 irq for gpio\n");
+ return res;
}
- if (request_irq(PA_IRQ_NBR, gpio_pa_interrupt,
- IRQF_SHARED | IRQF_DISABLED,"gpio PA", NULL)) {
+ res = request_irq(PA_IRQ_NBR, gpio_interrupt,
+ IRQF_SHARED | IRQF_DISABLED, "gpio PA", gpio_name);
+ if (res)
printk(KERN_CRIT "err: PA irq for gpio\n");
- }
-
return res;
}
/* this makes sure that gpio_init is called during kernel boot */
-
module_init(gpio_init);
+
diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c
index aca81ddaf60..d6d22067d0c 100644
--- a/arch/cris/arch-v10/drivers/i2c.c
+++ b/arch/cris/arch-v10/drivers/i2c.c
@@ -6,85 +6,9 @@
*! kernel modules (i2c_writereg/readreg) and from userspace using
*! ioctl()'s
*!
-*! Nov 30 1998 Torbjorn Eliasson Initial version.
-*! Bjorn Wesen Elinux kernel version.
-*! Jan 14 2000 Johan Adolfsson Fixed PB shadow register stuff -
-*! don't use PB_I2C if DS1302 uses same bits,
-*! use PB.
-*! $Log: i2c.c,v $
-*! Revision 1.13 2005/03/07 13:13:07 starvik
-*! Added spinlocks to protect states etc
-*!
-*! Revision 1.12 2005/01/05 06:11:22 starvik
-*! No need to do local_irq_disable after local_irq_save.
-*!
-*! Revision 1.11 2004/12/13 12:21:52 starvik
-*! Added I/O and DMA allocators from Linux 2.4
-*!
-*! Revision 1.9 2004/08/24 06:49:14 starvik
-*! Whitespace cleanup
-*!
-*! Revision 1.8 2004/06/08 08:48:26 starvik
-*! Removed unused code
-*!
-*! Revision 1.7 2004/05/28 09:26:59 starvik
-*! Modified I2C initialization to work in 2.6.
-*!
-*! Revision 1.6 2004/05/14 07:58:03 starvik
-*! Merge of changes from 2.4
-*!
-*! Revision 1.4 2002/12/11 13:13:57 starvik
-*! Added arch/ to v10 specific includes
-*! Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
-*!
-*! Revision 1.3 2002/11/20 11:56:11 starvik
-*! Merge of Linux 2.5.48
-*!
-*! Revision 1.2 2002/11/18 13:16:06 starvik
-*! Linux 2.5 port of latest 2.4 drivers
-*!
-*! Revision 1.9 2002/10/31 15:32:26 starvik
-*! Update Port B register and shadow even when running with hardware support
-*! to avoid glitches when reading bits
-*! Never set direction to out in i2c_inbyte
-*! Removed incorrect clock toggling at end of i2c_inbyte
-*!
-*! Revision 1.8 2002/08/13 06:31:53 starvik
-*! Made SDA and SCL line configurable
-*! Modified i2c_inbyte to work with PCF8563
-*!
-*! Revision 1.7 2001/04/04 13:11:36 markusl
-*! Updated according to review remarks
-*!
-*! Revision 1.6 2001/03/19 12:43:00 markusl
-*! Made some symbols unstatic (used by the eeprom driver)
-*!
-*! Revision 1.5 2001/02/27 13:52:48 bjornw
-*! malloc.h -> slab.h
-*!
-*! Revision 1.4 2001/02/15 07:17:40 starvik
-*! Corrected usage if port_pb_i2c_shadow
-*!
-*! Revision 1.3 2001/01/26 17:55:13 bjornw
-*! * Made I2C_USES_PB_NOT_PB_I2C a CONFIG option instead of assigning it
-*! magically. Config.in needs to set it for the options that need it, like
-*! Dallas 1302 support. Actually, it should be default since it screws up
-*! the PB bits even if you don't use I2C..
-*! * Include linux/config.h to get the above
-*!
-*! Revision 1.2 2001/01/18 15:49:30 bjornw
-*! 2.4 port of I2C including some cleanups (untested of course)
-*!
-*! Revision 1.1 2001/01/18 15:35:25 bjornw
-*! Verbatim copy of the Etrax i2c driver, 2.0 elinux version
-*!
-*!
-*! ---------------------------------------------------------------------------
-*!
-*! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN
+*! (C) Copyright 1999-2007 Axis Communications AB, LUND, SWEDEN
*!
*!***************************************************************************/
-/* $Id: i2c.c,v 1.13 2005/03/07 13:13:07 starvik Exp $ */
/****************** INCLUDE FILES SECTION ***********************************/
@@ -622,7 +546,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
* last received byte needs to be nacked
* instead of acked
*/
- i2c_sendack();
+ i2c_sendnack();
/*
* end sequence
*/
@@ -708,6 +632,7 @@ i2c_init(void)
if (!first) {
return res;
}
+ first = 0;
/* Setup and enable the Port B I2C interface */
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c
index c263b8232db..52103d16dc6 100644
--- a/arch/cris/arch-v10/drivers/pcf8563.c
+++ b/arch/cris/arch-v10/drivers/pcf8563.c
@@ -8,14 +8,13 @@
* low detector are also provided. All address and data are transferred
* serially via two-line bidirectional I2C-bus. Maximum bus speed is
* 400 kbits/s. The built-in word address register is incremented
- * automatically after each written or read bute.
+ * automatically after each written or read byte.
*
- * Copyright (c) 2002, Axis Communications AB
+ * Copyright (c) 2002-2007, Axis Communications AB
* All rights reserved.
*
* Author: Tobias Anderberg <tobiasa@axis.com>.
*
- * $Id: pcf8563.c,v 1.11 2005/03/07 13:13:07 starvik Exp $
*/
#include <linux/module.h>
@@ -27,19 +26,19 @@
#include <linux/ioctl.h>
#include <linux/delay.h>
#include <linux/bcd.h>
-#include <linux/capability.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/arch/svinto.h>
#include <asm/rtc.h>
+
#include "i2c.h"
-#define PCF8563_MAJOR 121 /* Local major number. */
-#define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */
+#define PCF8563_MAJOR 121 /* Local major number. */
+#define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */
#define PCF8563_NAME "PCF8563"
-#define DRIVER_VERSION "$Revision: 1.11 $"
+#define DRIVER_VERSION "$Revision: 1.24 $"
/* I2C bus slave registers. */
#define RTC_I2C_READ 0xa3
@@ -49,71 +48,88 @@
#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
-static DEFINE_SPINLOCK(rtc_lock); /* Protect state etc */
-
+static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
+
static const unsigned char days_in_month[] =
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+/* Cache VL bit value read at driver init since writing the RTC_SECOND
+ * register clears the VL status.
+ */
+static int voltage_low;
+
static const struct file_operations pcf8563_fops = {
.owner = THIS_MODULE,
.ioctl = pcf8563_ioctl,
};
unsigned char
-pcf8563_readreg(int reg)
+pcf8563_readreg(int reg)
{
- unsigned char res = i2c_readreg(RTC_I2C_READ, reg);
-
- /* The PCF8563 does not return 0 for unimplemented bits */
- switch(reg)
- {
- case RTC_SECONDS:
- case RTC_MINUTES:
- res &= 0x7f;
- break;
- case RTC_HOURS:
- case RTC_DAY_OF_MONTH:
- res &= 0x3f;
- break;
- case RTC_MONTH:
- res = (res & 0x1f) - 1; /* PCF8563 returns month in range 1-12 */
- break;
+ unsigned char res = rtc_read(reg);
+
+ /* The PCF8563 does not return 0 for unimplemented bits. */
+ switch (reg) {
+ case RTC_SECONDS:
+ case RTC_MINUTES:
+ res &= 0x7F;
+ break;
+ case RTC_HOURS:
+ case RTC_DAY_OF_MONTH:
+ res &= 0x3F;
+ break;
+ case RTC_WEEKDAY:
+ res &= 0x07;
+ break;
+ case RTC_MONTH:
+ res &= 0x1F;
+ break;
+ case RTC_CONTROL1:
+ res &= 0xA8;
+ break;
+ case RTC_CONTROL2:
+ res &= 0x1F;
+ break;
+ case RTC_CLOCKOUT_FREQ:
+ case RTC_TIMER_CONTROL:
+ res &= 0x83;
+ break;
}
return res;
}
void
-pcf8563_writereg(int reg, unsigned char val)
+pcf8563_writereg(int reg, unsigned char val)
{
-#ifdef CONFIG_ETRAX_RTC_READONLY
- if (reg == RTC_CONTROL1 || (reg >= RTC_SECONDS && reg <= RTC_YEAR))
- return;
-#endif
-
rtc_write(reg, val);
}
void
get_rtc_time(struct rtc_time *tm)
{
- tm->tm_sec = rtc_read(RTC_SECONDS);
- tm->tm_min = rtc_read(RTC_MINUTES);
+ tm->tm_sec = rtc_read(RTC_SECONDS);
+ tm->tm_min = rtc_read(RTC_MINUTES);
tm->tm_hour = rtc_read(RTC_HOURS);
tm->tm_mday = rtc_read(RTC_DAY_OF_MONTH);
- tm->tm_mon = rtc_read(RTC_MONTH);
+ tm->tm_wday = rtc_read(RTC_WEEKDAY);
+ tm->tm_mon = rtc_read(RTC_MONTH);
tm->tm_year = rtc_read(RTC_YEAR);
- if (tm->tm_sec & 0x80)
- printk(KERN_WARNING "%s: RTC Low Voltage - date/time is not reliable!\n", PCF8563_NAME);
+ if (tm->tm_sec & 0x80) {
+ printk(KERN_ERR "%s: RTC Voltage Low - reliable date/time "
+ "information is no longer guaranteed!\n", PCF8563_NAME);
+ }
- tm->tm_year = BCD_TO_BIN(tm->tm_year) + ((tm->tm_mon & 0x80) ? 100 : 0);
- tm->tm_sec &= 0x7f;
- tm->tm_min &= 0x7f;
- tm->tm_hour &= 0x3f;
- tm->tm_mday &= 0x3f;
- tm->tm_mon &= 0x1f;
+ tm->tm_year = BCD_TO_BIN(tm->tm_year) +
+ ((tm->tm_mon & 0x80) ? 100 : 0);
+ tm->tm_sec &= 0x7F;
+ tm->tm_min &= 0x7F;
+ tm->tm_hour &= 0x3F;
+ tm->tm_mday &= 0x3F;
+ tm->tm_wday &= 0x07; /* Not coded in BCD. */
+ tm->tm_mon &= 0x1F;
BCD_TO_BIN(tm->tm_sec);
BCD_TO_BIN(tm->tm_min);
@@ -126,17 +142,24 @@ get_rtc_time(struct rtc_time *tm)
int __init
pcf8563_init(void)
{
- int ret;
-
- if ((ret = i2c_init())) {
- printk(KERN_CRIT "pcf8563_init: failed to init i2c\n");
- return ret;
+ static int res;
+ static int first = 1;
+
+ if (!first)
+ return res;
+ first = 0;
+
+ /* Initiate the i2c protocol. */
+ res = i2c_init();
+ if (res < 0) {
+ printk(KERN_CRIT "pcf8563_init: Failed to init i2c.\n");
+ return res;
}
/*
* First of all we need to reset the chip. This is done by
- * clearing control1, control2 and clk freq, clear the
- * Voltage Low bit, and resetting all alarms.
+ * clearing control1, control2 and clk freq and resetting
+ * all alarms.
*/
if (rtc_write(RTC_CONTROL1, 0x00) < 0)
goto err;
@@ -147,34 +170,36 @@ pcf8563_init(void)
if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0)
goto err;
- /* Clear the VL bit in the seconds register. */
- ret = rtc_read(RTC_SECONDS);
-
- if (rtc_write(RTC_SECONDS, (ret & 0x7f)) < 0)
+ if (rtc_write(RTC_TIMER_CONTROL, 0x03) < 0)
goto err;
-
+
/* Reset the alarms. */
- if (rtc_write(RTC_MINUTE_ALARM, 0x00) < 0)
+ if (rtc_write(RTC_MINUTE_ALARM, 0x80) < 0)
goto err;
-
- if (rtc_write(RTC_HOUR_ALARM, 0x00) < 0)
+
+ if (rtc_write(RTC_HOUR_ALARM, 0x80) < 0)
goto err;
-
- if (rtc_write(RTC_DAY_ALARM, 0x00) < 0)
+
+ if (rtc_write(RTC_DAY_ALARM, 0x80) < 0)
goto err;
-
- if (rtc_write(RTC_WEEKDAY_ALARM, 0x00) < 0)
+
+ if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0)
goto err;
-
- /* Check for low voltage, and warn about it.. */
- if (rtc_read(RTC_SECONDS) & 0x80)
- printk(KERN_WARNING "%s: RTC Low Voltage - date/time is not reliable!\n", PCF8563_NAME);
-
- return 0;
+
+ /* Check for low voltage, and warn about it. */
+ if (rtc_read(RTC_SECONDS) & 0x80) {
+ voltage_low = 1;
+ printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
+ "date/time information is no longer guaranteed!\n",
+ PCF8563_NAME);
+ }
+
+ return res;
err:
printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME);
- return -1;
+ res = -1;
+ return res;
}
void __exit
@@ -187,8 +212,8 @@ pcf8563_exit(void)
* ioctl calls for this driver. Why return -ENOTTY upon error? Because
* POSIX says so!
*/
-int
-pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
{
/* Some sanity checks. */
if (_IOC_TYPE(cmd) != RTC_MAGIC)
@@ -198,124 +223,146 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
return -ENOTTY;
switch (cmd) {
- case RTC_RD_TIME:
- {
- struct rtc_time tm;
-
- spin_lock(&rtc_lock);
- get_rtc_time(&tm);
-
- if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) {
- spin_unlock(&rtc_lock);
- return -EFAULT;
- }
-
- spin_unlock(&rtc_lock);
- return 0;
- }
- break;
- case RTC_SET_TIME:
- {
-#ifdef CONFIG_ETRAX_RTC_READONLY
- return -EPERM;
-#else
- int leap;
- int century;
- struct rtc_time tm;
-
- memset(&tm, 0, sizeof (struct rtc_time));
- if (!capable(CAP_SYS_TIME))
- return -EPERM;
-
- if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(struct rtc_time)))
- return -EFAULT;
-
- /* Convert from struct tm to struct rtc_time. */
- tm.tm_year += 1900;
- tm.tm_mon += 1;
-
- leap = ((tm.tm_mon == 2) && ((tm.tm_year % 4) == 0)) ? 1 : 0;
-
- /* Perform some sanity checks. */
- if ((tm.tm_year < 1970) ||
- (tm.tm_mon > 12) ||
- (tm.tm_mday == 0) ||
- (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
- (tm.tm_hour >= 24) ||
- (tm.tm_min >= 60) ||
- (tm.tm_sec >= 60))
- return -EINVAL;
-
- century = (tm.tm_year >= 2000) ? 0x80 : 0;
- tm.tm_year = tm.tm_year % 100;
-
- BIN_TO_BCD(tm.tm_year);
- BIN_TO_BCD(tm.tm_mday);
- BIN_TO_BCD(tm.tm_hour);
- BIN_TO_BCD(tm.tm_min);
- BIN_TO_BCD(tm.tm_sec);
- tm.tm_mon |= century;
-
- spin_lock(&rtc_lock);
-
- rtc_write(RTC_YEAR, tm.tm_year);
- rtc_write(RTC_MONTH, tm.tm_mon);
- rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
- rtc_write(RTC_HOURS, tm.tm_hour);
- rtc_write(RTC_MINUTES, tm.tm_min);
- rtc_write(RTC_SECONDS, tm.tm_sec);
-
- spin_unlock(&rtc_lock);
-
- return 0;
-#endif /* !CONFIG_ETRAX_RTC_READONLY */
- }
-
- case RTC_VLOW_RD:
- {
- int vl_bit = 0;
-
- if (rtc_read(RTC_SECONDS) & 0x80) {
- vl_bit = 1;
- printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
- "date/time information is no longer guaranteed!\n",
- PCF8563_NAME);
- }
- if (copy_to_user((int *) arg, &vl_bit, sizeof(int)))
- return -EFAULT;
-
- return 0;
- }
+ case RTC_RD_TIME:
+ {
+ struct rtc_time tm;
- case RTC_VLOW_SET:
- {
- /* Clear the VL bit in the seconds register */
- int ret = rtc_read(RTC_SECONDS);
+ mutex_lock(&rtc_lock);
+ memset(&tm, 0, sizeof tm);
+ get_rtc_time(&tm);
- rtc_write(RTC_SECONDS, (ret & 0x7F));
+ if (copy_to_user((struct rtc_time *) arg, &tm,
+ sizeof tm)) {
+ spin_unlock(&rtc_lock);
+ return -EFAULT;
+ }
+
+ mutex_unlock(&rtc_lock);
- return 0;
+ return 0;
+ }
+ case RTC_SET_TIME:
+ {
+ int leap;
+ int year;
+ int century;
+ struct rtc_time tm;
+
+ memset(&tm, 0, sizeof tm);
+ if (!capable(CAP_SYS_TIME))
+ return -EPERM;
+
+ if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof tm))
+ return -EFAULT;
+
+ /* Convert from struct tm to struct rtc_time. */
+ tm.tm_year += 1900;
+ tm.tm_mon += 1;
+
+ /*
+ * Check if tm.tm_year is a leap year. A year is a leap
+ * year if it is divisible by 4 but not 100, except
+ * that years divisible by 400 _are_ leap years.
+ */
+ year = tm.tm_year;
+ leap = (tm.tm_mon == 2) &&
+ ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
+
+ /* Perform some sanity checks. */
+ if ((tm.tm_year < 1970) ||
+ (tm.tm_mon > 12) ||
+ (tm.tm_mday == 0) ||
+ (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
+ (tm.tm_wday >= 7) ||
+ (tm.tm_hour >= 24) ||
+ (tm.tm_min >= 60) ||
+ (tm.tm_sec >= 60))
+ return -EINVAL;
+
+ century = (tm.tm_year >= 2000) ? 0x80 : 0;
+ tm.tm_year = tm.tm_year % 100;
+
+ BIN_TO_BCD(tm.tm_year);
+ BIN_TO_BCD(tm.tm_mon);
+ BIN_TO_BCD(tm.tm_mday);
+ BIN_TO_BCD(tm.tm_hour);
+ BIN_TO_BCD(tm.tm_min);
+ BIN_TO_BCD(tm.tm_sec);
+ tm.tm_mon |= century;
+
+ mutex_lock(&rtc_lock);
+
+ rtc_write(RTC_YEAR, tm.tm_year);
+ rtc_write(RTC_MONTH, tm.tm_mon);
+ rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */
+ rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
+ rtc_write(RTC_HOURS, tm.tm_hour);
+ rtc_write(RTC_MINUTES, tm.tm_min);
+ rtc_write(RTC_SECONDS, tm.tm_sec);
+
+ mutex_unlock(&rtc_lock);
+
+ return 0;
+ }
+ case RTC_VL_READ:
+ if (voltage_low) {
+ printk(KERN_ERR "%s: RTC Voltage Low - "
+ "reliable date/time information is no "
+ "longer guaranteed!\n", PCF8563_NAME);
}
- default:
- return -ENOTTY;
+ if (copy_to_user((int *) arg, &voltage_low, sizeof(int)))
+ return -EFAULT;
+ return 0;
+
+ case RTC_VL_CLR:
+ {
+ /* Clear the VL bit in the seconds register in case
+ * the time has not been set already (which would
+ * have cleared it). This does not really matter
+ * because of the cached voltage_low value but do it
+ * anyway for consistency. */
+
+ int ret = rtc_read(RTC_SECONDS);
+
+ rtc_write(RTC_SECONDS, (ret & 0x7F));
+
+ /* Clear the cached value. */
+ voltage_low = 0;
+
+ return 0;
+ }
+ default:
+ return -ENOTTY;
}
return 0;
}
-static int __init
-pcf8563_register(void)
+static int __init pcf8563_register(void)
{
- pcf8563_init();
+ if (pcf8563_init() < 0) {
+ printk(KERN_INFO "%s: Unable to initialize Real-Time Clock "
+ "Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);
+ return -1;
+ }
+
if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
printk(KERN_INFO "%s: Unable to get major number %d for RTC device.\n",
PCF8563_NAME, PCF8563_MAJOR);
return -1;
}
- printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);
- return 0;
+ printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME,
+ DRIVER_VERSION);
+
+ /* Check for low voltage, and warn about it. */
+ if (voltage_low) {
+ printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "
+ "information is no longer guaranteed!\n", PCF8563_NAME);
+ }
+
+ return 0;
}
module_init(pcf8563_register);
diff --git a/arch/cris/arch-v10/drivers/sync_serial.c b/arch/cris/arch-v10/drivers/sync_serial.c
new file mode 100644
index 00000000000..069546e342c
--- /dev/null
+++ b/arch/cris/arch-v10/drivers/sync_serial.c
@@ -0,0 +1,1441 @@
+/*
+ * Simple synchronous serial port driver for ETRAX 100LX.
+ *
+ * Synchronous serial ports are used for continuous streamed data like audio.
+ * The default setting for this driver is compatible with the STA 013 MP3
+ * decoder. The driver can easily be tuned to fit other audio encoder/decoders
+ * and SPI
+ *
+ * Copyright (c) 2001-2008 Axis Communications AB
+ *
+ * Author: Mikael Starvik, Johan Adolfsson
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/arch/svinto.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/sync_serial.h>
+#include <asm/arch/io_interface_mux.h>
+
+/* The receiver is a bit tricky beacuse of the continuous stream of data.*/
+/* */
+/* Three DMA descriptors are linked together. Each DMA descriptor is */
+/* responsible for port->bufchunk of a common buffer. */
+/* */
+/* +---------------------------------------------+ */
+/* | +----------+ +----------+ +----------+ | */
+/* +-> | Descr[0] |-->| Descr[1] |-->| Descr[2] |-+ */
+/* +----------+ +----------+ +----------+ */
+/* | | | */
+/* v v v */
+/* +-------------------------------------+ */
+/* | BUFFER | */
+/* +-------------------------------------+ */
+/* |<- data_avail ->| */
+/* readp writep */
+/* */
+/* If the application keeps up the pace readp will be right after writep.*/
+/* If the application can't keep the pace we have to throw away data. */
+/* The idea is that readp should be ready with the data pointed out by */
+/* Descr[i] when the DMA has filled in Descr[i+1]. */
+/* Otherwise we will discard */
+/* the rest of the data pointed out by Descr1 and set readp to the start */
+/* of Descr2 */
+
+#define SYNC_SERIAL_MAJOR 125
+
+/* IN_BUFFER_SIZE should be a multiple of 6 to make sure that 24 bit */
+/* words can be handled */
+#define IN_BUFFER_SIZE 12288
+#define IN_DESCR_SIZE 256
+#define NUM_IN_DESCR (IN_BUFFER_SIZE/IN_DESCR_SIZE)
+#define OUT_BUFFER_SIZE 4096
+
+#define DEFAULT_FRAME_RATE 0
+#define DEFAULT_WORD_RATE 7
+
+/* NOTE: Enabling some debug will likely cause overrun or underrun,
+ * especially if manual mode is use.
+ */
+#define DEBUG(x)
+#define DEBUGREAD(x)
+#define DEBUGWRITE(x)
+#define DEBUGPOLL(x)
+#define DEBUGRXINT(x)
+#define DEBUGTXINT(x)
+
+/* Define some macros to access ETRAX 100 registers */
+#define SETF(var, reg, field, val) \
+ do { \
+ var = (var & ~IO_MASK_(reg##_, field##_)) | \
+ IO_FIELD_(reg##_, field##_, val); \
+ } while (0)
+
+#define SETS(var, reg, field, val) \
+ do { \
+ var = (var & ~IO_MASK_(reg##_, field##_)) | \
+ IO_STATE_(reg##_, field##_, _##val); \
+ } while (0)
+
+struct sync_port {
+ /* Etrax registers and bits*/
+ const volatile unsigned *const status;
+ volatile unsigned *const ctrl_data;
+ volatile unsigned *const output_dma_first;
+ volatile unsigned char *const output_dma_cmd;
+ volatile unsigned char *const output_dma_clr_irq;
+ volatile unsigned *const input_dma_first;
+ volatile unsigned char *const input_dma_cmd;
+ volatile unsigned *const input_dma_descr;
+ /* 8*4 */
+ volatile unsigned char *const input_dma_clr_irq;
+ volatile unsigned *const data_out;
+ const volatile unsigned *const data_in;
+ char data_avail_bit; /* In R_IRQ_MASK1_RD/SET/CLR */
+ char transmitter_ready_bit; /* In R_IRQ_MASK1_RD/SET/CLR */
+ char input_dma_descr_bit; /* In R_IRQ_MASK2_RD */
+
+ char output_dma_bit; /* In R_IRQ_MASK2_RD */
+ /* End of fields initialised in array */
+ char started; /* 1 if port has been started */
+ char port_nbr; /* Port 0 or 1 */
+ char busy; /* 1 if port is busy */
+
+ char enabled; /* 1 if port is enabled */
+ char use_dma; /* 1 if port uses dma */
+ char tr_running;
+
+ char init_irqs;
+
+ /* Register shadow */
+ unsigned int ctrl_data_shadow;
+ /* Remaining bytes for current transfer */
+ volatile unsigned int out_count;
+ /* Current position in out_buffer */
+ unsigned char *outp;
+ /* 16*4 */
+ /* Next byte to be read by application */
+ volatile unsigned char *volatile readp;
+ /* Next byte to be written by etrax */
+ volatile unsigned char *volatile writep;
+
+ unsigned int in_buffer_size;
+ unsigned int inbufchunk;
+ struct etrax_dma_descr out_descr __attribute__ ((aligned(32)));
+ struct etrax_dma_descr in_descr[NUM_IN_DESCR] __attribute__ ((aligned(32)));
+ unsigned char out_buffer[OUT_BUFFER_SIZE] __attribute__ ((aligned(32)));
+ unsigned char in_buffer[IN_BUFFER_SIZE]__attribute__ ((aligned(32)));
+ unsigned char flip[IN_BUFFER_SIZE] __attribute__ ((aligned(32)));
+ struct etrax_dma_descr *next_rx_desc;
+ struct etrax_dma_descr *prev_rx_desc;
+ int full;
+
+ wait_queue_head_t out_wait_q;
+ wait_queue_head_t in_wait_q;
+};
+
+
+static int etrax_sync_serial_init(void);
+static void initialize_port(int portnbr);
+static inline int sync_data_avail(struct sync_port *port);
+
+static int sync_serial_open(struct inode *inode, struct file *file);
+static int sync_serial_release(struct inode *inode, struct file *file);
+static unsigned int sync_serial_poll(struct file *filp, poll_table *wait);
+
+static int sync_serial_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static ssize_t sync_serial_write(struct file *file, const char *buf,
+ size_t count, loff_t *ppos);
+static ssize_t sync_serial_read(struct file *file, char *buf,
+ size_t count, loff_t *ppos);
+
+#if ((defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \
+ defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)) || \
+ (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) && \
+ defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA)))
+#define SYNC_SER_DMA
+#endif
+
+static void send_word(struct sync_port *port);
+static void start_dma(struct sync_port *port, const char *data, int count);
+static void start_dma_in(struct sync_port *port);
+#ifdef SYNC_SER_DMA
+static irqreturn_t tr_interrupt(int irq, void *dev_id);
+static irqreturn_t rx_interrupt(int irq, void *dev_id);
+#endif
+#if ((defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \
+ !defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)) || \
+ (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) && \
+ !defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA)))
+#define SYNC_SER_MANUAL
+#endif
+#ifdef SYNC_SER_MANUAL
+static irqreturn_t manual_interrupt(int irq, void *dev_id);
+#endif
+
+/* The ports */
+static struct sync_port ports[] = {
+ {
+ .status = R_SYNC_SERIAL1_STATUS,
+ .ctrl_data = R_SYNC_SERIAL1_CTRL,
+ .output_dma_first = R_DMA_CH8_FIRST,
+ .output_dma_cmd = R_DMA_CH8_CMD,
+ .output_dma_clr_irq = R_DMA_CH8_CLR_INTR,
+ .input_dma_first = R_DMA_CH9_FIRST,
+ .input_dma_cmd = R_DMA_CH9_CMD,
+ .input_dma_descr = R_DMA_CH9_DESCR,
+ .input_dma_clr_irq = R_DMA_CH9_CLR_INTR,
+ .data_out = R_SYNC_SERIAL1_TR_DATA,
+ .data_in = R_SYNC_SERIAL1_REC_DATA,
+ .data_avail_bit = IO_BITNR(R_IRQ_MASK1_RD, ser1_data),
+ .transmitter_ready_bit = IO_BITNR(R_IRQ_MASK1_RD, ser1_ready),
+ .input_dma_descr_bit = IO_BITNR(R_IRQ_MASK2_RD, dma9_descr),
+ .output_dma_bit = IO_BITNR(R_IRQ_MASK2_RD, dma8_eop),
+ .init_irqs = 1,
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)
+ .use_dma = 1,
+#else
+ .use_dma = 0,
+#endif
+ },
+ {
+ .status = R_SYNC_SERIAL3_STATUS,
+ .ctrl_data = R_SYNC_SERIAL3_CTRL,
+ .output_dma_first = R_DMA_CH4_FIRST,
+ .output_dma_cmd = R_DMA_CH4_CMD,
+ .output_dma_clr_irq = R_DMA_CH4_CLR_INTR,
+ .input_dma_first = R_DMA_CH5_FIRST,
+ .input_dma_cmd = R_DMA_CH5_CMD,
+ .input_dma_descr = R_DMA_CH5_DESCR,
+ .input_dma_clr_irq = R_DMA_CH5_CLR_INTR,
+ .data_out = R_SYNC_SERIAL3_TR_DATA,
+ .data_in = R_SYNC_SERIAL3_REC_DATA,
+ .data_avail_bit = IO_BITNR(R_IRQ_MASK1_RD, ser3_data),
+ .transmitter_ready_bit = IO_BITNR(R_IRQ_MASK1_RD, ser3_ready),
+ .input_dma_descr_bit = IO_BITNR(R_IRQ_MASK2_RD, dma5_descr),
+ .output_dma_bit = IO_BITNR(R_IRQ_MASK2_RD, dma4_eop),
+ .init_irqs = 1,
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA)
+ .use_dma = 1,
+#else
+ .use_dma = 0,
+#endif
+ }
+};
+
+/* Register shadows */
+static unsigned sync_serial_prescale_shadow;
+
+#define NUMBER_OF_PORTS 2
+
+static struct file_operations sync_serial_fops = {
+ .owner = THIS_MODULE,
+ .write = sync_serial_write,
+ .read = sync_serial_read,
+ .poll = sync_serial_poll,
+ .ioctl = sync_serial_ioctl,
+ .open = sync_serial_open,
+ .release = sync_serial_release
+};
+
+static int __init etrax_sync_serial_init(void)
+{
+ ports[0].enabled = 0;
+ ports[1].enabled = 0;
+
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0)
+ if (cris_request_io_interface(if_sync_serial_1, "sync_ser1")) {
+ printk(KERN_CRIT "ETRAX100LX sync_serial: "
+ "Could not allocate IO group for port %d\n", 0);
+ return -EBUSY;
+ }
+#endif
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1)
+ if (cris_request_io_interface(if_sync_serial_3, "sync_ser3")) {
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0)
+ cris_free_io_interface(if_sync_serial_1);
+#endif
+ printk(KERN_CRIT "ETRAX100LX sync_serial: "
+ "Could not allocate IO group for port %d\n", 1);
+ return -EBUSY;
+ }
+#endif
+
+ if (register_chrdev(SYNC_SERIAL_MAJOR, "sync serial",
+ &sync_serial_fops) < 0) {
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1)
+ cris_free_io_interface(if_sync_serial_3);
+#endif
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0)
+ cris_free_io_interface(if_sync_serial_1);
+#endif
+ printk("unable to get major for synchronous serial port\n");
+ return -EBUSY;
+ }
+
+ /* Deselect synchronous serial ports while configuring. */
+ SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async);
+ SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async);
+ *R_GEN_CONFIG_II = gen_config_ii_shadow;
+
+ /* Initialize Ports */
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0)
+ ports[0].enabled = 1;
+ SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser1, ss1extra);
+ SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync);
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)
+ ports[0].use_dma = 1;
+#else
+ ports[0].use_dma = 0;
+#endif
+ initialize_port(0);
+#endif
+
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1)
+ ports[1].enabled = 1;
+ SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser3, ss3extra);
+ SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync);
+#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA)
+ ports[1].use_dma = 1;
+#else
+ ports[1].use_dma = 0;
+#endif
+ initialize_port(1);
+#endif
+
+ *R_PORT_PB_I2C = port_pb_i2c_shadow; /* Use PB4/PB7 */
+
+ /* Set up timing */
+ *R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow = (
+ IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec) |
+ IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u1, external) |
+ IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec) |
+ IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u3, external) |
+ IO_STATE(R_SYNC_SERIAL_PRESCALE, prescaler, div4) |
+ IO_FIELD(R_SYNC_SERIAL_PRESCALE, frame_rate,
+ DEFAULT_FRAME_RATE) |
+ IO_FIELD(R_SYNC_SERIAL_PRESCALE, word_rate, DEFAULT_WORD_RATE) |
+ IO_STATE(R_SYNC_SERIAL_PRESCALE, warp_mode, normal));
+
+ /* Select synchronous ports */
+ *R_GEN_CONFIG_II = gen_config_ii_shadow;
+
+ printk(KERN_INFO "ETRAX 100LX synchronous serial port driver\n");
+ return 0;
+}
+
+static void __init initialize_port(int portnbr)
+{
+ struct sync_port *port = &ports[portnbr];
+
+ DEBUG(printk(KERN_DEBUG "Init sync serial port %d\n", portnbr));
+
+ port->started = 0;
+ port->port_nbr = portnbr;
+ port->busy = 0;
+ port->tr_running = 0;
+
+ port->out_count = 0;
+ port->outp = port->out_buffer;
+
+ port->readp = port->flip;
+ port->writep = port->flip;
+ port->in_buffer_size = IN_BUFFER_SIZE;
+ port->inbufchunk = IN_DESCR_SIZE;
+ port->next_rx_desc = &port->in_descr[0];
+ port->prev_rx_desc = &port->in_descr[NUM_IN_DESCR-1];
+ port->prev_rx_desc->ctrl = d_eol;
+
+ init_waitqueue_head(&port->out_wait_q);
+ init_waitqueue_head(&port->in_wait_q);
+
+ port->ctrl_data_shadow =
+ IO_STATE(R_SYNC_SERIAL1_CTRL, tr_baud, c115k2Hz) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, mode, master_output) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, error, ignore) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, rec_enable, disable) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, f_synctype, normal) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, f_syncsize, word) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, f_sync, on) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, clk_mode, normal) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, clk_halt, stopped) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, bitorder, msb) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, tr_enable, disable) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, buf_empty, lmt_8) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, buf_full, lmt_8) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, flow_ctrl, enabled) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, clk_polarity, neg) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, frame_polarity, normal)|
+ IO_STATE(R_SYNC_SERIAL1_CTRL, status_polarity, inverted)|
+ IO_STATE(R_SYNC_SERIAL1_CTRL, clk_driver, normal) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, frame_driver, normal) |
+ IO_STATE(R_SYNC_SERIAL1_CTRL, status_driver, normal)|
+ IO_STATE(R_SYNC_SERIAL1_CTRL, def_out0, high);
+
+ if (port->use_dma)
+ port->ctrl_data_shadow |= IO_STATE(R_SYNC_SERIAL1_CTRL,
+ dma_enable, on);
+ else
+ port->ctrl_data_shadow |= IO_STATE(R_SYNC_SERIAL1_CTRL,
+ dma_enable, off);
+
+ *port->ctrl_data = port->ctrl_data_shadow;
+}
+
+static inline int sync_data_avail(struct sync_port *port)
+{
+ int avail;
+ unsigned char *start;
+ unsigned char *end;
+
+ start = (unsigned char *)port->readp; /* cast away volatile */
+ end = (unsigned char *)port->writep; /* cast away volatile */
+ /* 0123456789 0123456789
+ * ----- - -----
+ * ^rp ^wp ^wp ^rp
+ */
+ if (end >= start)
+ avail = end - start;
+ else
+ avail = port->in_buffer_size - (start - end);
+ return avail;
+}
+
+static inline int sync_data_avail_to_end(struct sync_port *port)
+{
+ int avail;
+ unsigned char *start;
+ unsigned char *end;
+
+ start = (unsigned char *)port->readp; /* cast away volatile */
+ end = (unsigned char *)port->writep; /* cast away volatile */
+ /* 0123456789 0123456789
+ * ----- -----
+ * ^rp ^wp ^wp ^rp
+ */
+
+ if (end >= start)
+ avail = end - start;
+ else
+ avail = port->flip + port->in_buffer_size - start;
+ return avail;
+}
+
+
+static int sync_serial_open(struct inode *inode, struct file *file)
+{
+ int dev = MINOR(inode->i_rdev);
+ struct sync_port *port;
+ int mode;
+
+ DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));
+
+ if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) {
+ DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev));
+ return -ENODEV;
+ }
+ port = &ports[dev];
+ /* Allow open this device twice (assuming one reader and one writer) */
+ if (port->busy == 2) {
+ DEBUG(printk(KERN_DEBUG "Device is busy.. \n"));
+ return -EBUSY;
+ }
+ if (port->init_irqs) {
+ if (port->use_dma) {
+ if (port == &ports[0]) {
+#ifdef SYNC_SER_DMA
+ if (request_irq(24, tr_interrupt, 0,
+ "synchronous serial 1 dma tr",
+ &ports[0])) {
+ printk(KERN_CRIT "Can't alloc "
+ "sync serial port 1 IRQ");
+ return -EBUSY;
+ } else if (request_irq(25, rx_interrupt, 0,
+ "synchronous serial 1 dma rx",
+ &ports[0])) {
+ free_irq(24, &port[0]);
+ printk(KERN_CRIT "Can't alloc "
+ "sync serial port 1 IRQ");
+ return -EBUSY;
+ } else if (cris_request_dma(8,
+ "synchronous serial 1 dma tr",
+ DMA_VERBOSE_ON_ERROR,
+ dma_ser1)) {
+ free_irq(24, &port[0]);
+ free_irq(25, &port[0]);
+ printk(KERN_CRIT "Can't alloc "
+ "sync serial port 1 "
+ "TX DMA channel");
+ return -EBUSY;
+ } else if (cris_request_dma(9,
+ "synchronous serial 1 dma rec",
+ DMA_VERBOSE_ON_ERROR,
+ dma_ser1)) {
+ cris_free_dma(8, NULL);
+ free_irq(24, &port[0]);
+ free_irq(25, &port[0]);
+ printk(KERN_CRIT "Can't alloc "
+ "sync serial port 1 "
+ "RX DMA channel");
+ return -EBUSY;
+ }
+#endif
+ RESET_DMA(8); WAIT_DMA(8);
+ RESET_DMA(9); WAIT_DMA(9);
+ *R_DMA_CH8_CLR_INTR =
+ IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop,
+ do) |
+ IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr,
+ do);
+ *R_DMA_CH9_CLR_INTR =
+ IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop,
+ do) |
+ IO_STATE(R_DMA_CH9_CLR_INTR, clr_descr,
+ do);
+ *R_IRQ_MASK2_SET =
+ IO_STATE(R_IRQ_MASK2_SET, dma8_eop,
+ set) |
+ IO_STATE(R_IRQ_MASK2_SET, dma9_descr,
+ set);
+ } else if (port == &ports[1]) {
+#ifdef SYNC_SER_DMA
+ if (request_irq(20, tr_interrupt, 0,
+ "synchronous serial 3 dma tr",
+ &ports[1])) {
+ printk(KERN_CRIT "Can't alloc "
+ "sync serial port 3 IRQ");
+ return -EBUSY;
+ } else if (request_irq(21, rx_interrupt, 0,
+ "synchronous serial 3 dma rx",
+ &ports[1])) {
+ free_irq(20, &ports[1]);
+ printk(KERN_CRIT "Can't alloc "
+ "sync serial port 3 IRQ");
+ return -EBUSY;
+ } else if (cris_request_dma(4,
+ "synchronous serial 3 dma tr",
+ DMA_VERBOSE_ON_ERROR,
+ dma_ser3)) {
+ free_irq(21, &ports[1]);
+ free_irq(20, &ports[1]);
+ printk(KERN_CRIT "Can't alloc "
+ "sync serial port 3 "
+ "TX DMA channel");
+ return -EBUSY;
+ } else if (cris_request_dma(5,
+ "synchronous serial 3 dma rec",
+ DMA_VERBOSE_ON_ERROR,
+ dma_ser3)) {
+ cris_free_dma(4, NULL);
+ free_irq(21, &ports[1]);
+ free_irq(20, &ports[1]);
+ printk(KERN_CRIT "Can't alloc "
+ "sync serial port 3 "
+ "RX DMA channel");
+ return -EBUSY;
+ }
+#endif
+ RESET_DMA(4); WAIT_DMA(4);
+ RESET_DMA(5); WAIT_DMA(5);
+ *R_DMA_CH4_CLR_INTR =
+ IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop,
+ do) |
+ IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr,
+ do);
+ *R_DMA_CH5_CLR_INTR =
+ IO_STATE(R_DMA_CH5_CLR_INTR, clr_eop,
+ do) |
+ IO_STATE(R_DMA_CH5_CLR_INTR, clr_descr,
+ do);
+ *R_IRQ_MASK2_SET =
+ IO_STATE(R_IRQ_MASK2_SET, dma4_eop,
+ set) |
+ IO_STATE(R_IRQ_MASK2_SET, dma5_descr,
+ set);
+ }
+ start_dma_in(port);
+ port->init_irqs = 0;
+ } else { /* !port->use_dma */
+#ifdef SYNC_SER_MANUAL
+ if (port == &ports[0]) {
+ if (request_irq(8,
+ manual_interrupt,
+ IRQF_SHARED | IRQF_DISABLED,
+ "synchronous serial manual irq",
+ &ports[0])) {
+ printk(KERN_CRIT "Can't alloc "
+ "sync serial manual irq");
+ return -EBUSY;
+ }
+ } else if (port == &ports[1]) {
+ if (request_irq(8,
+ manual_interrupt,
+ IRQF_SHARED | IRQF_DISABLED,
+ "synchronous serial manual irq",
+ &ports[1])) {
+ printk(KERN_CRIT "Can't alloc "
+ "sync serial manual irq");
+ return -EBUSY;
+ }
+ }
+ port->init_irqs = 0;
+#else
+ panic("sync_serial: Manual mode not supported.\n");
+#endif /* SYNC_SER_MANUAL */
+ }
+ } /* port->init_irqs */
+
+ port->busy++;
+ /* Start port if we use it as input */
+ mode = IO_EXTRACT(R_SYNC_SERIAL1_CTRL, mode, port->ctrl_data_shadow);
+ if (mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, master_input) ||
+ mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, slave_input) ||
+ mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, master_bidir) ||
+ mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, slave_bidir)) {
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt,
+ running);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable,
+ enable);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable,
+ enable);
+ port->started = 1;
+ *port->ctrl_data = port->ctrl_data_shadow;
+ if (!port->use_dma)
+ *R_IRQ_MASK1_SET = 1 << port->data_avail_bit;
+ DEBUG(printk(KERN_DEBUG "sser%d rec started\n", dev));
+ }
+ return 0;
+}
+
+static int sync_serial_release(struct inode *inode, struct file *file)
+{
+ int dev = MINOR(inode->i_rdev);
+ struct sync_port *port;
+
+ if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) {
+ DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev));
+ return -ENODEV;
+ }
+ port = &ports[dev];
+ if (port->busy)
+ port->busy--;
+ if (!port->busy)
+ *R_IRQ_MASK1_CLR = ((1 << port->data_avail_bit) |
+ (1 << port->transmitter_ready_bit));
+
+ return 0;
+}
+
+
+
+static unsigned int sync_serial_poll(struct file *file, poll_table *wait)
+{
+ int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+ unsigned int mask = 0;
+ struct sync_port *port;
+ DEBUGPOLL(static unsigned int prev_mask = 0);
+
+ port = &ports[dev];
+ poll_wait(file, &port->out_wait_q, wait);
+ poll_wait(file, &port->in_wait_q, wait);
+ /* Some room to write */
+ if (port->out_count < OUT_BUFFER_SIZE)
+ mask |= POLLOUT | POLLWRNORM;
+ /* At least an inbufchunk of data */
+ if (sync_data_avail(port) >= port->inbufchunk)
+ mask |= POLLIN | POLLRDNORM;
+
+ DEBUGPOLL(if (mask != prev_mask)
+ printk(KERN_DEBUG "sync_serial_poll: mask 0x%08X %s %s\n",
+ mask,
+ mask & POLLOUT ? "POLLOUT" : "",
+ mask & POLLIN ? "POLLIN" : "");
+ prev_mask = mask;
+ );
+ return mask;
+}
+
+static int sync_serial_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int return_val = 0;
+ unsigned long flags;
+
+ int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+ struct sync_port *port;
+
+ if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) {
+ DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev));
+ return -1;
+ }
+ port = &ports[dev];
+
+ local_irq_save(flags);
+ /* Disable port while changing config */
+ if (dev) {
+ if (port->use_dma) {
+ RESET_DMA(4); WAIT_DMA(4);
+ port->tr_running = 0;
+ port->out_count = 0;
+ port->outp = port->out_buffer;
+ *R_DMA_CH4_CLR_INTR =
+ IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, do) |
+ IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do);
+ }
+ SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async);
+ } else {
+ if (port->use_dma) {
+ RESET_DMA(8); WAIT_DMA(8);
+ port->tr_running = 0;
+ port->out_count = 0;
+ port->outp = port->out_buffer;
+ *R_DMA_CH8_CLR_INTR =
+ IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, do) |
+ IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, do);
+ }
+ SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async);
+ }
+ *R_GEN_CONFIG_II = gen_config_ii_shadow;
+ local_irq_restore(flags);
+
+ switch (cmd) {
+ case SSP_SPEED:
+ if (GET_SPEED(arg) == CODEC) {
+ if (dev)
+ SETS(sync_serial_prescale_shadow,
+ R_SYNC_SERIAL_PRESCALE, clk_sel_u3,
+ codec);
+ else
+ SETS(sync_serial_prescale_shadow,
+ R_SYNC_SERIAL_PRESCALE, clk_sel_u1,
+ codec);
+
+ SETF(sync_serial_prescale_shadow,
+ R_SYNC_SERIAL_PRESCALE, prescaler,
+ GET_FREQ(arg));
+ SETF(sync_serial_prescale_shadow,
+ R_SYNC_SERIAL_PRESCALE, frame_rate,
+ GET_FRAME_RATE(arg));
+ SETF(sync_serial_prescale_shadow,
+ R_SYNC_SERIAL_PRESCALE, word_rate,
+ GET_WORD_RATE(arg));
+ } else {
+ SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ tr_baud, GET_SPEED(arg));
+ if (dev)
+ SETS(sync_serial_prescale_shadow,
+ R_SYNC_SERIAL_PRESCALE, clk_sel_u3,
+ baudrate);
+ else
+ SETS(sync_serial_prescale_shadow,
+ R_SYNC_SERIAL_PRESCALE, clk_sel_u1,
+ baudrate);
+ }
+ break;
+ case SSP_MODE:
+ if (arg > 5)
+ return -EINVAL;
+ if (arg == MASTER_OUTPUT || arg == SLAVE_OUTPUT)
+ *R_IRQ_MASK1_CLR = 1 << port->data_avail_bit;
+ else if (!port->use_dma)
+ *R_IRQ_MASK1_SET = 1 << port->data_avail_bit;
+ SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, arg);
+ break;
+ case SSP_FRAME_SYNC:
+ if (arg & NORMAL_SYNC)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ f_synctype, normal);
+ else if (arg & EARLY_SYNC)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ f_synctype, early);
+
+ if (arg & BIT_SYNC)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ f_syncsize, bit);
+ else if (arg & WORD_SYNC)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ f_syncsize, word);
+ else if (arg & EXTENDED_SYNC)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ f_syncsize, extended);
+
+ if (arg & SYNC_ON)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ f_sync, on);
+ else if (arg & SYNC_OFF)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ f_sync, off);
+
+ if (arg & WORD_SIZE_8)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ wordsize, size8bit);
+ else if (arg & WORD_SIZE_12)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ wordsize, size12bit);
+ else if (arg & WORD_SIZE_16)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ wordsize, size16bit);
+ else if (arg & WORD_SIZE_24)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ wordsize, size24bit);
+ else if (arg & WORD_SIZE_32)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ wordsize, size32bit);
+
+ if (arg & BIT_ORDER_MSB)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ bitorder, msb);
+ else if (arg & BIT_ORDER_LSB)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ bitorder, lsb);
+
+ if (arg & FLOW_CONTROL_ENABLE)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ flow_ctrl, enabled);
+ else if (arg & FLOW_CONTROL_DISABLE)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ flow_ctrl, disabled);
+
+ if (arg & CLOCK_NOT_GATED)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ clk_mode, normal);
+ else if (arg & CLOCK_GATED)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ clk_mode, gated);
+
+ break;
+ case SSP_IPOLARITY:
+ /* NOTE!! negedge is considered NORMAL */
+ if (arg & CLOCK_NORMAL)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ clk_polarity, neg);
+ else if (arg & CLOCK_INVERT)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ clk_polarity, pos);
+
+ if (arg & FRAME_NORMAL)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ frame_polarity, normal);
+ else if (arg & FRAME_INVERT)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ frame_polarity, inverted);
+
+ if (arg & STATUS_NORMAL)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ status_polarity, normal);
+ else if (arg & STATUS_INVERT)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ status_polarity, inverted);
+ break;
+ case SSP_OPOLARITY:
+ if (arg & CLOCK_NORMAL)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ clk_driver, normal);
+ else if (arg & CLOCK_INVERT)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ clk_driver, inverted);
+
+ if (arg & FRAME_NORMAL)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ frame_driver, normal);
+ else if (arg & FRAME_INVERT)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ frame_driver, inverted);
+
+ if (arg & STATUS_NORMAL)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ status_driver, normal);
+ else if (arg & STATUS_INVERT)
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ status_driver, inverted);
+ break;
+ case SSP_SPI:
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl,
+ disabled);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder,
+ msb);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize,
+ size8bit);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize,
+ word);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype,
+ normal);
+ if (arg & SPI_SLAVE) {
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ frame_polarity, inverted);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ clk_polarity, neg);
+ SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ mode, SLAVE_INPUT);
+ } else {
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ frame_driver, inverted);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ clk_driver, inverted);
+ SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL,
+ mode, MASTER_OUTPUT);
+ }
+ break;
+ case SSP_INBUFCHUNK:
+#if 0
+ if (arg > port->in_buffer_size/NUM_IN_DESCR)
+ return -EINVAL;
+ port->inbufchunk = arg;
+ /* Make sure in_buffer_size is a multiple of inbufchunk */
+ port->in_buffer_size =
+ (port->in_buffer_size/port->inbufchunk) *
+ port->inbufchunk;
+ DEBUG(printk(KERN_DEBUG "inbufchunk %i in_buffer_size: %i\n",
+ port->inbufchunk, port->in_buffer_size));
+ if (port->use_dma) {
+ if (port->port_nbr == 0) {
+ RESET_DMA(9);
+ WAIT_DMA(9);
+ } else {
+ RESET_DMA(5);
+ WAIT_DMA(5);
+ }
+ start_dma_in(port);
+ }
+#endif
+ break;
+ default:
+ return_val = -1;
+ }
+ /* Make sure we write the config without interruption */
+ local_irq_save(flags);
+ /* Set config and enable port */
+ *port->ctrl_data = port->ctrl_data_shadow;
+ nop(); nop(); nop(); nop();
+ *R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow;
+ nop(); nop(); nop(); nop();
+ if (dev)
+ SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync);
+ else
+ SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync);
+
+ *R_GEN_CONFIG_II = gen_config_ii_shadow;
+ /* Reset DMA. At readout from serial port the data could be shifted
+ * one byte if not resetting DMA.
+ */
+ if (port->use_dma) {
+ if (port->port_nbr == 0) {
+ RESET_DMA(9);
+ WAIT_DMA(9);
+ } else {
+ RESET_DMA(5);
+ WAIT_DMA(5);
+ }
+ start_dma_in(port);
+ }
+ local_irq_restore(flags);
+ return return_val;
+}
+
+
+static ssize_t sync_serial_write(struct file *file, const char *buf,
+ size_t count, loff_t *ppos)
+{
+ int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+ DECLARE_WAITQUEUE(wait, current);
+ struct sync_port *port;
+ unsigned long flags;
+ unsigned long c, c1;
+ unsigned long free_outp;
+ unsigned long outp;
+ unsigned long out_buffer;
+
+ if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) {
+ DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev));
+ return -ENODEV;
+ }
+ port = &ports[dev];
+
+ DEBUGWRITE(printk(KERN_DEBUG "W d%d c %lu (%d/%d)\n",
+ port->port_nbr, count, port->out_count, OUT_BUFFER_SIZE));
+ /* Space to end of buffer */
+ /*
+ * out_buffer <c1>012345<- c ->OUT_BUFFER_SIZE
+ * outp^ +out_count
+ * ^free_outp
+ * out_buffer 45<- c ->0123OUT_BUFFER_SIZE
+ * +out_count outp^
+ * free_outp
+ *
+ */
+
+ /* Read variables that may be updated by interrupts */
+ local_irq_save(flags);
+ if (count > OUT_BUFFER_SIZE - port->out_count)
+ count = OUT_BUFFER_SIZE - port->out_count;
+
+ outp = (unsigned long)port->outp;
+ free_outp = outp + port->out_count;
+ local_irq_restore(flags);
+ out_buffer = (unsigned long)port->out_buffer;
+
+ /* Find out where and how much to write */
+ if (free_outp >= out_buffer + OUT_BUFFER_SIZE)
+ free_outp -= OUT_BUFFER_SIZE;
+ if (free_outp >= outp)
+ c = out_buffer + OUT_BUFFER_SIZE - free_outp;
+ else
+ c = outp - free_outp;
+ if (c > count)
+ c = count;
+
+ DEBUGWRITE(printk(KERN_DEBUG "w op %08lX fop %08lX c %lu\n",
+ outp, free_outp, c));
+ if (copy_from_user((void *)free_outp, buf, c))
+ return -EFAULT;
+
+ if (c != count) {
+ buf += c;
+ c1 = count - c;
+ DEBUGWRITE(printk(KERN_DEBUG "w2 fi %lu c %lu c1 %lu\n",
+ free_outp-out_buffer, c, c1));
+ if (copy_from_user((void *)out_buffer, buf, c1))
+ return -EFAULT;
+ }
+ local_irq_save(flags);
+ port->out_count += count;
+ local_irq_restore(flags);
+
+ /* Make sure transmitter/receiver is running */
+ if (!port->started) {
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt,
+ running);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable,
+ enable);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable,
+ enable);
+ port->started = 1;
+ }
+
+ *port->ctrl_data = port->ctrl_data_shadow;
+
+ if (file->f_flags & O_NONBLOCK) {
+ local_irq_save(flags);
+ if (!port->tr_running) {
+ if (!port->use_dma) {
+ /* Start sender by writing data */
+ send_word(port);
+ /* and enable transmitter ready IRQ */
+ *R_IRQ_MASK1_SET = 1 <<
+ port->transmitter_ready_bit;
+ } else
+ start_dma(port,
+ (unsigned char *volatile)port->outp, c);
+ }
+ local_irq_restore(flags);
+ DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu NB\n",
+ port->port_nbr, count));
+ return count;
+ }
+
+ /* Sleep until all sent */
+ add_wait_queue(&port->out_wait_q, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ local_irq_save(flags);
+ if (!port->tr_running) {
+ if (!port->use_dma) {
+ /* Start sender by writing data */
+ send_word(port);
+ /* and enable transmitter ready IRQ */
+ *R_IRQ_MASK1_SET = 1 << port->transmitter_ready_bit;
+ } else
+ start_dma(port, port->outp, c);
+ }
+ local_irq_restore(flags);
+ schedule();
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&port->out_wait_q, &wait);
+ if (signal_pending(current))
+ return -EINTR;
+
+ DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu\n", port->port_nbr, count));
+ return count;
+}
+
+static ssize_t sync_serial_read(struct file *file, char *buf,
+ size_t count, loff_t *ppos)
+{
+ int dev = MINOR(file->f_dentry->d_inode->i_rdev);
+ int avail;
+ struct sync_port *port;
+ unsigned char *start;
+ unsigned char *end;
+ unsigned long flags;
+
+ if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) {
+ DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev));
+ return -ENODEV;
+ }
+ port = &ports[dev];
+
+ DEBUGREAD(printk(KERN_DEBUG "R%d c %d ri %lu wi %lu /%lu\n",
+ dev, count, port->readp - port->flip,
+ port->writep - port->flip, port->in_buffer_size));
+
+ if (!port->started) {
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt,
+ running);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable,
+ enable);
+ SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable,
+ enable);
+ port->started = 1;
+ }
+ *port->ctrl_data = port->ctrl_data_shadow;
+
+ /* Calculate number of available bytes */
+ /* Save pointers to avoid that they are modified by interrupt */
+ local_irq_save(flags);
+ start = (unsigned char *)port->readp; /* cast away volatile */
+ end = (unsigned char *)port->writep; /* cast away volatile */
+ local_irq_restore(flags);
+ while (start == end && !port->full) {
+ /* No data */
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ interruptible_sleep_on(&port->in_wait_q);
+ if (signal_pending(current))
+ return -EINTR;
+
+ local_irq_save(flags);
+ start = (unsigned char *)port->readp; /* cast away volatile */
+ end = (unsigned char *)port->writep; /* cast away volatile */
+ local_irq_restore(flags);
+ }
+
+ /* Lazy read, never return wrapped data. */
+ if (port->full)
+ avail = port->in_buffer_size;
+ else if (end > start)
+ avail = end - start;
+ else
+ avail = port->flip + port->in_buffer_size - start;
+
+ count = count > avail ? avail : count;
+ if (copy_to_user(buf, start, count))
+ return -EFAULT;
+ /* Disable interrupts while updating readp */
+ local_irq_save(flags);
+ port->readp += count;
+ if (port->readp >= port->flip + port->in_buffer_size) /* Wrap? */
+ port->readp = port->flip;
+ port->full = 0;
+ local_irq_restore(flags);
+ DEBUGREAD(printk(KERN_DEBUG "r %d\n", count));
+ return count;
+}
+
+static void send_word(struct sync_port *port)
+{
+ switch (IO_EXTRACT(R_SYNC_SERIAL1_CTRL, wordsize,
+ port->ctrl_data_shadow)) {
+ case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):
+ port->out_count--;
+ *port->data_out = *port->outp++;
+ if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+ port->outp = port->out_buffer;
+ break;
+ case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):
+ {
+ int data = (*port->outp++) << 8;
+ data |= *port->outp++;
+ port->out_count -= 2;
+ *port->data_out = data;
+ if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+ port->outp = port->out_buffer;
+ break;
+ }
+ case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):
+ port->out_count -= 2;
+ *port->data_out = *(unsigned short *)port->outp;
+ port->outp += 2;
+ if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+ port->outp = port->out_buffer;
+ break;
+ case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):
+ port->out_count -= 3;
+ *port->data_out = *(unsigned int *)port->outp;
+ port->outp += 3;
+ if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+ port->outp = port->out_buffer;
+ break;
+ case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):
+ port->out_count -= 4;
+ *port->data_out = *(unsigned int *)port->outp;
+ port->outp += 4;
+ if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+ port->outp = port->out_buffer;
+ break;
+ }
+}
+
+
+static void start_dma(struct sync_port *port, const char *data, int count)
+{
+ port->tr_running = 1;
+ port->out_descr.hw_len = 0;
+ port->out_descr.next = 0;
+ port->out_descr.ctrl = d_eol | d_eop; /* No d_wait to avoid glitches */
+ port->out_descr.sw_len = count;
+ port->out_descr.buf = virt_to_phys(data);
+ port->out_descr.status = 0;
+
+ *port->output_dma_first = virt_to_phys(&port->out_descr);
+ *port->output_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start);
+ DEBUGTXINT(printk(KERN_DEBUG "dma %08lX c %d\n",
+ (unsigned long)data, count));
+}
+
+static void start_dma_in(struct sync_port *port)
+{
+ int i;
+ unsigned long buf;
+ port->writep = port->flip;
+
+ if (port->writep > port->flip + port->in_buffer_size) {
+ panic("Offset too large in sync serial driver\n");
+ return;
+ }
+ buf = virt_to_phys(port->in_buffer);
+ for (i = 0; i < NUM_IN_DESCR; i++) {
+ port->in_descr[i].sw_len = port->inbufchunk;
+ port->in_descr[i].ctrl = d_int;
+ port->in_descr[i].next = virt_to_phys(&port->in_descr[i+1]);
+ port->in_descr[i].buf = buf;
+ port->in_descr[i].hw_len = 0;
+ port->in_descr[i].status = 0;
+ port->in_descr[i].fifo_len = 0;
+ buf += port->inbufchunk;
+ prepare_rx_descriptor(&port->in_descr[i]);
+ }
+ /* Link the last descriptor to the first */
+ port->in_descr[i-1].next = virt_to_phys(&port->in_descr[0]);
+ port->in_descr[i-1].ctrl |= d_eol;
+ port->next_rx_desc = &port->in_descr[0];
+ port->prev_rx_desc = &port->in_descr[NUM_IN_DESCR - 1];
+ *port->input_dma_first = virt_to_phys(port->next_rx_desc);
+ *port->input_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start);
+}
+
+#ifdef SYNC_SER_DMA
+static irqreturn_t tr_interrupt(int irq, void *dev_id)
+{
+ unsigned long ireg = *R_IRQ_MASK2_RD;
+ struct etrax_dma_descr *descr;
+ unsigned int sentl;
+ int handled = 0;
+ int i;
+
+ for (i = 0; i < NUMBER_OF_PORTS; i++) {
+ struct sync_port *port = &ports[i];
+ if (!port->enabled || !port->use_dma)
+ continue;
+
+ /* IRQ active for the port? */
+ if (!(ireg & (1 << port->output_dma_bit)))
+ continue;
+
+ handled = 1;
+
+ /* Clear IRQ */
+ *port->output_dma_clr_irq =
+ IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do) |
+ IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do);
+
+ descr = &port->out_descr;
+ if (!(descr->status & d_stop))
+ sentl = descr->sw_len;
+ else
+ /* Otherwise find amount of data sent here */
+ sentl = descr->hw_len;
+
+ port->out_count -= sentl;
+ port->outp += sentl;
+ if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
+ port->outp = port->out_buffer;
+ if (port->out_count) {
+ int c = port->out_buffer + OUT_BUFFER_SIZE - port->outp;
+ if (c > port->out_count)
+ c = port->out_count;
+ DEBUGTXINT(printk(KERN_DEBUG
+ "tx_int DMAWRITE %i %i\n", sentl, c));
+ start_dma(port, port->outp, c);
+ } else {
+ DEBUGTXINT(printk(KERN_DEBUG
+ "tx_int DMA stop %i\n", sentl));
+ port->tr_running = 0;
+ }
+ /* wake up the waiting process */
+ wake_up_interruptible(&port->out_wait_q);
+ }
+ return IRQ_RETVAL(handled);
+} /* tr_interrupt */
+
+static irqreturn_t rx_interrupt(int irq, void *dev_id)
+{
+ unsigned long ireg = *R_IRQ_MASK2_RD;
+ int i;
+ int handled = 0;
+
+ for (i = 0; i < NUMBER_OF_PORTS; i++) {
+ struct sync_port *port = &ports[i];
+
+ if (!port->enabled || !port->use_dma)
+ continue;
+
+ if (!(ireg & (1 << port->input_dma_descr_bit)))
+ continue;
+
+ /* Descriptor interrupt */
+ handled = 1;
+ while (*port->input_dma_descr !=
+ virt_to_phys(port->next_rx_desc)) {
+ if (port->writep + port->inbufchunk > port->flip +
+ port->in_buffer_size) {
+ int first_size = port->flip +
+ port->in_buffer_size - port->writep;
+ memcpy(port->writep,
+ phys_to_virt(port->next_rx_desc->buf),
+ first_size);
+ memcpy(port->flip,
+ phys_to_virt(port->next_rx_desc->buf +
+ first_size),
+ port->inbufchunk - first_size);
+ port->writep = port->flip +
+ port->inbufchunk - first_size;
+ } else {
+ memcpy(port->writep,
+ phys_to_virt(port->next_rx_desc->buf),
+ port->inbufchunk);
+ port->writep += port->inbufchunk;
+ if (port->writep >= port->flip
+ + port->in_buffer_size)
+ port->writep = port->flip;
+ }
+ if (port->writep == port->readp)
+ port->full = 1;
+ prepare_rx_descriptor(port->next_rx_desc);
+ port->next_rx_desc->ctrl |= d_eol;
+ port->prev_rx_desc->ctrl &= ~d_eol;
+ port->prev_rx_desc = phys_to_virt((unsigned)
+ port->next_rx_desc);
+ port->next_rx_desc = phys_to_virt((unsigned)
+ port->next_rx_desc->next);
+ /* Wake up the waiting process */
+ wake_up_interruptible(&port->in_wait_q);
+ *port->input_dma_cmd = IO_STATE(R_DMA_CH1_CMD,
+ cmd, restart);
+ /* DMA has reached end of descriptor */
+ *port->input_dma_clr_irq = IO_STATE(R_DMA_CH0_CLR_INTR,
+ clr_descr, do);
+ }
+ }
+ return IRQ_RETVAL(handled);
+} /* rx_interrupt */
+#endif /* SYNC_SER_DMA */
+
+#ifdef SYNC_SER_MANUAL
+static irqreturn_t manual_interrupt(int irq, void *dev_id)
+{
+ int i;
+ int handled = 0;
+
+ for (i = 0; i < NUMBER_OF_PORTS; i++) {
+ struct sync_port *port = &ports[i];
+
+ if (!port->enabled || port->use_dma)
+ continue;
+
+ /* Data received? */
+ if (*R_IRQ_MASK1_RD & (1 << port->data_avail_bit)) {
+ handled = 1;
+ /* Read data */
+ switch (port->ctrl_data_shadow &
+ IO_MASK(R_SYNC_SERIAL1_CTRL, wordsize)) {
+ case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit):
+ *port->writep++ =
+ *(volatile char *)port->data_in;
+ break;
+ case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit):
+ {
+ int data = *(unsigned short *)port->data_in;
+ *port->writep = (data & 0x0ff0) >> 4;
+ *(port->writep + 1) = data & 0x0f;
+ port->writep += 2;
+ break;
+ }
+ case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit):
+ *(unsigned short *)port->writep =
+ *(volatile unsigned short *)port->data_in;
+ port->writep += 2;
+ break;
+ case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit):
+ *(unsigned int *)port->writep = *port->data_in;
+ port->writep += 3;
+ break;
+ case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit):
+ *(unsigned int *)port->writep = *port->data_in;
+ port->writep += 4;
+ break;
+ }
+
+ /* Wrap? */
+ if (port->writep >= port->flip + port->in_buffer_size)
+ port->writep = port->flip;
+ if (port->writep == port->readp) {
+ /* Receive buffer overrun, discard oldest */
+ port->readp++;
+ /* Wrap? */
+ if (port->readp >= port->flip +
+ port->in_buffer_size)
+ port->readp = port->flip;
+ }
+ if (sync_data_avail(port) >= port->inbufchunk) {
+ /* Wake up application */
+ wake_up_interruptible(&port->in_wait_q);
+ }
+ }
+
+ /* Transmitter ready? */
+ if (*R_IRQ_MASK1_RD & (1 << port->transmitter_ready_bit)) {
+ if (port->out_count > 0) {
+ /* More data to send */
+ send_word(port);
+ } else {
+ /* Transmission finished */
+ /* Turn off IRQ */
+ *R_IRQ_MASK1_CLR = 1 <<
+ port->transmitter_ready_bit;
+ /* Wake up application */
+ wake_up_interruptible(&port->out_wait_q);
+ }
+ }
+ }
+ return IRQ_RETVAL(handled);
+}
+#endif
+
+module_init(etrax_sync_serial_init);
diff --git a/arch/cris/arch-v10/kernel/debugport.c b/arch/cris/arch-v10/kernel/debugport.c
index 93679a48c79..04d5eee2c90 100644
--- a/arch/cris/arch-v10/kernel/debugport.c
+++ b/arch/cris/arch-v10/kernel/debugport.c
@@ -1,6 +1,6 @@
/* Serialport functions for debugging
*
- * Copyright (c) 2000 Axis Communications AB
+ * Copyright (c) 2000-2007 Axis Communications AB
*
* Authors: Bjorn Wesen
*
@@ -11,96 +11,6 @@
* enableDebugIRQ()
* init_etrax_debug()
*
- * $Log: debugport.c,v $
- * Revision 1.27 2005/06/10 10:34:14 starvik
- * Real console support
- *
- * Revision 1.26 2005/06/07 07:06:07 starvik
- * Added LF->CR translation to make ETRAX customers happy.
- *
- * Revision 1.25 2005/03/08 08:56:47 mikaelam
- * Do only set index as port->index if port is defined, otherwise use the index from the command line
- *
- * Revision 1.24 2005/01/19 10:26:33 mikaelam
- * Return the cris serial driver in console device driver callback function
- *
- * Revision 1.23 2005/01/14 10:12:17 starvik
- * KGDB on separate port.
- * Console fixes from 2.4.
- *
- * Revision 1.22 2005/01/11 16:06:13 starvik
- * typo
- *
- * Revision 1.21 2005/01/11 13:49:14 starvik
- * Added raw_printk to be used where we don't trust the console.
- *
- * Revision 1.20 2004/12/27 11:18:32 starvik
- * Merge of Linux 2.6.10 (not functional yet).
- *
- * Revision 1.19 2004/10/21 07:26:16 starvik
- * Made it possible to specify console settings on kernel command line.
- *
- * Revision 1.18 2004/10/19 13:07:37 starvik
- * Merge of Linux 2.6.9
- *
- * Revision 1.17 2004/09/29 10:33:46 starvik
- * Resolved a dealock when printing debug from kernel.
- *
- * Revision 1.16 2004/08/24 06:12:19 starvik
- * Whitespace cleanup
- *
- * Revision 1.15 2004/08/16 12:37:19 starvik
- * Merge of Linux 2.6.8
- *
- * Revision 1.14 2004/05/17 13:11:29 starvik
- * Disable DMA until real serial driver is up
- *
- * Revision 1.13 2004/05/14 07:58:01 starvik
- * Merge of changes from 2.4
- *
- * Revision 1.12 2003/09/11 07:29:49 starvik
- * Merge of Linux 2.6.0-test5
- *
- * Revision 1.11 2003/07/07 09:53:36 starvik
- * Revert all the 2.5.74 merge changes to make the console work again
- *
- * Revision 1.9 2003/02/17 17:07:23 starvik
- * Solved the problem with corrupted debug output (from Linux 2.4)
- * * Wait until DMA, FIFO and pipe is empty before and after transmissions
- * * Buffer data until a FIFO flush can be triggered.
- *
- * Revision 1.8 2003/01/22 06:48:36 starvik
- * Fixed warnings issued by GCC 3.2.1
- *
- * Revision 1.7 2002/12/12 08:26:32 starvik
- * Don't use C-comments inside CVS comments
- *
- * Revision 1.6 2002/12/11 15:42:02 starvik
- * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/
- *
- * Revision 1.5 2002/11/20 06:58:03 starvik
- * Compiles with kgdb
- *
- * Revision 1.4 2002/11/19 14:35:24 starvik
- * Changes from linux 2.4
- * Changed struct initializer syntax to the currently preferred notation
- *
- * Revision 1.3 2002/11/06 09:47:03 starvik
- * Modified for new interrupt macros
- *
- * Revision 1.2 2002/01/21 15:21:50 bjornw
- * Update for kdev_t changes
- *
- * Revision 1.6 2001/04/17 13:58:39 orjanf
- * * Renamed CONFIG_KGDB to CONFIG_ETRAX_KGDB.
- *
- * Revision 1.5 2001/03/26 14:22:05 bjornw
- * Namechange of some config options
- *
- * Revision 1.4 2000/10/06 12:37:26 bjornw
- * Use physical addresses when talking to DMA
- *
- *
*/
#include <linux/console.h>
@@ -112,6 +22,8 @@
#include <asm/arch/svinto.h>
#include <asm/io.h> /* Get SIMCOUT. */
+extern void reset_watchdog(void);
+
struct dbg_port
{
unsigned int index;
@@ -188,7 +100,9 @@ struct dbg_port ports[]=
}
};
+#ifdef CONFIG_ETRAX_SERIAL
extern struct tty_driver *serial_driver;
+#endif
struct dbg_port* port =
#if defined(CONFIG_ETRAX_DEBUG_PORT0)
@@ -368,11 +282,12 @@ console_write_direct(struct console *co, const char *buf, unsigned int len)
{
int i;
unsigned long flags;
- local_irq_save(flags);
if (!port)
return;
+ local_irq_save(flags);
+
/* Send data */
for (i = 0; i < len; i++) {
/* LF -> CRLF */
@@ -386,26 +301,16 @@ console_write_direct(struct console *co, const char *buf, unsigned int len)
;
*port->write = buf[i];
}
- local_irq_restore(flags);
-}
-int raw_printk(const char *fmt, ...)
-{
- static char buf[1024];
- int printed_len;
- static int first = 1;
- if (first) {
- /* Force reinitialization of the port to get manual mode. */
- port->started = 0;
- start_port(port);
- first = 0;
- }
- va_list args;
- va_start(args, fmt);
- printed_len = vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- console_write_direct(NULL, buf, strlen(buf));
- return printed_len;
+ /*
+ * Feed the watchdog, otherwise it will reset the chip during boot.
+ * The time to send an ordinary boot message line (10-90 chars)
+ * varies between 1-8ms at 115200. What makes up for the additional
+ * 90ms that allows the watchdog to bite?
+ */
+ reset_watchdog();
+
+ local_irq_restore(flags);
}
static void
@@ -500,6 +405,7 @@ console_setup(struct console *co, char *options)
return 0;
}
+
/* This is a dummy serial device that throws away anything written to it.
* This is used when no debug output is wanted.
*/
@@ -555,7 +461,13 @@ etrax_console_device(struct console* co, int *index)
{
if (port)
*index = port->index;
+ else
+ *index = 0;
+#ifdef CONFIG_ETRAX_SERIAL
return port ? serial_driver : &dummy_driver;
+#else
+ return &dummy_driver;
+#endif
}
static struct console sercons = {
diff --git a/arch/cris/arch-v10/kernel/dma.c b/arch/cris/arch-v10/kernel/dma.c
index e9a0311b141..eb1fa0d2b49 100644
--- a/arch/cris/arch-v10/kernel/dma.c
+++ b/arch/cris/arch-v10/kernel/dma.c
@@ -1,6 +1,5 @@
/* Wrapper for DMA channel allocator that updates DMA client muxing.
- * Copyright 2004, Axis Communications AB
- * $Id: dma.c,v 1.1 2004/12/13 12:21:51 starvik Exp $
+ * Copyright 2004-2007, Axis Communications AB
*/
#include <linux/kernel.h>
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index ec62c951fa3..3a65f322ae0 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -1,252 +1,9 @@
-/* $Id: entry.S,v 1.28 2005/06/20 05:06:30 starvik Exp $
- *
+/*
* linux/arch/cris/entry.S
*
* Copyright (C) 2000, 2001, 2002 Axis Communications AB
*
* Authors: Bjorn Wesen (bjornw@axis.com)
- *
- * $Log: entry.S,v $
- * Revision 1.28 2005/06/20 05:06:30 starvik
- * Remove unnecessary diff to kernel.org tree
- *
- * Revision 1.27 2005/03/04 08:16:16 starvik
- * Merge of Linux 2.6.11.
- *
- * Revision 1.26 2005/01/11 13:49:47 starvik
- * Added NMI handler.
- *
- * Revision 1.25 2004/12/27 11:18:32 starvik
- * Merge of Linux 2.6.10 (not functional yet).
- *
- * Revision 1.24 2004/12/22 10:41:23 starvik
- * Updates to make v10 compile with the latest SMP aware generic code (even
- * though v10 will never have SMP).
- *
- * Revision 1.23 2004/10/19 13:07:37 starvik
- * Merge of Linux 2.6.9
- *
- * Revision 1.22 2004/06/21 10:29:55 starvik
- * Merge of Linux 2.6.7
- *
- * Revision 1.21 2004/06/09 05:30:27 starvik
- * Clean up multiple interrupt handling.
- * Prevent interrupts from interrupting each other.
- * Handle all active interrupts.
- *
- * Revision 1.20 2004/06/08 08:55:32 starvik
- * Removed unused code
- *
- * Revision 1.19 2004/06/04 11:56:15 starvik
- * Implemented page table lookup for refills in assembler for improved performance.
- *
- * Revision 1.18 2004/05/11 12:28:25 starvik
- * Merge of Linux 2.6.6
- *
- * Revision 1.17 2003/09/11 07:29:49 starvik
- * Merge of Linux 2.6.0-test5
- *
- * Revision 1.16 2003/07/04 08:27:41 starvik
- * Merge of Linux 2.5.74
- *
- * Revision 1.15 2003/04/09 07:32:55 starvik
- * resume should return task_struct, not thread_info
- *
- * Revision 1.14 2003/04/09 05:20:44 starvik
- * Merge of Linux 2.5.67
- *
- * Revision 1.13 2002/12/11 15:42:02 starvik
- * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/*.c
- *
- * Revision 1.12 2002/12/10 09:00:10 starvik
- * Merge of Linux 2.5.51
- *
- * Revision 1.11 2002/12/05 07:53:10 starvik
- * Corrected constants used with btstq
- *
- * Revision 1.10 2002/11/27 08:45:10 starvik
- * pid is in task_struct, not thread_info
- *
- * Revision 1.9 2002/11/26 09:52:05 starvik
- * Added preemptive kernel scheduling (if CONFIG_PREEMPT)
- *
- * Revision 1.8 2002/11/20 11:56:11 starvik
- * Merge of Linux 2.5.48
- *
- * Revision 1.7 2002/11/18 13:02:42 starvik
- * Added fourth parameter to do_notify_resume
- * Minor cleanup
- *
- * Revision 1.6 2002/11/11 10:37:50 starvik
- * Use new asm-offset defines
- * Modified for new location of current->work etc
- * Removed SYMBOL_NAME from syscalls
- * Added some new syscalls
- *
- * Revision 1.5 2002/11/05 06:45:11 starvik
- * Merge of Linux 2.5.45
- *
- * Revision 1.4 2002/02/05 15:41:31 bjornw
- * Rewritten to conform better to current 2.5 code (similar to arch/i386)
- *
- * Revision 1.3 2002/01/21 15:22:20 bjornw
- * NICE_DOGGY fix from 2.4 arch/cris
- *
- * Revision 1.37 2001/12/07 17:03:55 bjornw
- * Call a c-hook called watchdog_bite_hook instead of show_registers directly
- *
- * Revision 1.36 2001/11/22 13:36:36 bjornw
- * * In ret_from_intr, check regs->dccr for usermode reentrance instead of
- * DCCR explicitly (because the latter might not reflect current reality)
- * * In mmu_bus_fault, set $r9 _after_ calling the C-code instead of before
- * since $r9 is call-clobbered and is potentially needed afterwards
- *
- * Revision 1.35 2001/10/30 17:10:15 bjornw
- * Add some syscalls
- *
- * Revision 1.34 2001/10/01 14:45:03 bjornw
- * Removed underscores and added register prefixes
- *
- * Revision 1.33 2001/08/21 13:48:01 jonashg
- * Added fix by HP to avoid oops when doing a hard_reset_now.
- *
- * Revision 1.32 2001/08/14 04:32:02 hp
- * In _resume, add comment why R9 is saved; don't sound like it's call-saved.
- *
- * Revision 1.31 2001/07/25 16:07:42 bjornw
- * softirq_active/mask -> softirq_pending only
- *
- * Revision 1.30 2001/07/05 01:03:32 hp
- * - include asm/errno.h to get ENOSYS.
- * - Use ENOSYS, not local constant LENOSYS; tweak comments.
- * - Explain why .include, not #include is used.
- * - Make oops-register-dump if watchdog bits and it's not expected.
- * - Don't jsr, use jump _hard_reset_now, and skip spurious nop.
- * - Use correct section attribute for section .rodata.
- * - Adjust sys_ni_syscall fill number.
- *
- * Revision 1.29 2001/06/25 14:07:00 hp
- * Fix review comment.
- * * head.S: Use IO_STATE, IO_FIELD and IO_MASK constructs instead of
- * magic numbers. Add comment that -traditional must not be used.
- * * entry.S (SYMBOL_NAME): Change redefinition to use ## concatenation.
- * Correct and update comment.
- * * Makefile (.S.o): Don't use -traditional. Add comment why the
- * toplevel rule can't be used (now that there's a reason).
- *
- * Revision 1.28 2001/06/21 02:00:40 hp
- * * entry.S: Include asm/unistd.h.
- * (_sys_call_table): Use section .rodata, not .data.
- * (_kernel_thread): Move from...
- * * process.c: ... here.
- * * entryoffsets.c (VAL): Break out from...
- * (OF): Use VAL.
- * (LCLONE_VM): New asmified value from CLONE_VM.
- *
- * Revision 1.27 2001/05/29 11:25:27 markusl
- * In case of "spurious_interrupt", do hard_reset instead of hanging system in a loop...
- *
- * Revision 1.26 2001/05/15 15:46:03 bjornw
- * Include config.h now that we use some CONFIG_ options
- *
- * Revision 1.25 2001/05/15 05:38:47 hp
- * Tweaked code in _ret_from_sys_call
- *
- * Revision 1.24 2001/05/15 05:27:49 hp
- * Save r9 in r1 over function call rather than on stack.
- *
- * Revision 1.23 2001/05/15 05:10:00 hp
- * Generate entry.S structure offsets from C
- *
- * Revision 1.22 2001/04/17 13:58:39 orjanf
- * * Renamed CONFIG_KGDB to CONFIG_ETRAX_KGDB.
- *
- * Revision 1.21 2001/04/17 11:33:29 orjanf
- * Updated according to review:
- * * Included asm/sv_addr_ag.h to get macro for internal register.
- * * Corrected comment regarding system call argument passing.
- * * Removed comment about instruction being in a delay slot.
- * * Added comment about SYMBOL_NAME macro.
- *
- * Revision 1.20 2001/04/12 08:51:07 hp
- * - Add entry for sys_fcntl64. In fact copy last piece from i386 including ...
- * - .rept to fill table to safe state with sys_ni_syscall.
- *
- * Revision 1.19 2001/04/04 09:43:32 orjanf
- * * Moved do_sigtrap from traps.c to entry.S.
- * * LTASK_PID need not be global anymore.
- *
- * Revision 1.18 2001/03/26 09:25:02 markusl
- * Updated after review, should now handle USB interrupts correctly.
- *
- * Revision 1.17 2001/03/21 16:12:55 bjornw
- * * Always make room for the cpu status record in the frame, in order to
- * use the same framelength and layout for both mmu busfaults and normal
- * irqs. No need to check for the explicit CRIS_FRAME_FIXUP type anymore.
- * * Fixed bug with using addq for popping the stack in the epilogue - it
- * destroyed the flag register. Use instructions that don't affect the
- * flag register instead.
- * * Removed write to R_PORT_PA_DATA during spurious_interrupt
- *
- * Revision 1.16 2001/03/20 19:43:02 bjornw
- * * Get rid of esp0 setting
- * * Give a 7th argument to a systemcall - the stackframe
- *
- * Revision 1.15 2001/03/05 13:14:30 bjornw
- * Spelling fix
- *
- * Revision 1.14 2001/02/23 08:36:36 perf
- * New ABI; syscallnr=r9, arg5=mof, arg6=srp.
- * Corrected tracesys call check.
- *
- * Revision 1.13 2001/02/15 08:40:55 perf
- * H-P by way of perf;
- * - (_system_call): Don't read system call function address into r1.
- * - (RBFExit): There is no such thing as a null pop. Adjust sp by addq.
- * - (_system_call): Don't use r10 and don't save and restore it.
- * - (THREAD_ESP0): New constant.
- * - (_system_call): Inline set_esp0.
- *
- * Revision 1.12 2001/01/31 17:56:25 orjanf
- * Added definition of LTASK_PID and made it global.
- *
- * Revision 1.11 2001/01/10 21:13:29 bjornw
- * SYMBOL_NAME is defined incorrectly for the compiler options we currently use
- *
- * Revision 1.10 2000/12/18 23:47:56 bjornw
- * * Added syscall trace support (ptrace), completely untested of course
- * * Removed redundant check for NULL entries in syscall_table
- *
- * Revision 1.9 2000/11/21 16:40:51 bjornw
- * * New frame type used when an SBFS frame needs to be popped without
- * actually restarting the instruction
- * * Enable interrupts in signal_return (they did so in x86, I hope it's a good
- * idea)
- *
- * Revision 1.8 2000/11/17 16:53:35 bjornw
- * Added detection of frame-type in Rexit, so that mmu_bus_fault can
- * use ret_from_intr in the return-path to check for signals (like SEGV)
- * and other foul things that might have occurred during the fault.
- *
- * Revision 1.7 2000/10/06 15:04:28 bjornw
- * Include mof in register savings
- *
- * Revision 1.6 2000/09/12 16:02:44 bjornw
- * Linux-2.4.0-test7 derived updates
- *
- * Revision 1.5 2000/08/17 15:35:15 bjornw
- * 2.4.0-test6 changed local_irq_count and friends API
- *
- * Revision 1.4 2000/08/02 13:59:30 bjornw
- * Removed olduname and uname from the syscall list
- *
- * Revision 1.3 2000/07/31 13:32:58 bjornw
- * * Export ret_from_intr
- * * _resume updated (prev/last tjohejsan)
- * * timer_interrupt obsolete
- * * SIGSEGV detection in mmu_bus_fault temporarily disabled
- *
- *
*/
/*
@@ -1167,9 +924,11 @@ sys_call_table:
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_timerfd_create
.long sys_eventfd
.long sys_fallocate
+ .long sys_timerfd_settime /* 325 */
+ .long sys_timerfd_gettime
/*
* NOTE!! This doesn't have to be exact - we just have
diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c
index c1a3a2100ee..31ff35cff02 100644
--- a/arch/cris/arch-v10/kernel/fasttimer.c
+++ b/arch/cris/arch-v10/kernel/fasttimer.c
@@ -31,15 +31,12 @@
#define DEBUG_LOG_INCLUDED
#define FAST_TIMER_LOG
-//#define FAST_TIMER_TEST
+/* #define FAST_TIMER_TEST */
#define FAST_TIMER_SANITY_CHECKS
#ifdef FAST_TIMER_SANITY_CHECKS
-#define SANITYCHECK(x) x
static int sanity_failed;
-#else
-#define SANITYCHECK(x)
#endif
#define D1(x)
@@ -226,23 +223,19 @@ void start_one_shot_timer(struct fast_timer *t,
do_gettimeofday_fast(&t->tv_set);
tmp = fast_timer_list;
- SANITYCHECK({ /* Check so this is not in the list already... */
- while (tmp != NULL)
- {
- if (tmp == t)
- {
- printk(KERN_WARNING
- "timer name: %s data: 0x%08lX already in list!\n", name, data);
- sanity_failed++;
- goto done;
- }
- else
- {
- tmp = tmp->next;
- }
- }
- tmp = fast_timer_list;
- });
+#ifdef FAST_TIMER_SANITY_CHECKS
+ /* Check so this is not in the list already... */
+ while (tmp != NULL) {
+ if (tmp == t) {
+ printk(KERN_WARNING "timer name: %s data: "
+ "0x%08lX already in list!\n", name, data);
+ sanity_failed++;
+ goto done;
+ } else
+ tmp = tmp->next;
+ }
+ tmp = fast_timer_list;
+#endif
t->delay_us = delay_us;
t->function = function;
diff --git a/arch/cris/arch-v10/kernel/head.S b/arch/cris/arch-v10/kernel/head.S
index d946d8b8d27..96344afc4eb 100644
--- a/arch/cris/arch-v10/kernel/head.S
+++ b/arch/cris/arch-v10/kernel/head.S
@@ -1,186 +1,10 @@
-/* $Id: head.S,v 1.10 2005/06/20 05:12:54 starvik Exp $
- *
+/*
* Head of the kernel - alter with care
*
* Copyright (C) 2000, 2001 Axis Communications AB
*
* Authors: Bjorn Wesen (bjornw@axis.com)
*
- * $Log: head.S,v $
- * Revision 1.10 2005/06/20 05:12:54 starvik
- * Remove unnecessary diff to kernel.org tree
- *
- * Revision 1.9 2004/12/13 12:21:51 starvik
- * Added I/O and DMA allocators from Linux 2.4
- *
- * Revision 1.8 2004/11/22 11:41:14 starvik
- * Kernel command line may be supplied to kernel. Not used by Axis but may
- * be used by customers.
- *
- * Revision 1.7 2004/05/14 07:58:01 starvik
- * Merge of changes from 2.4
- *
- * Revision 1.6 2003/04/28 05:31:46 starvik
- * Added section attributes
- *
- * Revision 1.5 2002/12/11 15:42:02 starvik
- * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/*.c
- *
- * Revision 1.4 2002/11/07 09:00:44 starvik
- * Names changed for init sections
- * init_task_union -> init_thread_union
- *
- * Revision 1.3 2002/02/05 15:38:23 bjornw
- * Oops.. non-CRAMFS_MAGIC should jump over the copying, not into it...
- *
- * Revision 1.2 2001/12/18 13:35:19 bjornw
- * Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
- *
- * Revision 1.43 2001/11/08 15:09:43 starvik
- * Only start MII clock if Ethernet is configured
- *
- * Revision 1.42 2001/11/08 14:37:34 starvik
- * Start MII clock early to make sure that it is running at tranceiver reset
- *
- * Revision 1.41 2001/10/29 14:55:58 pkj
- * Corrected pa$r0 to par0.
- *
- * Revision 1.40 2001/10/03 14:59:57 pkj
- * Added support for resetting the Bluetooth hardware.
- *
- * Revision 1.39 2001/10/01 14:45:03 bjornw
- * Removed underscores and added register prefixes
- *
- * Revision 1.38 2001/09/21 07:14:11 jonashg
- * Made root filesystem (cramfs) use mtdblock driver when booting from flash.
- *
- * Revision 1.37 2001/09/11 13:44:29 orjanf
- * Decouple usage of serial ports for debug and kgdb.
- *
- * Revision 1.36 2001/06/29 12:39:31 pkj
- * Added support for mirroring the first flash to just below the
- * second one, to make them look consecutive to cramfs.
- *
- * Revision 1.35 2001/06/25 14:07:00 hp
- * Fix review comment.
- * * head.S: Use IO_STATE, IO_FIELD and IO_MASK constructs instead of
- * magic numbers. Add comment that -traditional must not be used.
- * * entry.S (SYMBOL_NAME): Change redefinition to use ## concatenation.
- * Correct and update comment.
- * * Makefile (.S.o): Don't use -traditional. Add comment why the
- * toplevel rule can't be used (now that there's a reason).
- *
- * Revision 1.34 2001/05/15 07:08:14 hp
- * Tweak "notice" to reflect that both r8 r9 are used
- *
- * Revision 1.33 2001/05/15 06:40:05 hp
- * Put bulk of code in .text.init, data in .data.init
- *
- * Revision 1.32 2001/05/15 06:18:56 hp
- * Execute review comment: s/bcc/bhs/g; s/bcs/blo/g
- *
- * Revision 1.31 2001/05/15 06:08:40 hp
- * Add sentence about autodetecting the bit31-MMU-bug
- *
- * Revision 1.30 2001/05/15 06:00:05 hp
- * Update comment: LOW_MAP is not forced on xsim anymore.
- *
- * Revision 1.29 2001/04/18 12:51:59 orjanf
- * * Reverted review change regarding the use of bcs/bcc.
- * * Removed non-working LED-clearing code.
- *
- * Revision 1.28 2001/04/17 13:58:39 orjanf
- * * Renamed CONFIG_KGDB to CONFIG_ETRAX_KGDB.
- *
- * Revision 1.27 2001/04/17 11:42:35 orjanf
- * Changed according to review:
- * * Added comment explaining memory map bug.
- * * Changed bcs and bcc to blo and bhs, respectively.
- * * Removed mentioning of Stallone and Olga boards.
- *
- * Revision 1.26 2001/04/06 12:31:07 jonashg
- * Check for cramfs in flash before RAM instead of RAM before flash.
- *
- * Revision 1.25 2001/04/04 06:23:53 starvik
- * Initialize DRAM if not already initialized
- *
- * Revision 1.24 2001/04/03 11:12:00 starvik
- * Removed dram init (done by rescue or etrax100boot
- * Corrected include
- *
- * Revision 1.23 2001/04/03 09:53:03 starvik
- * Include hw_settings.S
- *
- * Revision 1.22 2001/03/26 14:23:26 bjornw
- * Namechange of some config options
- *
- * Revision 1.21 2001/03/08 12:14:41 bjornw
- * * Config name for ETRAX IDE was renamed
- * * Removed G27 auto-setting when JULIETTE is chosen (need to make this
- * a new config option later)
- *
- * Revision 1.20 2001/02/23 12:47:56 bjornw
- * MMU regs during LOW_MAP updated to reflect a newer reality
- *
- * Revision 1.19 2001/02/19 11:12:07 bjornw
- * Changed comment header format
- *
- * Revision 1.18 2001/02/15 07:25:38 starvik
- * Added support for synchronous serial ports
- *
- * Revision 1.17 2001/02/08 15:53:13 starvik
- * Last commit removed some important ifdefs
- *
- * Revision 1.16 2001/02/08 15:20:38 starvik
- * Include dram_init.S as inline
- *
- * Revision 1.15 2001/01/29 18:12:01 bjornw
- * Corrected some comments
- *
- * Revision 1.14 2001/01/29 13:11:29 starvik
- * Include dram_init.S (with DRAM/SDRAM initialization)
- *
- * Revision 1.13 2001/01/23 14:54:57 markusl
- * Updated for USB
- * i.e. added r_gen_config settings
- *
- * Revision 1.12 2001/01/19 16:16:29 perf
- * Added temporary mapping of 0x0c->0x0c to avoid flash loading confusion.
- * Renamed serial options from ETRAX100 to ETRAX.
- *
- * Revision 1.11 2001/01/16 16:31:38 bjornw
- * * Changed name and semantics of running_from_flash to romfs_in_flash,
- * set by head.S to indicate to setup.c whether there is a cramfs image
- * after the kernels BSS or not. Should work for all three boot-cases
- * (DRAM with cramfs in DRAM, DRAM with cramfs in flash (compressed boot),
- * and flash with cramfs in flash)
- *
- * Revision 1.10 2001/01/16 14:12:21 bjornw
- * * Check for cramfs start passed in r9 from the decompressor, if all other
- * cramfs options fail (if we boot from DRAM but don't find a cramfs image
- * after the kernel in DRAM, it is probably still in the flash)
- * * Check magic in cramfs detection when booting from flash directly
- *
- * Revision 1.9 2001/01/15 17:17:02 bjornw
- * * Corrected the code that detects the cramfs lengths
- * * Added a comment saying that the above does not work due to other
- * reasons..
- *
- * Revision 1.8 2001/01/15 16:27:51 jonashg
- * Made boot after flashing work.
- * * end destination is __vmlinux_end in RAM.
- * * _romfs_start moved because of virtual memory.
- *
- * Revision 1.7 2000/11/21 13:55:29 bjornw
- * Use CONFIG_CRIS_LOW_MAP for the low VM map instead of explicit CPU type
- *
- * Revision 1.6 2000/10/06 12:36:55 bjornw
- * Forgot swapper_pg_dir when changing memory map..
- *
- * Revision 1.5 2000/10/04 16:49:30 bjornw
- * * Fixed memory mapping in LX
- * * Check for cramfs instead of romfs
- *
*/
#define ASSEMBLER_MACROS_ONLY
@@ -595,11 +419,17 @@ no_command_line:
moveq 0,$r0
+ ;; Select or disable serial port 2
+#ifdef CONFIG_ETRAX_SERIAL_PORT2
+ or.d IO_STATE (R_GEN_CONFIG, ser2, select),$r0
+#else
+ or.d IO_STATE (R_GEN_CONFIG, ser2, disable),$r0
+#endif
+
;; Init interfaces (disable them).
or.d IO_STATE (R_GEN_CONFIG, scsi0, disable) \
| IO_STATE (R_GEN_CONFIG, ata, disable) \
| IO_STATE (R_GEN_CONFIG, par0, disable) \
- | IO_STATE (R_GEN_CONFIG, ser2, disable) \
| IO_STATE (R_GEN_CONFIG, mio, disable) \
| IO_STATE (R_GEN_CONFIG, scsi1, disable) \
| IO_STATE (R_GEN_CONFIG, scsi0w, disable) \
@@ -801,6 +631,41 @@ no_command_line:
| IO_STATE (R_SERIAL1_TR_CTRL, tr_bitnr, tr_8bit),$r0
move.b $r0,[R_SERIAL1_TR_CTRL]
+#ifdef CONFIG_ETRAX_SERIAL_PORT2
+ ;; setup the serial port 2 at 115200 baud for debug purposes
+
+ moveq IO_STATE (R_SERIAL2_XOFF, tx_stop, enable) \
+ | IO_STATE (R_SERIAL2_XOFF, auto_xoff, disable) \
+ | IO_FIELD (R_SERIAL2_XOFF, xoff_char, 0),$r0
+ move.d $r0,[R_SERIAL2_XOFF]
+
+ ; 115.2kbaud for both transmit and receive
+ move.b IO_STATE (R_SERIAL2_BAUD, tr_baud, c115k2Hz) \
+ | IO_STATE (R_SERIAL2_BAUD, rec_baud, c115k2Hz),$r0
+ move.b $r0,[R_SERIAL2_BAUD]
+
+ ; Set up and enable the serial2 receiver.
+ move.b IO_STATE (R_SERIAL2_REC_CTRL, dma_err, stop) \
+ | IO_STATE (R_SERIAL2_REC_CTRL, rec_enable, enable) \
+ | IO_STATE (R_SERIAL2_REC_CTRL, rts_, active) \
+ | IO_STATE (R_SERIAL2_REC_CTRL, sampling, middle) \
+ | IO_STATE (R_SERIAL2_REC_CTRL, rec_stick_par, normal) \
+ | IO_STATE (R_SERIAL2_REC_CTRL, rec_par, even) \
+ | IO_STATE (R_SERIAL2_REC_CTRL, rec_par_en, disable) \
+ | IO_STATE (R_SERIAL2_REC_CTRL, rec_bitnr, rec_8bit),$r0
+ move.b $r0,[R_SERIAL2_REC_CTRL]
+
+ ; Set up and enable the serial2 transmitter.
+ move.b IO_FIELD (R_SERIAL2_TR_CTRL, txd, 0) \
+ | IO_STATE (R_SERIAL2_TR_CTRL, tr_enable, enable) \
+ | IO_STATE (R_SERIAL2_TR_CTRL, auto_cts, disabled) \
+ | IO_STATE (R_SERIAL2_TR_CTRL, stop_bits, one_bit) \
+ | IO_STATE (R_SERIAL2_TR_CTRL, tr_stick_par, normal) \
+ | IO_STATE (R_SERIAL2_TR_CTRL, tr_par, even) \
+ | IO_STATE (R_SERIAL2_TR_CTRL, tr_par_en, disable) \
+ | IO_STATE (R_SERIAL2_TR_CTRL, tr_bitnr, tr_8bit),$r0
+ move.b $r0,[R_SERIAL2_TR_CTRL]
+#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT3
;; setup the serial port 3 at 115200 baud for debug purposes
diff --git a/arch/cris/arch-v10/kernel/io_interface_mux.c b/arch/cris/arch-v10/kernel/io_interface_mux.c
index f3b327d4ed9..add98e0941b 100644
--- a/arch/cris/arch-v10/kernel/io_interface_mux.c
+++ b/arch/cris/arch-v10/kernel/io_interface_mux.c
@@ -1,10 +1,9 @@
/* IO interface mux allocator for ETRAX100LX.
- * Copyright 2004, Axis Communications AB
- * $Id: io_interface_mux.c,v 1.2 2004/12/21 12:08:38 starvik Exp $
+ * Copyright 2004-2007, Axis Communications AB
*/
-/* C.f. ETRAX100LX Designer's Reference 20.9 */
+/* C.f. ETRAX100LX Designer's Reference chapter 19.9 */
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -45,17 +44,39 @@ struct watcher
struct if_group
{
enum io_if_group group;
- unsigned char used;
- enum cris_io_interface owner;
+ /* name - the name of the group 'A' to 'F' */
+ char *name;
+ /* used - a bit mask of all pins in the group in the order listed
+ * in the tables in 19.9.1 to 19.9.6. Note that no
+ * distinction is made between in, out and in/out pins. */
+ unsigned int used;
};
struct interface
{
enum cris_io_interface ioif;
+ /* name - the name of the interface */
+ char *name;
+ /* groups - OR'ed together io_if_group flags describing what pin groups
+ * the interface uses pins in. */
unsigned char groups;
+ /* used - set when the interface is allocated. */
unsigned char used;
char *owner;
+ /* group_a through group_f - bit masks describing what pins in the
+ * pin groups the interface uses. */
+ unsigned int group_a;
+ unsigned int group_b;
+ unsigned int group_c;
+ unsigned int group_d;
+ unsigned int group_e;
+ unsigned int group_f;
+
+ /* gpio_g_in, gpio_g_out, gpio_b - bit masks telling what pins in the
+ * GPIO ports the interface uses. This could be reconstucted using
+ * the group_X masks and a table of what pins the GPIO ports use,
+ * but that would be messy. */
unsigned int gpio_g_in;
unsigned int gpio_g_out;
unsigned char gpio_b;
@@ -64,26 +85,32 @@ struct interface
static struct if_group if_groups[6] = {
{
.group = group_a,
+ .name = "A",
.used = 0,
},
{
.group = group_b,
+ .name = "B",
.used = 0,
},
{
.group = group_c,
+ .name = "C",
.used = 0,
},
{
.group = group_d,
+ .name = "D",
.used = 0,
},
{
.group = group_e,
+ .name = "E",
.used = 0,
},
{
.group = group_f,
+ .name = "F",
.used = 0,
}
};
@@ -94,14 +121,32 @@ static struct interface interfaces[] = {
/* Begin Non-multiplexed interfaces */
{
.ioif = if_eth,
+ .name = "ethernet",
.groups = 0,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0,
.gpio_g_out = 0,
.gpio_b = 0
},
{
.ioif = if_serial_0,
+ .name = "serial_0",
.groups = 0,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0,
.gpio_g_out = 0,
.gpio_b = 0
@@ -109,172 +154,385 @@ static struct interface interfaces[] = {
/* End Non-multiplexed interfaces */
{
.ioif = if_serial_1,
+ .name = "serial_1",
.groups = group_e,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0x0f,
+ .group_f = 0,
+
.gpio_g_in = 0x00000000,
.gpio_g_out = 0x00000000,
.gpio_b = 0x00
},
{
.ioif = if_serial_2,
+ .name = "serial_2",
.groups = group_b,
+
+ .group_a = 0,
+ .group_b = 0x0f,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0x000000c0,
.gpio_g_out = 0x000000c0,
.gpio_b = 0x00
},
{
.ioif = if_serial_3,
+ .name = "serial_3",
.groups = group_c,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0x0f,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0xc0000000,
.gpio_g_out = 0xc0000000,
.gpio_b = 0x00
},
{
.ioif = if_sync_serial_1,
- .groups = group_e | group_f, /* if_sync_serial_1 and if_sync_serial_3
- can be used simultaneously */
+ .name = "sync_serial_1",
+ .groups = group_e | group_f,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0x0f,
+ .group_f = 0x10,
+
.gpio_g_in = 0x00000000,
.gpio_g_out = 0x00000000,
.gpio_b = 0x10
},
{
.ioif = if_sync_serial_3,
+ .name = "sync_serial_3",
.groups = group_c | group_f,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0x0f,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0x80,
+
.gpio_g_in = 0xc0000000,
.gpio_g_out = 0xc0000000,
.gpio_b = 0x80
},
{
.ioif = if_shared_ram,
+ .name = "shared_ram",
.groups = group_a,
+
+ .group_a = 0x7f8ff,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0x0000ff3e,
.gpio_g_out = 0x0000ff38,
.gpio_b = 0x00
},
{
.ioif = if_shared_ram_w,
+ .name = "shared_ram_w",
.groups = group_a | group_d,
+
+ .group_a = 0x7f8ff,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0xff,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0x00ffff3e,
.gpio_g_out = 0x00ffff38,
.gpio_b = 0x00
},
{
.ioif = if_par_0,
+ .name = "par_0",
.groups = group_a,
+
+ .group_a = 0x7fbff,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0x0000ff3e,
.gpio_g_out = 0x0000ff3e,
.gpio_b = 0x00
},
{
.ioif = if_par_1,
+ .name = "par_1",
.groups = group_d,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0x7feff,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0x3eff0000,
.gpio_g_out = 0x3eff0000,
.gpio_b = 0x00
},
{
.ioif = if_par_w,
+ .name = "par_w",
.groups = group_a | group_d,
+
+ .group_a = 0x7fbff,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0xff,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0x00ffff3e,
.gpio_g_out = 0x00ffff3e,
.gpio_b = 0x00
},
{
.ioif = if_scsi8_0,
- .groups = group_a | group_b | group_f, /* if_scsi8_0 and if_scsi8_1
- can be used simultaneously */
+ .name = "scsi8_0",
+ .groups = group_a | group_b | group_f,
+
+ .group_a = 0x7ffff,
+ .group_b = 0x0f,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0x10,
+
.gpio_g_in = 0x0000ffff,
.gpio_g_out = 0x0000ffff,
.gpio_b = 0x10
},
{
.ioif = if_scsi8_1,
- .groups = group_c | group_d | group_f, /* if_scsi8_0 and if_scsi8_1
- can be used simultaneously */
+ .name = "scsi8_1",
+ .groups = group_c | group_d | group_f,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0x0f,
+ .group_d = 0x7ffff,
+ .group_e = 0,
+ .group_f = 0x80,
+
.gpio_g_in = 0xffff0000,
.gpio_g_out = 0xffff0000,
.gpio_b = 0x80
},
{
.ioif = if_scsi_w,
+ .name = "scsi_w",
.groups = group_a | group_b | group_d | group_f,
+
+ .group_a = 0x7ffff,
+ .group_b = 0x0f,
+ .group_c = 0,
+ .group_d = 0x601ff,
+ .group_e = 0,
+ .group_f = 0x90,
+
.gpio_g_in = 0x01ffffff,
.gpio_g_out = 0x07ffffff,
.gpio_b = 0x80
},
{
.ioif = if_ata,
+ .name = "ata",
.groups = group_a | group_b | group_c | group_d,
+
+ .group_a = 0x7ffff,
+ .group_b = 0x0f,
+ .group_c = 0x0f,
+ .group_d = 0x7cfff,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0xf9ffffff,
.gpio_g_out = 0xffffffff,
.gpio_b = 0x80
},
{
.ioif = if_csp,
- .groups = group_f, /* if_csp and if_i2c can be used simultaneously */
+ .name = "csp",
+ .groups = group_f,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0xfc,
+
.gpio_g_in = 0x00000000,
.gpio_g_out = 0x00000000,
.gpio_b = 0xfc
},
{
.ioif = if_i2c,
- .groups = group_f, /* if_csp and if_i2c can be used simultaneously */
+ .name = "i2c",
+ .groups = group_f,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0x03,
+
.gpio_g_in = 0x00000000,
.gpio_g_out = 0x00000000,
.gpio_b = 0x03
},
{
.ioif = if_usb_1,
+ .name = "usb_1",
.groups = group_e | group_f,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0x0f,
+ .group_f = 0x2c,
+
.gpio_g_in = 0x00000000,
.gpio_g_out = 0x00000000,
.gpio_b = 0x2c
},
{
.ioif = if_usb_2,
+ .name = "usb_2",
.groups = group_d,
- .gpio_g_in = 0x0e000000,
- .gpio_g_out = 0x3c000000,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0x33e00,
+ .group_f = 0,
+
+ .gpio_g_in = 0x3e000000,
+ .gpio_g_out = 0x0c000000,
.gpio_b = 0x00
},
/* GPIO pins */
{
.ioif = if_gpio_grp_a,
+ .name = "gpio_a",
.groups = group_a,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0x0000ff3f,
.gpio_g_out = 0x0000ff3f,
.gpio_b = 0x00
},
{
.ioif = if_gpio_grp_b,
+ .name = "gpio_b",
.groups = group_b,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0x000000c0,
.gpio_g_out = 0x000000c0,
.gpio_b = 0x00
},
{
.ioif = if_gpio_grp_c,
+ .name = "gpio_c",
.groups = group_c,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0xc0000000,
.gpio_g_out = 0xc0000000,
.gpio_b = 0x00
},
{
.ioif = if_gpio_grp_d,
+ .name = "gpio_d",
.groups = group_d,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0x3fff0000,
.gpio_g_out = 0x3fff0000,
.gpio_b = 0x00
},
{
.ioif = if_gpio_grp_e,
+ .name = "gpio_e",
.groups = group_e,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0x00000000,
.gpio_g_out = 0x00000000,
.gpio_b = 0x00
},
{
.ioif = if_gpio_grp_f,
+ .name = "gpio_f",
.groups = group_f,
+
+ .group_a = 0,
+ .group_b = 0,
+ .group_c = 0,
+ .group_d = 0,
+ .group_e = 0,
+ .group_f = 0,
+
.gpio_g_in = 0x00000000,
.gpio_g_out = 0x00000000,
.gpio_b = 0xff
@@ -284,11 +542,13 @@ static struct interface interfaces[] = {
static struct watcher *watchers = NULL;
+/* The pins that are free to use in the GPIO ports. */
static unsigned int gpio_in_pins = 0xffffffff;
static unsigned int gpio_out_pins = 0xffffffff;
static unsigned char gpio_pb_pins = 0xff;
static unsigned char gpio_pa_pins = 0xff;
+/* Identifiers for the owners of the GPIO pins. */
static enum cris_io_interface gpio_pa_owners[8];
static enum cris_io_interface gpio_pb_owners[8];
static enum cris_io_interface gpio_pg_owners[32];
@@ -338,13 +598,15 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id
struct if_group *grp;
unsigned char group_set;
unsigned long flags;
+ int res = 0;
(void)cris_io_interface_init();
DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id));
if ((ioif >= if_max_interfaces) || (ioif < 0)) {
- printk(KERN_CRIT "cris_request_io_interface: Bad interface %u submitted for %s\n",
+ printk(KERN_CRIT "cris_request_io_interface: Bad interface "
+ "%u submitted for %s\n",
ioif,
device_id);
return -EINVAL;
@@ -353,59 +615,69 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id
local_irq_save(flags);
if (interfaces[ioif].used) {
- local_irq_restore(flags);
- printk(KERN_CRIT "cris_io_interface: Cannot allocate interface for %s, in use by %s\n",
+ printk(KERN_CRIT "cris_io_interface: Cannot allocate interface "
+ "%s for %s, in use by %s\n",
+ interfaces[ioif].name,
device_id,
interfaces[ioif].owner);
- return -EBUSY;
+ res = -EBUSY;
+ goto exit;
}
- /* Check that all required groups are free before allocating, */
+ /* Check that all required pins in the used groups are free
+ * before allocating. */
group_set = interfaces[ioif].groups;
while (NULL != (grp = get_group(group_set))) {
- if (grp->used) {
- if (grp->group == group_f) {
- if ((if_sync_serial_1 == ioif) ||
- (if_sync_serial_3 == ioif)) {
- if ((grp->owner != if_sync_serial_1) &&
- (grp->owner != if_sync_serial_3)) {
- local_irq_restore(flags);
- return -EBUSY;
- }
- } else if ((if_scsi8_0 == ioif) ||
- (if_scsi8_1 == ioif)) {
- if ((grp->owner != if_scsi8_0) &&
- (grp->owner != if_scsi8_1)) {
- local_irq_restore(flags);
- return -EBUSY;
- }
- }
- } else {
- local_irq_restore(flags);
- return -EBUSY;
- }
+ unsigned int if_group_use = 0;
+
+ switch (grp->group) {
+ case group_a:
+ if_group_use = interfaces[ioif].group_a;
+ break;
+ case group_b:
+ if_group_use = interfaces[ioif].group_b;
+ break;
+ case group_c:
+ if_group_use = interfaces[ioif].group_c;
+ break;
+ case group_d:
+ if_group_use = interfaces[ioif].group_d;
+ break;
+ case group_e:
+ if_group_use = interfaces[ioif].group_e;
+ break;
+ case group_f:
+ if_group_use = interfaces[ioif].group_f;
+ break;
+ default:
+ BUG_ON(1);
}
+
+ if (if_group_use & grp->used) {
+ printk(KERN_INFO "cris_request_io_interface: group "
+ "%s needed by %s not available\n",
+ grp->name, interfaces[ioif].name);
+ res = -EBUSY;
+ goto exit;
+ }
+
group_set = clear_group_from_set(group_set, grp);
}
/* Are the required GPIO pins available too? */
- if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != interfaces[ioif].gpio_g_in) ||
- ((interfaces[ioif].gpio_g_out & gpio_out_pins) != interfaces[ioif].gpio_g_out) ||
- ((interfaces[ioif].gpio_b & gpio_pb_pins) != interfaces[ioif].gpio_b)) {
- local_irq_restore(flags);
- printk(KERN_CRIT "cris_request_io_interface: Could not get required pins for interface %u\n",
- ioif);
- return -EBUSY;
- }
-
- /* All needed I/O pins and pin groups are free, allocate. */
- group_set = interfaces[ioif].groups;
- while (NULL != (grp = get_group(group_set))) {
- grp->used = 1;
- grp->owner = ioif;
- group_set = clear_group_from_set(group_set, grp);
+ if (((interfaces[ioif].gpio_g_in & gpio_in_pins) !=
+ interfaces[ioif].gpio_g_in) ||
+ ((interfaces[ioif].gpio_g_out & gpio_out_pins) !=
+ interfaces[ioif].gpio_g_out) ||
+ ((interfaces[ioif].gpio_b & gpio_pb_pins) !=
+ interfaces[ioif].gpio_b)) {
+ printk(KERN_CRIT "cris_request_io_interface: Could not get "
+ "required pins for interface %u\n", ioif);
+ res = -EBUSY;
+ goto exit;
}
+ /* Check which registers need to be reconfigured. */
gens = genconfig_shadow;
gens_ii = gen_config_ii_shadow;
@@ -495,9 +767,43 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id
set_gen_config = 0;
break;
default:
- panic("cris_request_io_interface: Bad interface %u submitted for %s\n",
- ioif,
- device_id);
+ printk(KERN_INFO "cris_request_io_interface: Bad interface "
+ "%u submitted for %s\n",
+ ioif, device_id);
+ res = -EBUSY;
+ goto exit;
+ }
+
+ /* All needed I/O pins and pin groups are free, allocate. */
+ group_set = interfaces[ioif].groups;
+ while (NULL != (grp = get_group(group_set))) {
+ unsigned int if_group_use = 0;
+
+ switch (grp->group) {
+ case group_a:
+ if_group_use = interfaces[ioif].group_a;
+ break;
+ case group_b:
+ if_group_use = interfaces[ioif].group_b;
+ break;
+ case group_c:
+ if_group_use = interfaces[ioif].group_c;
+ break;
+ case group_d:
+ if_group_use = interfaces[ioif].group_d;
+ break;
+ case group_e:
+ if_group_use = interfaces[ioif].group_e;
+ break;
+ case group_f:
+ if_group_use = interfaces[ioif].group_f;
+ break;
+ default:
+ BUG_ON(1);
+ }
+ grp->used |= if_group_use;
+
+ group_set = clear_group_from_set(group_set, grp);
}
interfaces[ioif].used = 1;
@@ -516,25 +822,28 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id
*R_GEN_CONFIG_II = gen_config_ii_shadow;
}
- DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
- gpio_in_pins, gpio_out_pins, gpio_pb_pins));
- DBG(printk("grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
- interfaces[ioif].gpio_g_in,
- interfaces[ioif].gpio_g_out,
- interfaces[ioif].gpio_b));
+ DBG(printk(KERN_DEBUG "GPIO pins: available before: "
+ "g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
+ gpio_in_pins, gpio_out_pins, gpio_pb_pins));
+ DBG(printk(KERN_DEBUG
+ "grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
+ interfaces[ioif].gpio_g_in,
+ interfaces[ioif].gpio_g_out,
+ interfaces[ioif].gpio_b));
gpio_in_pins &= ~interfaces[ioif].gpio_g_in;
gpio_out_pins &= ~interfaces[ioif].gpio_g_out;
gpio_pb_pins &= ~interfaces[ioif].gpio_b;
- DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
- gpio_in_pins, gpio_out_pins, gpio_pb_pins));
+ DBG(printk(KERN_DEBUG "GPIO pins: available after: "
+ "g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
+ gpio_in_pins, gpio_out_pins, gpio_pb_pins));
+exit:
local_irq_restore(flags);
-
- notify_watchers();
-
- return 0;
+ if (res == 0)
+ notify_watchers();
+ return res;
}
@@ -560,43 +869,35 @@ void cris_free_io_interface(enum cris_io_interface ioif)
}
group_set = interfaces[ioif].groups;
while (NULL != (grp = get_group(group_set))) {
- if (grp->group == group_f) {
- switch (ioif)
- {
- case if_sync_serial_1:
- if ((grp->owner == if_sync_serial_1) &&
- interfaces[if_sync_serial_3].used) {
- grp->owner = if_sync_serial_3;
- } else
- grp->used = 0;
- break;
- case if_sync_serial_3:
- if ((grp->owner == if_sync_serial_3) &&
- interfaces[if_sync_serial_1].used) {
- grp->owner = if_sync_serial_1;
- } else
- grp->used = 0;
- break;
- case if_scsi8_0:
- if ((grp->owner == if_scsi8_0) &&
- interfaces[if_scsi8_1].used) {
- grp->owner = if_scsi8_1;
- } else
- grp->used = 0;
- break;
- case if_scsi8_1:
- if ((grp->owner == if_scsi8_1) &&
- interfaces[if_scsi8_0].used) {
- grp->owner = if_scsi8_0;
- } else
- grp->used = 0;
- break;
- default:
- grp->used = 0;
- }
- } else {
- grp->used = 0;
+ unsigned int if_group_use = 0;
+
+ switch (grp->group) {
+ case group_a:
+ if_group_use = interfaces[ioif].group_a;
+ break;
+ case group_b:
+ if_group_use = interfaces[ioif].group_b;
+ break;
+ case group_c:
+ if_group_use = interfaces[ioif].group_c;
+ break;
+ case group_d:
+ if_group_use = interfaces[ioif].group_d;
+ break;
+ case group_e:
+ if_group_use = interfaces[ioif].group_e;
+ break;
+ case group_f:
+ if_group_use = interfaces[ioif].group_f;
+ break;
+ default:
+ BUG_ON(1);
}
+
+ if ((grp->used & if_group_use) != if_group_use)
+ BUG_ON(1);
+ grp->used = grp->used & ~if_group_use;
+
group_set = clear_group_from_set(group_set, grp);
}
interfaces[ioif].used = 0;
diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c
index e06ab0050d3..65ed803dae6 100644
--- a/arch/cris/arch-v10/kernel/irq.c
+++ b/arch/cris/arch-v10/kernel/irq.c
@@ -1,5 +1,4 @@
-/* $Id: irq.c,v 1.4 2005/01/04 12:22:28 starvik Exp $
- *
+/*
* linux/arch/cris/kernel/irq.c
*
* Copyright (c) 2000-2002 Axis Communications AB
@@ -18,10 +17,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
-/* From kgdb.c. */
-extern void kgdb_init(void);
-extern void breakpoint(void);
-
#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c
index 77f4b142372..a3ca5515074 100644
--- a/arch/cris/arch-v10/kernel/kgdb.c
+++ b/arch/cris/arch-v10/kernel/kgdb.c
@@ -17,66 +17,8 @@
*! Jun 17 1999 Hendrik Ruijter Added gdb 4.18 support. 'X', 'qC' and 'qL'.
*! Jul 21 1999 Bjorn Wesen eLinux port
*!
-*! $Log: kgdb.c,v $
-*! Revision 1.6 2005/01/14 10:12:17 starvik
-*! KGDB on separate port.
-*! Console fixes from 2.4.
-*!
-*! Revision 1.5 2004/10/07 13:59:08 starvik
-*! Corrected call to set_int_vector
-*!
-*! Revision 1.4 2003/04/09 05:20:44 starvik
-*! Merge of Linux 2.5.67
-*!
-*! Revision 1.3 2003/01/21 19:11:08 starvik
-*! Modified include path for new dir layout
-*!
-*! Revision 1.2 2002/11/19 14:35:24 starvik
-*! Changes from linux 2.4
-*! Changed struct initializer syntax to the currently preferred notation
-*!
-*! Revision 1.1 2001/12/17 13:59:27 bjornw
-*! Initial revision
-*!
-*! Revision 1.6 2001/10/09 13:10:03 matsfg
-*! Added $ on registers and removed some underscores
-*!
-*! Revision 1.5 2001/04/17 13:58:39 orjanf
-*! * Renamed CONFIG_KGDB to CONFIG_ETRAX_KGDB.
-*!
-*! Revision 1.4 2001/02/23 13:45:19 bjornw
-*! config.h check
-*!
-*! Revision 1.3 2001/01/31 18:08:23 orjanf
-*! Removed kgdb_handle_breakpoint from being the break 8 handler.
-*!
-*! Revision 1.2 2001/01/12 14:22:25 orjanf
-*! Updated kernel debugging support to work with ETRAX 100LX.
-*!
-*! Revision 1.1 2000/07/10 16:25:21 bjornw
-*! Initial revision
-*!
-*! Revision 1.1.1.1 1999/12/03 14:57:31 bjornw
-*! * Initial version of arch/cris, the latest CRIS architecture with an MMU.
-*! Mostly copied from arch/etrax100 with appropriate renames of files.
-*! The mm/ subdir is copied from arch/i386.
-*! This does not compile yet at all.
-*!
-*!
-*! Revision 1.4 1999/07/22 17:25:25 bjornw
-*! Dont wait for + in putpacket if we havent hit the initial breakpoint yet. Added a kgdb_init function which sets up the break and irq vectors.
-*!
-*! Revision 1.3 1999/07/21 19:51:18 bjornw
-*! Check if the interrupting char is a ctrl-C, ignore otherwise.
-*!
-*! Revision 1.2 1999/07/21 18:09:39 bjornw
-*! Ported to eLinux architecture, and added some kgdb documentation.
-*!
-*!
*!---------------------------------------------------------------------------
*!
-*! $Id: kgdb.c,v 1.6 2005/01/14 10:12:17 starvik Exp $
-*!
*! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN
*!
*!**************************************************************************/
diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c
index 1a3760c94f8..53117f07cc1 100644
--- a/arch/cris/arch-v10/kernel/process.c
+++ b/arch/cris/arch-v10/kernel/process.c
@@ -1,5 +1,4 @@
-/* $Id: process.c,v 1.12 2004/12/27 11:18:32 starvik Exp $
- *
+/*
* linux/arch/cris/kernel/process.c
*
* Copyright (C) 1995 Linus Torvalds
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index b570ae9b6ca..ee505b2eb4d 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -65,6 +65,7 @@ void
ptrace_disable(struct task_struct *child)
{
/* Todo - pending singlesteps? */
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
}
/*
diff --git a/arch/cris/arch-v10/kernel/shadows.c b/arch/cris/arch-v10/kernel/shadows.c
index 326178aef6e..2454a0b02f5 100644
--- a/arch/cris/arch-v10/kernel/shadows.c
+++ b/arch/cris/arch-v10/kernel/shadows.c
@@ -1,5 +1,4 @@
-/* $Id: shadows.c,v 1.2 2004/12/13 12:21:51 starvik Exp $
- *
+/*
* Various shadow registers. Defines for these are in include/asm-etrax100/io.h
*/
diff --git a/arch/cris/arch-v10/kernel/traps.c b/arch/cris/arch-v10/kernel/traps.c
index 4becc1bcced..9eada5d8893 100644
--- a/arch/cris/arch-v10/kernel/traps.c
+++ b/arch/cris/arch-v10/kernel/traps.c
@@ -1,13 +1,10 @@
-/* $Id: traps.c,v 1.4 2005/04/24 18:47:55 starvik Exp $
+/*
+ * Helper functions for trap handlers
*
- * linux/arch/cris/arch-v10/traps.c
+ * Copyright (C) 2000-2007, Axis Communications AB.
*
- * Heler functions for trap handlers
- *
- * Copyright (C) 2000-2002 Axis Communications AB
- *
- * Authors: Bjorn Wesen
- * Hans-Peter Nilsson
+ * Authors: Bjorn Wesen
+ * Hans-Peter Nilsson
*
*/
@@ -15,124 +12,119 @@
#include <asm/uaccess.h>
#include <asm/arch/sv_addr_ag.h>
-extern int raw_printk(const char *fmt, ...);
-
-void
-show_registers(struct pt_regs * regs)
+void
+show_registers(struct pt_regs *regs)
{
- /* We either use rdusp() - the USP register, which might not
- correspond to the current process for all cases we're called,
- or we use the current->thread.usp, which is not up to date for
- the current process. Experience shows we want the USP
- register. */
+ /*
+ * It's possible to use either the USP register or current->thread.usp.
+ * USP might not correspond to the current process for all cases this
+ * function is called, and current->thread.usp isn't up to date for the
+ * current process. Experience shows that using USP is the way to go.
+ */
unsigned long usp = rdusp();
- raw_printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
- regs->irp, regs->srp, regs->dccr, usp, regs->mof );
- raw_printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
+ printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
+ regs->irp, regs->srp, regs->dccr, usp, regs->mof);
+
+ printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
regs->r0, regs->r1, regs->r2, regs->r3);
- raw_printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
+
+ printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
regs->r4, regs->r5, regs->r6, regs->r7);
- raw_printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
+
+ printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
regs->r8, regs->r9, regs->r10, regs->r11);
- raw_printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n",
- regs->r12, regs->r13, regs->orig_r10, regs);
- raw_printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
- raw_printk("Process %s (pid: %d, stackpage=%08lx)\n",
+
+ printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n",
+ regs->r12, regs->r13, regs->orig_r10, (long unsigned)regs);
+
+ printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
+
+ printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, (unsigned long)current);
/*
- * When in-kernel, we also print out the stack and code at the
- * time of the fault..
- */
- if (! user_mode(regs)) {
- int i;
+ * When in-kernel, we also print out the stack and code at the
+ * time of the fault..
+ */
+ if (!user_mode(regs)) {
+ int i;
- show_stack(NULL, (unsigned long*)usp);
+ show_stack(NULL, (unsigned long *)usp);
- /* Dump kernel stack if the previous dump wasn't one. */
+ /*
+ * If the previous stack-dump wasn't a kernel one, dump the
+ * kernel stack now.
+ */
if (usp != 0)
- show_stack (NULL, NULL);
-
- raw_printk("\nCode: ");
- if(regs->irp < PAGE_OFFSET)
- goto bad;
-
- /* Often enough the value at regs->irp does not point to
- the interesting instruction, which is most often the
- _previous_ instruction. So we dump at an offset large
- enough that instruction decoding should be in sync at
- the interesting point, but small enough to fit on a row
- (sort of). We point out the regs->irp location in a
- ksymoops-friendly way by wrapping the byte for that
- address in parentheses. */
- for(i = -12; i < 12; i++)
- {
- unsigned char c;
- if(__get_user(c, &((unsigned char*)regs->irp)[i])) {
-bad:
- raw_printk(" Bad IP value.");
- break;
- }
+ show_stack(NULL, NULL);
+
+ printk("\nCode: ");
+
+ if (regs->irp < PAGE_OFFSET)
+ goto bad_value;
+
+ /*
+ * Quite often the value at regs->irp doesn't point to the
+ * interesting instruction, which often is the previous
+ * instruction. So dump at an offset large enough that the
+ * instruction decoding should be in sync at the interesting
+ * point, but small enough to fit on a row. The regs->irp
+ * location is pointed out in a ksymoops-friendly way by
+ * wrapping the byte for that address in parenthesises.
+ */
+ for (i = -12; i < 12; i++) {
+ unsigned char c;
+
+ if (__get_user(c, &((unsigned char *)regs->irp)[i])) {
+bad_value:
+ printk(" Bad IP value.");
+ break;
+ }
if (i == 0)
- raw_printk("(%02x) ", c);
+ printk("(%02x) ", c);
else
- raw_printk("%02x ", c);
- }
- raw_printk("\n");
- }
+ printk("%02x ", c);
+ }
+ printk("\n");
+ }
}
-/* Called from entry.S when the watchdog has bitten
- * We print out something resembling an oops dump, and if
- * we have the nice doggy development flag set, we halt here
- * instead of rebooting.
- */
-
-extern void reset_watchdog(void);
-extern void stop_watchdog(void);
-
-
void
-watchdog_bite_hook(struct pt_regs *regs)
+arch_enable_nmi(void)
{
-#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
- local_irq_disable();
- stop_watchdog();
- show_registers(regs);
- while(1) /* nothing */;
-#else
- show_registers(regs);
-#endif
+ asm volatile ("setf m");
}
-/* This is normally the 'Oops' routine */
-void
-die_if_kernel(const char * str, struct pt_regs * regs, long err)
+extern void (*nmi_handler)(struct pt_regs *);
+void handle_nmi(struct pt_regs *regs)
{
- if(user_mode(regs))
- return;
-
-#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
- /* This printout might take too long and trigger the
- * watchdog normally. If we're in the nice doggy
- * development mode, stop the watchdog during printout.
- */
- stop_watchdog();
-#endif
-
- raw_printk("%s: %04lx\n", str, err & 0xffff);
-
- show_registers(regs);
-
-#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
- reset_watchdog();
-#endif
- do_exit(SIGSEGV);
+ if (nmi_handler)
+ nmi_handler(regs);
+
+ /* Wait until nmi is no longer active. (We enable NMI immediately after
+ returning from this function, and we don't want it happening while
+ exiting from the NMI interrupt handler.) */
+ while (*R_IRQ_MASK0_RD & IO_STATE(R_IRQ_MASK0_RD, nmi_pin, active))
+ ;
}
-void arch_enable_nmi(void)
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+void
+handle_BUG(struct pt_regs *regs)
{
- asm volatile("setf m");
+ struct bug_frame f;
+ unsigned char c;
+ unsigned long irp = regs->irp;
+
+ if (__copy_from_user(&f, (const void __user *)(irp - 8), sizeof f))
+ return;
+ if (f.prefix != BUG_PREFIX || f.magic != BUG_MAGIC)
+ return;
+ if (__get_user(c, f.filename))
+ f.filename = "<bad filename>";
+
+ printk("kernel BUG at %s:%d!\n", f.filename, f.line);
}
+#endif
diff --git a/arch/cris/arch-v10/lib/checksum.S b/arch/cris/arch-v10/lib/checksum.S
index 85c48f0a9ec..7d552f4bd5a 100644
--- a/arch/cris/arch-v10/lib/checksum.S
+++ b/arch/cris/arch-v10/lib/checksum.S
@@ -1,4 +1,4 @@
-/* $Id: checksum.S,v 1.1 2001/12/17 13:59:27 bjornw Exp $
+/*
* A fast checksum routine using movem
* Copyright (c) 1998-2001 Axis Communications AB
*
@@ -61,8 +61,6 @@ _mloop: movem [$r10+],$r9 ; read 10 longwords
ax
addq 0,$r12
- ax ; do it again, since we might have generated a carry
- addq 0,$r12
subq 10*4,$r11
bge _mloop
@@ -88,10 +86,6 @@ _word_loop:
lsrq 16,$r13 ; r13 = checksum >> 16
and.d $r9,$r12 ; checksum = checksum & 0xffff
add.d $r13,$r12 ; checksum += r13
- move.d $r12,$r13 ; do the same again, maybe we got a carry last add
- lsrq 16,$r13
- and.d $r9,$r12
- add.d $r13,$r12
_no_fold:
cmpq 2,$r11
diff --git a/arch/cris/arch-v10/lib/checksumcopy.S b/arch/cris/arch-v10/lib/checksumcopy.S
index 35cbffb306f..540db8a5f84 100644
--- a/arch/cris/arch-v10/lib/checksumcopy.S
+++ b/arch/cris/arch-v10/lib/checksumcopy.S
@@ -1,4 +1,4 @@
-/* $Id: checksumcopy.S,v 1.1 2001/12/17 13:59:27 bjornw Exp $
+/*
* A fast checksum+copy routine using movem
* Copyright (c) 1998, 2001 Axis Communications AB
*
@@ -67,8 +67,6 @@ _mloop: movem [$r10+],$r9 ; read 10 longwords
ax
addq 0,$r13
- ax ; do it again, since we might have generated a carry
- addq 0,$r13
subq 10*4,$r12
bge _mloop
@@ -91,10 +89,6 @@ _word_loop:
lsrq 16,$r9 ; r0 = checksum >> 16
and.d 0xffff,$r13 ; checksum = checksum & 0xffff
add.d $r9,$r13 ; checksum += r0
- move.d $r13,$r9 ; do the same again, maybe we got a carry last add
- lsrq 16,$r9
- and.d 0xffff,$r13
- add.d $r9,$r13
_no_fold:
cmpq 2,$r12
diff --git a/arch/cris/arch-v10/lib/dram_init.S b/arch/cris/arch-v10/lib/dram_init.S
index 6a6bdfd6984..b9190ff7d0a 100644
--- a/arch/cris/arch-v10/lib/dram_init.S
+++ b/arch/cris/arch-v10/lib/dram_init.S
@@ -1,5 +1,4 @@
-/* $Id: dram_init.S,v 1.4 2003/09/22 09:21:59 starvik Exp $
- *
+/*
* DRAM/SDRAM initialization - alter with care
* This file is intended to be included from other assembler files
*
@@ -8,60 +7,7 @@
*
* Copyright (C) 2000, 2001 Axis Communications AB
*
- * Authors: Mikael Starvik (starvik@axis.com)
- *
- * $Log: dram_init.S,v $
- * Revision 1.4 2003/09/22 09:21:59 starvik
- * Decompresser is linked to 0x407xxxxx and sdram commands are at 0x000xxxxx
- * so we need to mask off 12 bits.
- *
- * Revision 1.3 2003/03/31 09:38:37 starvik
- * Corrected calculation of end of sdram init commands
- *
- * Revision 1.2 2002/11/19 13:33:29 starvik
- * Changes from Linux 2.4
- *
- * Revision 1.13 2002/10/30 07:42:28 starvik
- * Always read SDRAM command sequence from flash
- *
- * Revision 1.12 2002/08/09 11:37:37 orjanf
- * Added double initialization work-around for Samsung SDRAMs.
- *
- * Revision 1.11 2002/06/04 11:43:21 starvik
- * Check if mrs_data is specified in kernelconfig (necessary for MCM)
- *
- * Revision 1.10 2001/10/04 12:00:21 martinnn
- * Added missing underscores.
- *
- * Revision 1.9 2001/10/01 14:47:35 bjornw
- * Added register prefixes and removed underscores
- *
- * Revision 1.8 2001/05/15 07:12:45 hp
- * Copy warning from head.S about r8 and r9
- *
- * Revision 1.7 2001/04/18 12:05:39 bjornw
- * Fixed comments, and explicitly include config.h to be sure its there
- *
- * Revision 1.6 2001/04/10 06:20:16 starvik
- * Delay should be 200us, not 200ns
- *
- * Revision 1.5 2001/04/09 06:01:13 starvik
- * Added support for 100 MHz SDRAMs
- *
- * Revision 1.4 2001/03/26 14:24:01 bjornw
- * Namechange of some config options
- *
- * Revision 1.3 2001/03/23 08:29:41 starvik
- * Corrected calculation of mrs_data
- *
- * Revision 1.2 2001/02/08 15:20:00 starvik
- * Corrected SDRAM initialization
- * Should now be included as inline
- *
- * Revision 1.1 2001/01/29 13:08:02 starvik
- * Initial version
- * This file should be included from all assembler files that needs to
- * initialize DRAM/SDRAM.
+ * Authors: Mikael Starvik (starvik@axis.com)
*
*/
diff --git a/arch/cris/arch-v10/lib/memset.c b/arch/cris/arch-v10/lib/memset.c
index 42c1101043a..c94ea9b3ec2 100644
--- a/arch/cris/arch-v10/lib/memset.c
+++ b/arch/cris/arch-v10/lib/memset.c
@@ -1,252 +1,259 @@
-/*#************************************************************************#*/
-/*#-------------------------------------------------------------------------*/
-/*# */
-/*# FUNCTION NAME: memset() */
-/*# */
-/*# PARAMETERS: void* dst; Destination address. */
-/*# int c; Value of byte to write. */
-/*# int len; Number of bytes to write. */
-/*# */
-/*# RETURNS: dst. */
-/*# */
-/*# DESCRIPTION: Sets the memory dst of length len bytes to c, as standard. */
-/*# Framework taken from memcpy. This routine is */
-/*# very sensitive to compiler changes in register allocation. */
-/*# Should really be rewritten to avoid this problem. */
-/*# */
-/*#-------------------------------------------------------------------------*/
-/*# */
-/*# HISTORY */
-/*# */
-/*# DATE NAME CHANGES */
-/*# ---- ---- ------- */
-/*# 990713 HP Tired of watching this function (or */
-/*# really, the nonoptimized generic */
-/*# implementation) take up 90% of simulator */
-/*# output. Measurements needed. */
-/*# */
-/*#-------------------------------------------------------------------------*/
-
-#include <linux/types.h>
-
-/* No, there's no macro saying 12*4, since it is "hard" to get it into
- the asm in a good way. Thus better to expose the problem everywhere.
- */
-
-/* Assuming 1 cycle per dword written or read (ok, not really true), and
- one per instruction, then 43+3*(n/48-1) <= 24+24*(n/48-1)
- so n >= 45.7; n >= 0.9; we win on the first full 48-byte block to set. */
-
-#define ZERO_BLOCK_SIZE (1*12*4)
-
-void *memset(void *pdst,
- int c,
- size_t plen)
+/* A memset for CRIS.
+ Copyright (C) 1999-2005 Axis Communications.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Neither the name of Axis Communications nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS
+ COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE. */
+
+/* FIXME: This file should really only be used for reference, as the
+ result is somewhat depending on gcc generating what we expect rather
+ than what we describe. An assembly file should be used instead. */
+
+/* Note the multiple occurrence of the expression "12*4", including the
+ asm. It is hard to get it into the asm in a good way. Thus better to
+ expose the problem everywhere: no macro. */
+
+/* Assuming one cycle per dword written or read (ok, not really true; the
+ world is not ideal), and one cycle per instruction, then 43+3*(n/48-1)
+ <= 24+24*(n/48-1) so n >= 45.7; n >= 0.9; we win on the first full
+ 48-byte block to set. */
+
+#define MEMSET_BY_BLOCK_THRESHOLD (1 * 48)
+
+/* No name ambiguities in this file. */
+__asm__ (".syntax no_register_prefix");
+
+void *memset(void *pdst, int c, unsigned int plen)
{
- /* Ok. Now we want the parameters put in special registers.
- Make sure the compiler is able to make something useful of this. */
+ /* Now we want the parameters in special registers. Make sure the
+ compiler does something usable with this. */
register char *return_dst __asm__ ("r10") = pdst;
register int n __asm__ ("r12") = plen;
register int lc __asm__ ("r11") = c;
- /* Most apps use memset sanely. Only those memsetting about 3..4
- bytes or less get penalized compared to the generic implementation
- - and that's not really sane use. */
+ /* Most apps use memset sanely. Memsetting about 3..4 bytes or less get
+ penalized here compared to the generic implementation. */
- /* Ugh. This is fragile at best. Check with newer GCC releases, if
- they compile cascaded "x |= x << 8" sanely! */
- __asm__("movu.b %0,$r13\n\t"
- "lslq 8,$r13\n\t"
- "move.b %0,$r13\n\t"
- "move.d $r13,%0\n\t"
- "lslq 16,$r13\n\t"
- "or.d $r13,%0"
- : "=r" (lc) : "0" (lc) : "r13");
+ /* This is fragile performancewise at best. Check with newer GCC
+ releases, if they compile cascaded "x |= x << 8" to sane code. */
+ __asm__("movu.b %0,r13 \n\
+ lslq 8,r13 \n\
+ move.b %0,r13 \n\
+ move.d r13,%0 \n\
+ lslq 16,r13 \n\
+ or.d r13,%0"
+ : "=r" (lc) /* Inputs. */
+ : "0" (lc) /* Outputs. */
+ : "r13"); /* Trash. */
{
register char *dst __asm__ ("r13") = pdst;
- /* This is NONPORTABLE, but since this whole routine is */
- /* grossly nonportable that doesn't matter. */
+ if (((unsigned long) pdst & 3) != 0
+ /* Oops! n = 0 must be a valid call, regardless of alignment. */
+ && n >= 3)
+ {
+ if ((unsigned long) dst & 1)
+ {
+ *dst = (char) lc;
+ n--;
+ dst++;
+ }
- if (((unsigned long) pdst & 3) != 0
- /* Oops! n=0 must be a legal call, regardless of alignment. */
- && n >= 3)
- {
- if ((unsigned long)dst & 1)
- {
- *dst = (char) lc;
- n--;
- dst++;
- }
-
- if ((unsigned long)dst & 2)
- {
- *(short *)dst = lc;
- n -= 2;
- dst += 2;
- }
- }
+ if ((unsigned long) dst & 2)
+ {
+ *(short *) dst = lc;
+ n -= 2;
+ dst += 2;
+ }
+ }
- /* Now the fun part. For the threshold value of this, check the equation
- above. */
- /* Decide which copying method to use. */
- if (n >= ZERO_BLOCK_SIZE)
- {
- /* For large copies we use 'movem' */
-
- /* It is not optimal to tell the compiler about clobbering any
- registers; that will move the saving/restoring of those registers
- to the function prologue/epilogue, and make non-movem sizes
- suboptimal.
-
- This method is not foolproof; it assumes that the "asm reg"
- declarations at the beginning of the function really are used
- here (beware: they may be moved to temporary registers).
- This way, we do not have to save/move the registers around into
- temporaries; we can safely use them straight away.
-
- If you want to check that the allocation was right; then
- check the equalities in the first comment. It should say
- "r13=r13, r12=r12, r11=r11" */
- __asm__ volatile ("\n\
- ;; Check that the following is true (same register names on \n\
- ;; both sides of equal sign, as in r8=r8): \n\
- ;; %0=r13, %1=r12, %4=r11 \n\
- ;; \n\
- ;; Save the registers we'll clobber in the movem process \n\
- ;; on the stack. Don't mention them to gcc, it will only be \n\
- ;; upset. \n\
- subq 11*4,$sp \n\
- movem $r10,[$sp] \n\
+ /* Decide which setting method to use. */
+ if (n >= MEMSET_BY_BLOCK_THRESHOLD)
+ {
+ /* It is not optimal to tell the compiler about clobbering any
+ registers; that will move the saving/restoring of those registers
+ to the function prologue/epilogue, and make non-block sizes
+ suboptimal. */
+ __asm__ volatile
+ ("\
+ ;; GCC does promise correct register allocations, but let's \n\
+ ;; make sure it keeps its promises. \n\
+ .ifnc %0-%1-%4,$r13-$r12-$r11 \n\
+ .error \"GCC reg alloc bug: %0-%1-%4 != $r13-$r12-$r11\" \n\
+ .endif \n\
+ \n\
+ ;; Save the registers we'll clobber in the movem process \n\
+ ;; on the stack. Don't mention them to gcc, it will only be \n\
+ ;; upset. \n\
+ subq 11*4,sp \n\
+ movem r10,[sp] \n\
\n\
- move.d $r11,$r0 \n\
- move.d $r11,$r1 \n\
- move.d $r11,$r2 \n\
- move.d $r11,$r3 \n\
- move.d $r11,$r4 \n\
- move.d $r11,$r5 \n\
- move.d $r11,$r6 \n\
- move.d $r11,$r7 \n\
- move.d $r11,$r8 \n\
- move.d $r11,$r9 \n\
- move.d $r11,$r10 \n\
+ move.d r11,r0 \n\
+ move.d r11,r1 \n\
+ move.d r11,r2 \n\
+ move.d r11,r3 \n\
+ move.d r11,r4 \n\
+ move.d r11,r5 \n\
+ move.d r11,r6 \n\
+ move.d r11,r7 \n\
+ move.d r11,r8 \n\
+ move.d r11,r9 \n\
+ move.d r11,r10 \n\
\n\
- ;; Now we've got this: \n\
- ;; r13 - dst \n\
- ;; r12 - n \n\
+ ;; Now we've got this: \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
\n\
- ;; Update n for the first loop \n\
- subq 12*4,$r12 \n\
+ ;; Update n for the first loop \n\
+ subq 12*4,r12 \n\
0: \n\
- subq 12*4,$r12 \n\
- bge 0b \n\
- movem $r11,[$r13+] \n\
+"
+#ifdef __arch_common_v10_v32
+ /* Cater to branch offset difference between v32 and v10. We
+ assume the branch below has an 8-bit offset. */
+" setf\n"
+#endif
+" subq 12*4,r12 \n\
+ bge 0b \n\
+ movem r11,[r13+] \n\
\n\
- addq 12*4,$r12 ;; compensate for last loop underflowing n \n\
+ ;; Compensate for last loop underflowing n. \n\
+ addq 12*4,r12 \n\
\n\
- ;; Restore registers from stack \n\
- movem [$sp+],$r10"
+ ;; Restore registers from stack. \n\
+ movem [sp+],r10"
- /* Outputs */ : "=r" (dst), "=r" (n)
- /* Inputs */ : "0" (dst), "1" (n), "r" (lc));
+ /* Outputs. */
+ : "=r" (dst), "=r" (n)
- }
+ /* Inputs. */
+ : "0" (dst), "1" (n), "r" (lc));
+ }
+
+ /* An ad-hoc unroll, used for 4*12-1..16 bytes. */
+ while (n >= 16)
+ {
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ n -= 16;
+ }
- /* Either we directly starts copying, using dword copying
- in a loop, or we copy as much as possible with 'movem'
- and then the last block (<44 bytes) is copied here.
- This will work since 'movem' will have updated src,dst,n. */
-
- while ( n >= 16 )
- {
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- n -= 16;
- }
-
- /* A switch() is definitely the fastest although it takes a LOT of code.
- * Particularly if you inline code this.
- */
switch (n)
- {
+ {
case 0:
break;
+
case 1:
- *(char*)dst = (char) lc;
+ *dst = (char) lc;
break;
+
case 2:
- *(short*)dst = (short) lc;
+ *(short *) dst = (short) lc;
break;
+
case 3:
- *((short*)dst)++ = (short) lc;
- *(char*)dst = (char) lc;
+ *(short *) dst = (short) lc; dst += 2;
+ *dst = (char) lc;
break;
+
case 4:
- *((long*)dst)++ = lc;
+ *(long *) dst = lc;
break;
+
case 5:
- *((long*)dst)++ = lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *dst = (char) lc;
break;
+
case 6:
- *((long*)dst)++ = lc;
- *(short*)dst = (short) lc;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc;
break;
+
case 7:
- *((long*)dst)++ = lc;
- *((short*)dst)++ = (short) lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc; dst += 2;
+ *dst = (char) lc;
break;
+
case 8:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc;
break;
+
case 9:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *dst = (char) lc;
break;
+
case 10:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *(short*)dst = (short) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc;
break;
+
case 11:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((short*)dst)++ = (short) lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc; dst += 2;
+ *dst = (char) lc;
break;
+
case 12:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc;
break;
+
case 13:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *dst = (char) lc;
break;
+
case 14:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *(short*)dst = (short) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc;
break;
+
case 15:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((short*)dst)++ = (short) lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc; dst += 2;
+ *dst = (char) lc;
break;
- }
+ }
}
- return return_dst; /* destination pointer. */
-} /* memset() */
+ return return_dst;
+}
diff --git a/arch/cris/arch-v10/lib/old_checksum.c b/arch/cris/arch-v10/lib/old_checksum.c
index 497634a6482..1734b467efa 100644
--- a/arch/cris/arch-v10/lib/old_checksum.c
+++ b/arch/cris/arch-v10/lib/old_checksum.c
@@ -1,5 +1,4 @@
-/* $Id: old_checksum.c,v 1.3 2003/10/27 08:04:32 starvik Exp $
- *
+/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
diff --git a/arch/cris/arch-v10/mm/fault.c b/arch/cris/arch-v10/mm/fault.c
index fe2615022b9..65504fd8092 100644
--- a/arch/cris/arch-v10/mm/fault.c
+++ b/arch/cris/arch-v10/mm/fault.c
@@ -4,10 +4,10 @@
* Low level bus fault handler
*
*
- * Copyright (C) 2000, 2001 Axis Communications AB
+ * Copyright (C) 2000-2007 Axis Communications AB
+ *
+ * Authors: Bjorn Wesen
*
- * Authors: Bjorn Wesen
- *
*/
#include <linux/mm.h>
@@ -60,7 +60,7 @@ handle_mmu_bus_fault(struct pt_regs *regs)
#ifdef DEBUG
page_id = IO_EXTRACT(R_MMU_CAUSE, page_id, cause);
acc = IO_EXTRACT(R_MMU_CAUSE, acc_excp, cause);
- inv = IO_EXTRACT(R_MMU_CAUSE, inv_excp, cause);
+ inv = IO_EXTRACT(R_MMU_CAUSE, inv_excp, cause);
index = IO_EXTRACT(R_TLB_SELECT, index, select);
#endif
miss = IO_EXTRACT(R_MMU_CAUSE, miss_excp, cause);
@@ -84,12 +84,13 @@ handle_mmu_bus_fault(struct pt_regs *regs)
local_irq_disable();
pmd = (pmd_t *)(pgd + pgd_index(address));
if (pmd_none(*pmd))
- return;
+ goto exit;
pte = *pte_offset_kernel(pmd, address);
if (!pte_present(pte))
- return;
+ goto exit;
*R_TLB_SELECT = select;
*R_TLB_HI = cause;
*R_TLB_LO = pte_val(pte);
+exit:
local_irq_restore(flags);
}
diff --git a/arch/cris/arch-v10/mm/tlb.c b/arch/cris/arch-v10/mm/tlb.c
index 7d9fec88dee..6baf5bd209e 100644
--- a/arch/cris/arch-v10/mm/tlb.c
+++ b/arch/cris/arch-v10/mm/tlb.c
@@ -4,8 +4,8 @@
* Low level TLB handling
*
*
- * Copyright (C) 2000-2002 Axis Communications AB
- *
+ * Copyright (C) 2000-2007 Axis Communications AB
+ *
* Authors: Bjorn Wesen (bjornw@axis.com)
*
*/
@@ -39,7 +39,7 @@ flush_tlb_all(void)
unsigned long flags;
/* the vpn of i & 0xf is so we dont write similar TLB entries
- * in the same 4-way entry group. details..
+ * in the same 4-way entry group. details...
*/
local_irq_save(flags);
@@ -47,7 +47,7 @@ flush_tlb_all(void)
*R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
-
+
*R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
IO_STATE(R_TLB_LO, valid, no ) |
IO_STATE(R_TLB_LO, kernel,no ) |
@@ -71,10 +71,10 @@ flush_tlb_mm(struct mm_struct *mm)
if(page_id == NO_CONTEXT)
return;
-
+
/* mark the TLB entries that match the page_id as invalid.
* here we could also check the _PAGE_GLOBAL bit and NOT flush
- * global pages. is it worth the extra I/O ?
+ * global pages. is it worth the extra I/O ?
*/
local_irq_save(flags);
@@ -83,7 +83,7 @@ flush_tlb_mm(struct mm_struct *mm)
if (IO_EXTRACT(R_TLB_HI, page_id, *R_TLB_HI) == page_id) {
*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
-
+
*R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
IO_STATE(R_TLB_LO, valid, no ) |
IO_STATE(R_TLB_LO, kernel,no ) |
@@ -96,9 +96,7 @@ flush_tlb_mm(struct mm_struct *mm)
/* invalidate a single page */
-void
-flush_tlb_page(struct vm_area_struct *vma,
- unsigned long addr)
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
{
struct mm_struct *mm = vma->vm_mm;
int page_id = mm->context.page_id;
@@ -113,7 +111,7 @@ flush_tlb_page(struct vm_area_struct *vma,
addr &= PAGE_MASK; /* perhaps not necessary */
/* invalidate those TLB entries that match both the mm context
- * and the virtual address requested
+ * and the virtual address requested
*/
local_irq_save(flags);
@@ -125,7 +123,7 @@ flush_tlb_page(struct vm_area_struct *vma,
(tlb_hi & PAGE_MASK) == addr) {
*R_TLB_HI = IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
addr; /* same addr as before works. */
-
+
*R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) |
IO_STATE(R_TLB_LO, valid, no ) |
IO_STATE(R_TLB_LO, kernel,no ) |
@@ -144,7 +142,7 @@ dump_tlb_all(void)
{
int i;
unsigned long flags;
-
+
printk("TLB dump. LO is: pfn | reserved | global | valid | kernel | we |\n");
local_save_flags(flags);
@@ -172,27 +170,29 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
/* called in schedule() just before actually doing the switch_to */
-void
-switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk)
+void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ struct task_struct *tsk)
{
- /* make sure we have a context */
+ if (prev != next) {
+ /* make sure we have a context */
+ get_mmu_context(next);
- get_mmu_context(next);
+ /* remember the pgd for the fault handlers
+ * this is similar to the pgd register in some other CPU's.
+ * we need our own copy of it because current and active_mm
+ * might be invalid at points where we still need to derefer
+ * the pgd.
+ */
- /* remember the pgd for the fault handlers
- * this is similar to the pgd register in some other CPU's.
- * we need our own copy of it because current and active_mm
- * might be invalid at points where we still need to derefer
- * the pgd.
- */
+ per_cpu(current_pgd, smp_processor_id()) = next->pgd;
- per_cpu(current_pgd, smp_processor_id()) = next->pgd;
+ /* switch context in the MMU */
- /* switch context in the MMU */
-
- D(printk("switching mmu_context to %d (%p)\n", next->context, next));
+ D(printk(KERN_DEBUG "switching mmu_context to %d (%p)\n",
+ next->context, next));
- *R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT, page_id, next->context.page_id);
+ *R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT,
+ page_id, next->context.page_id);
+ }
}
diff --git a/arch/cris/arch-v32/Kconfig b/arch/cris/arch-v32/Kconfig
index 4f79d8ed3e1..005ed2b3f7f 100644
--- a/arch/cris/arch-v32/Kconfig
+++ b/arch/cris/arch-v32/Kconfig
@@ -1,25 +1,73 @@
+if ETRAX_ARCH_V32
+
+source arch/cris/arch-v32/mach-fs/Kconfig
+source arch/cris/arch-v32/mach-a3/Kconfig
+
+source drivers/cpufreq/Kconfig
+
config ETRAX_DRAM_VIRTUAL_BASE
hex
depends on ETRAX_ARCH_V32
default "c0000000"
-config ETRAX_LED1G
- string "First green LED bit"
+choice
+ prompt "Nbr of Ethernet LED groups"
depends on ETRAX_ARCH_V32
+ default ETRAX_NBR_LED_GRP_ONE
+ help
+ Select how many Ethernet LED groups that can be used. Usually one per Ethernet
+ interface is a good choice.
+
+config ETRAX_NBR_LED_GRP_ZERO
+ bool "Use zero LED groups"
+ help
+ Select this if you do not want any Ethernet LEDs.
+
+config ETRAX_NBR_LED_GRP_ONE
+ bool "Use one LED group"
+ help
+ Select this if you want one Ethernet LED group. This LED group
+ can be used for one or more Ethernet interfaces. However, it is
+ recomended that each Ethernet interface use a dedicated LED group.
+
+config ETRAX_NBR_LED_GRP_TWO
+ bool "Use two LED groups"
+ help
+ Select this if you want two Ethernet LED groups. This is the
+ best choice if you have more than one Ethernet interface and
+ would like to have separate LEDs for the interfaces.
+
+endchoice
+
+config ETRAX_LED_G_NET0
+ string "Ethernet LED group 0 green LED bit"
+ depends on ETRAX_ARCH_V32 && (ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO)
default "PA3"
help
- Bit to use for the first green LED (network LED).
- Most Axis products use bit A3 here.
+ Bit to use for the green LED in Ethernet LED group 0.
-config ETRAX_LED1R
- string "First red LED bit"
- depends on ETRAX_ARCH_V32
+config ETRAX_LED_R_NET0
+ string "Ethernet LED group 0 red LED bit"
+ depends on ETRAX_ARCH_V32 && (ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO)
default "PA4"
help
- Bit to use for the first red LED (network LED).
- Most Axis products use bit A4 here.
+ Bit to use for the red LED in Ethernet LED group 0.
-config ETRAX_LED2G
+config ETRAX_LED_G_NET1
+ string "Ethernet group 1 green LED bit"
+ depends on ETRAX_ARCH_V32 && ETRAX_NBR_LED_GRP_TWO
+ default ""
+ help
+ Bit to use for the green LED in Ethernet LED group 1.
+
+config ETRAX_LED_R_NET1
+ string "Ethernet group 1 red LED bit"
+ depends on ETRAX_ARCH_V32 && ETRAX_NBR_LED_GRP_TWO
+ default ""
+ help
+ Bit to use for the red LED in Ethernet LED group 1.
+
+config ETRAX_V32_LED2G
string "Second green LED bit"
depends on ETRAX_ARCH_V32
default "PA5"
@@ -27,7 +75,7 @@ config ETRAX_LED2G
Bit to use for the first green LED (status LED).
Most Axis products use bit A5 here.
-config ETRAX_LED2R
+config ETRAX_V32_LED2R
string "Second red LED bit"
depends on ETRAX_ARCH_V32
default "PA6"
@@ -35,7 +83,7 @@ config ETRAX_LED2R
Bit to use for the first red LED (network LED).
Most Axis products use bit A6 here.
-config ETRAX_LED3G
+config ETRAX_V32_LED3G
string "Third green LED bit"
depends on ETRAX_ARCH_V32
default "PA7"
@@ -43,7 +91,7 @@ config ETRAX_LED3G
Bit to use for the first green LED (drive/power LED).
Most Axis products use bit A7 here.
-config ETRAX_LED3R
+config ETRAX_V32_LED3R
string "Third red LED bit"
depends on ETRAX_ARCH_V32
default "PA7"
@@ -52,39 +100,6 @@ config ETRAX_LED3R
Most Axis products use bit A7 here.
choice
- prompt "Product debug-port"
- depends on ETRAX_ARCH_V32
- default ETRAX_DEBUG_PORT0
-
-config ETRAX_DEBUG_PORT0
- bool "Serial-0"
- help
- Choose a serial port for the ETRAX debug console. Default to
- port 0.
-
-config ETRAX_DEBUG_PORT1
- bool "Serial-1"
- help
- Use serial port 1 for the console.
-
-config ETRAX_DEBUG_PORT2
- bool "Serial-2"
- help
- Use serial port 2 for the console.
-
-config ETRAX_DEBUG_PORT3
- bool "Serial-3"
- help
- Use serial port 3 for the console.
-
-config ETRAX_DEBUG_PORT_NULL
- bool "disabled"
- help
- Disable serial-port debugging.
-
-endchoice
-
-choice
prompt "Kernel GDB port"
depends on ETRAX_KGDB
default ETRAX_KGDB_PORT0
@@ -93,25 +108,11 @@ choice
not be enabled under Drivers for built-in interfaces (as it has its
own initialization code) and should not be the same as the debug port.
-config ETRAX_KGDB_PORT0
- bool "Serial-0"
- help
- Use serial port 0 for kernel debugging.
-
-config ETRAX_KGDB_PORT1
- bool "Serial-1"
+config ETRAX_KGDB_PORT4
+ bool "Serial-4"
+ depends on ETRAX_SERIAL_PORTS = 5
help
- Use serial port 1 for kernel debugging.
-
-config ETRAX_KGDB_PORT2
- bool "Serial-2"
- help
- Use serial port 2 for kernel debugging.
-
-config ETRAX_KGDB_PORT3
- bool "Serial-3"
- help
- Use serial port 3 for kernel debugging.
+ Use serial port 4 for kernel debugging.
endchoice
@@ -294,3 +295,5 @@ config ETRAX_DEF_GIO_PE_OUT
help
Configures the initial data for the general port E bits. Most
products should use 00000 here.
+
+endif
diff --git a/arch/cris/arch-v32/boot/Makefile b/arch/cris/arch-v32/boot/Makefile
index 26f293ab961..3f91349c5f1 100644
--- a/arch/cris/arch-v32/boot/Makefile
+++ b/arch/cris/arch-v32/boot/Makefile
@@ -1,14 +1,21 @@
#
# arch/cris/arch-v32/boot/Makefile
#
-target = $(target_boot_dir)
-src = $(src_boot_dir)
-zImage: compressed/vmlinuz
+OBJCOPY = objcopy-cris
+OBJCOPYFLAGS = -O binary -R .note -R .comment
-compressed/vmlinuz: $(objtree)/vmlinux
- @$(MAKE) -f $(src)/compressed/Makefile $(objtree)/vmlinuz
+subdir- := compressed rescue
+targets := Image
-clean:
- rm -f zImage tools/build compressed/vmlinux.out
- @$(MAKE) -f $(src)/compressed/Makefile clean
+$(obj)/Image: vmlinux FORCE
+ $(call if_changed,objcopy)
+ @echo ' Kernel: $@ is ready'
+
+$(obj)/compressed/vmlinux: $(obj)/Image FORCE
+ $(Q)$(MAKE) $(build)=$(obj)/compressed $@
+ $(Q)$(MAKE) $(build)=$(obj)/rescue $(obj)/rescue/rescue.bin
+
+$(obj)/zImage: $(obj)/compressed/vmlinux
+ @cp $< $@
+ @echo ' Kernel: $@ is ready'
diff --git a/arch/cris/arch-v32/boot/compressed/Makefile b/arch/cris/arch-v32/boot/compressed/Makefile
index 609692f9d5e..2c8c2c3039c 100644
--- a/arch/cris/arch-v32/boot/compressed/Makefile
+++ b/arch/cris/arch-v32/boot/compressed/Makefile
@@ -1,41 +1,30 @@
#
-# lx25/arch/cris/arch-v32/boot/compressed/Makefile
+# arch/cris/arch-v32/boot/compressed/Makefile
#
-# create a compressed vmlinux image from the original vmlinux files and romfs
-#
-
-target = $(target_compressed_dir)
-src = $(src_compressed_dir)
CC = gcc-cris -mlinux -march=v32 $(LINUXINCLUDE)
-CFLAGS = -O2
+asflags-y += -I $(srctree)/include/asm/mach/ -I $(srctree)/include/asm/arch
+ccflags-y += -O2 -I $(srctree)/include/asm/mach/ -I $(srctree)/include/asm/arch
LD = gcc-cris -mlinux -march=v32 -nostdlib
+ldflags-y += -T $(obj)/decompress.ld
+obj-y = head.o misc.o
+OBJECTS = $(obj)/head.o $(obj)/misc.o
OBJCOPY = objcopy-cris
OBJCOPYFLAGS = -O binary --remove-section=.bss
-OBJECTS = $(target)/head.o $(target)/misc.o
-
-# files to compress
-SYSTEM = $(objtree)/vmlinux.bin
-
-all: vmlinuz
-
-$(target)/decompress.bin: $(OBJECTS)
- $(LD) -T $(src)/decompress.ld -o $(target)/decompress.o $(OBJECTS)
- $(OBJCOPY) $(OBJCOPYFLAGS) $(target)/decompress.o $(target)/decompress.bin
-$(objtree)/vmlinuz: $(target) piggy.img $(target)/decompress.bin
- cat $(target)/decompress.bin piggy.img > $(objtree)/vmlinuz
- rm -f piggy.img
- cp $(objtree)/vmlinuz $(src)
+quiet_cmd_image = BUILD $@
+cmd_image = cat $(obj)/decompress.bin $(obj)/piggy.gz > $@
-$(target)/head.o: $(src)/head.S
- $(CC) -D__ASSEMBLY__ -c $< -o $@
+targets := vmlinux piggy.gz decompress.o decompress.bin
-# gzip the kernel image
+$(obj)/decompress.o: $(OBJECTS) FORCE
+ $(call if_changed,ld)
-piggy.img: $(SYSTEM)
- cat $(SYSTEM) | gzip -f -9 > piggy.img
+$(obj)/decompress.bin: $(obj)/decompress.o FORCE
+ $(call if_changed,objcopy)
-clean:
- rm -f piggy.img $(objtree)/vmlinuz vmlinuz.o decompress.o decompress.bin $(OBJECTS)
+$(obj)/vmlinux: $(obj)/piggy.gz $(obj)/decompress.bin FORCE
+ $(call if_changed,image)
+$(obj)/piggy.gz: $(obj)/../Image FORCE
+ $(call if_changed,gzip)
diff --git a/arch/cris/arch-v32/boot/compressed/README b/arch/cris/arch-v32/boot/compressed/README
index e33691d15c5..182c5d75784 100644
--- a/arch/cris/arch-v32/boot/compressed/README
+++ b/arch/cris/arch-v32/boot/compressed/README
@@ -1,6 +1,5 @@
Creation of the self-extracting compressed kernel image (vmlinuz)
-----------------------------------------------------------------
-$Id: README,v 1.1 2003/08/21 09:37:03 johana Exp $
This can be slightly confusing because it's a process with many steps.
diff --git a/arch/cris/arch-v32/boot/compressed/head.S b/arch/cris/arch-v32/boot/compressed/head.S
index 34cea10a899..f86208caf32 100644
--- a/arch/cris/arch-v32/boot/compressed/head.S
+++ b/arch/cris/arch-v32/boot/compressed/head.S
@@ -2,13 +2,12 @@
* Code that sets up the DRAM registers, calls the
* decompressor to unpack the piggybacked kernel, and jumps.
*
- * Copyright (C) 1999 - 2003, Axis Communications AB
+ * Copyright (C) 1999 - 2006, Axis Communications AB
*/
#define ASSEMBLER_MACROS_ONLY
-#include <asm/arch/hwregs/asm/reg_map_asm.h>
-#include <asm/arch/hwregs/asm/gio_defs_asm.h>
-#include <asm/arch/hwregs/asm/config_defs_asm.h>
+#include <hwregs/asm/reg_map_asm.h>
+#include <asm/arch/mach/startup.inc>
#define RAM_INIT_MAGIC 0x56902387
#define COMMAND_LINE_MAGIC 0x87109563
@@ -22,114 +21,49 @@ start:
di
;; Start clocks for used blocks.
- move.d REG_ADDR(config, regi_config, rw_clk_ctrl), $r1
- move.d [$r1], $r0
- or.d REG_STATE(config, rw_clk_ctrl, cpu, yes) | \
- REG_STATE(config, rw_clk_ctrl, bif, yes) | \
- REG_STATE(config, rw_clk_ctrl, fix_io, yes), $r0
- move.d $r0, [$r1]
-
- ;; If booting from NAND flash we first have to copy some
- ;; data from NAND flash to internal RAM to get the code
- ;; that initializes the SDRAM. Lets copy 20 KB. This
- ;; code executes at 0x38010000 if booting from NAND and
- ;; we are guaranted that at least 0x200 bytes are good so
- ;; lets start from there. The first 8192 bytes in the nand
- ;; flash is spliced with zeroes and is thus 16384 bytes.
- move.d 0x38010200, $r10
- move.d 0x14200, $r11 ; Start offset in NAND flash 0x10200 + 16384
- move.d 0x5000, $r12 ; Length of copy
-
- ;; Before this code the tools add a partitiontable so the PC
- ;; has an offset from the linked address.
-offset1:
- lapcq ., $r13 ; get PC
- add.d first_copy_complete-offset1, $r13
-
-#include "../../lib/nand_init.S"
-
-first_copy_complete:
- ;; Initialze the DRAM registers.
+ START_CLOCKS
+
+ ;; Initialize the DRAM registers.
cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized?
beq dram_init_finished
nop
-#include "../../lib/dram_init.S"
+#include "../../mach/dram_init.S"
dram_init_finished:
- lapcq ., $r13 ; get PC
- add.d second_copy_complete-dram_init_finished, $r13
-
- move.d REG_ADDR(config, regi_config, r_bootsel), $r0
- move.d [$r0], $r0
- and.d REG_MASK(config, r_bootsel, boot_mode), $r0
- cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0
- bne second_copy_complete ; No NAND boot
- nop
-
- ;; Copy 2MB from NAND flash to SDRAM (at 2-4MB into the SDRAM)
- move.d 0x40204000, $r10
- move.d 0x8000, $r11
- move.d 0x200000, $r12
- ba copy_nand_to_ram
- nop
-second_copy_complete:
-
- ;; Initiate the PA port.
- move.d CONFIG_ETRAX_DEF_GIO_PA_OUT, $r0
- move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r1
- move.d $r0, [$r1]
-
- move.d CONFIG_ETRAX_DEF_GIO_PA_OE, $r0
- move.d REG_ADDR(gio, regi_gio, rw_pa_oe), $r1
- move.d $r0, [$r1]
+ GIO_INIT
;; Setup the stack to a suitably high address.
;; We assume 8 MB is the minimum DRAM and put
;; the SP at the top for now.
move.d 0x40800000, $sp
- ;; Figure out where the compressed piggyback image is
- ;; in the flash (since we wont try to copy it to DRAM
- ;; before unpacking). It is at _edata, but in flash.
+ ;; Figure out where the compressed piggyback image is.
+ ;; It is either in [NOR] flash (we don't want to copy it
+ ;; to DRAM before unpacking), or copied to DRAM
+ ;; by the [NAND] flash boot loader.
+ ;; The piggyback image is at _edata, but relative to where the
+ ;; image is actually located in memory, not where it is linked
+ ;; (the decompressor is linked at 0x40700000+ and runs there).
;; Use (_edata - herami) as offset to the current PC.
- move.d REG_ADDR(config, regi_config, r_bootsel), $r0
- move.d [$r0], $r0
- and.d REG_MASK(config, r_bootsel, boot_mode), $r0
- cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0
- beq hereami2
- nop
hereami:
lapcq ., $r5 ; get PC
and.d 0x7fffffff, $r5 ; strip any non-cache bit
- move.d $r5, $r0 ; save for later - flash address of 'herami'
+ move.d $r5, $r0 ; source address of 'herami'
add.d _edata, $r5
sub.d hereami, $r5 ; r5 = flash address of '_edata'
move.d hereami, $r1 ; destination
- ba 2f
- nop
-hereami2:
- lapcq ., $r5 ; get PC
- and.d 0x00ffffff, $r5 ; strip any non-cache bit
- move.d $r5, $r6
- or.d 0x40200000, $r6
- move.d $r6, $r0 ; save for later - flash address of 'herami'
- add.d _edata, $r5
- sub.d hereami2, $r5 ; r5 = flash address of '_edata'
- add.d 0x40200000, $r5
- move.d hereami2, $r1 ; destination
-2:
+
;; Copy text+data to DRAM
move.d _edata, $r2 ; end destination
-1: move.w [$r0+], $r3
- move.w $r3, [$r1+]
- cmp.d $r2, $r1
+1: move.w [$r0+], $r3 ; from herami+ source
+ move.w $r3, [$r1+] ; to hereami+ destination (linked address)
+ cmp.d $r2, $r1 ; finish when destination == _edata
bcs 1b
nop
-
move.d input_data, $r0 ; for the decompressor
move.d $r5, [$r0] ; for the decompressor
@@ -144,16 +78,24 @@ hereami2:
nop
;; Save command line magic and address.
- move.d _cmd_line_magic, $r12
- move.d $r10, [$r12]
- move.d _cmd_line_addr, $r12
- move.d $r11, [$r12]
+ move.d _cmd_line_magic, $r0
+ move.d $r10, [$r0]
+ move.d _cmd_line_addr, $r0
+ move.d $r11, [$r0]
+
+ ;; Save boot source indicator
+ move.d _boot_source, $r0
+ move.d $r12, [$r0]
;; Do the decompression and save compressed size in _inptr
jsr decompress_kernel
nop
+ ;; Restore boot source indicator
+ move.d _boot_source, $r12
+ move.d [$r12], $r12
+
;; Restore command line magic and address.
move.d _cmd_line_magic, $r10
move.d [$r10], $r10
@@ -166,11 +108,10 @@ hereami2:
move.d [$r0], $r9 ; flash address of compressed kernel
move.d inptr, $r0
add.d [$r0], $r9 ; size of compressed kernel
- cmp.d 0x40200000, $r9
- blo enter_kernel
- nop
- sub.d 0x40200000, $r9
- add.d 0x4000, $r9
+ cmp.d 0x40000000, $r9 ; image in DRAM ?
+ blo enter_kernel ; no, must be [NOR] flash, jump
+ nop ; delay slot
+ and.d 0x001fffff, $r9 ; assume compressed kernel was < 2M
enter_kernel:
;; Enter the decompressed kernel
@@ -186,7 +127,7 @@ _cmd_line_magic:
.dword 0
_cmd_line_addr:
.dword 0
-is_nand_boot:
- .dword 0
+_boot_source:
+ .dword 0
-#include "../../lib/hw_settings.S"
+#include "../../mach/hw_settings.S"
diff --git a/arch/cris/arch-v32/boot/compressed/misc.c b/arch/cris/arch-v32/boot/compressed/misc.c
index 0169ba1ca9c..55b2695c5d7 100644
--- a/arch/cris/arch-v32/boot/compressed/misc.c
+++ b/arch/cris/arch-v32/boot/compressed/misc.c
@@ -1,8 +1,6 @@
/*
* misc.c
*
- * $Id: misc.c,v 1.8 2005/04/24 18:34:29 starvik Exp $
- *
* This is a collection of several routines from gzip-1.0.3
* adapted for Linux.
*
@@ -22,9 +20,13 @@
#include <linux/types.h>
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/reg_map.h>
-#include <asm/arch/hwregs/ser_defs.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/ser_defs.h>
+#include <hwregs/pinmux_defs.h>
+#ifdef CONFIG_CRIS_MACH_ARTPEC3
+#include <hwregs/clkgen_defs.h>
+#endif
/*
* gzip declarations
@@ -85,7 +87,6 @@ static unsigned outcnt = 0; /* bytes in output buffer */
# define Tracecv(c,x)
#endif
-static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
static void gzip_mark(void **);
@@ -186,6 +187,8 @@ memset(void* s, int c, size_t n)
char *ss = (char*)s;
for (i=0;i<n;i++) ss[i] = c;
+
+ return s;
}
void*
@@ -196,6 +199,8 @@ memcpy(void* __dest, __const void* __src,
char *d = (char *)__dest, *s = (char *)__src;
for (i=0;i<__n;i++) d[i] = s[i];
+
+ return __dest;
}
/* ===========================================================================
@@ -225,15 +230,15 @@ flush_window()
static void
error(char *x)
{
- puts("\n\n");
+ puts("\r\n\n");
puts(x);
- puts("\n\n -- System halted\n");
+ puts("\r\n\n -- System halted\n");
while(1); /* Halt */
}
void
-setup_normal_output_buffer()
+setup_normal_output_buffer(void)
{
output_data = (char *)KERNEL_LOAD_ADR;
}
@@ -262,15 +267,17 @@ serial_setup(reg_scope_instances regi_ser)
rec_baud = REG_RD(ser, regi_ser, rw_rec_baud_div);
tr_ctrl.stop_bits = 1; /* 2 stop bits. */
+ tr_ctrl.en = 1; /* enable transmitter */
+ rec_ctrl.en = 1; /* enabler receiver */
/*
- * The baudrate setup is a bit fishy, but in the end the transceiver is
- * set to 4800 and the receiver to 115200. The magic value is
- * 29.493 MHz.
+ * The baudrate setup used to be a bit fishy, but now transmitter and
+ * receiver are both set to the intended baud rate, 115200.
+ * The magic value is 29.493 MHz.
*/
tr_ctrl.base_freq = regk_ser_f29_493;
rec_ctrl.base_freq = regk_ser_f29_493;
- tr_baud.div = (29493000 / 8) / 4800;
+ tr_baud.div = (29493000 / 8) / 115200;
rec_baud.div = (29493000 / 8) / 115200;
REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
@@ -280,25 +287,52 @@ serial_setup(reg_scope_instances regi_ser)
}
void
-decompress_kernel()
+decompress_kernel(void)
{
char revision;
- /* input_data is set in head.S */
- inbuf = input_data;
+#if defined(CONFIG_ETRAX_DEBUG_PORT1) || \
+ defined(CONFIG_ETRAX_DEBUG_PORT2) || \
+ defined(CONFIG_ETRAX_DEBUG_PORT3)
+ reg_pinmux_rw_hwprot hwprot;
+
+#ifdef CONFIG_CRIS_MACH_ARTPEC3
+ reg_clkgen_rw_clk_ctrl clk_ctrl;
+
+ /* Enable corresponding clock region when serial 1..3 selected */
+
+ clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
+ clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
+ REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
+#endif
+
+ /* pinmux setup for ports 1..3 */
+ hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
+#endif
#ifdef CONFIG_ETRAX_DEBUG_PORT0
serial_setup(regi_ser0);
#endif
#ifdef CONFIG_ETRAX_DEBUG_PORT1
+ hwprot.ser1 = regk_pinmux_yes;
serial_setup(regi_ser1);
#endif
#ifdef CONFIG_ETRAX_DEBUG_PORT2
+ hwprot.ser2 = regk_pinmux_yes;
serial_setup(regi_ser2);
#endif
#ifdef CONFIG_ETRAX_DEBUG_PORT3
+ hwprot.ser3 = regk_pinmux_yes;
serial_setup(regi_ser3);
#endif
+#if defined(CONFIG_ETRAX_DEBUG_PORT1) || \
+ defined(CONFIG_ETRAX_DEBUG_PORT2) || \
+ defined(CONFIG_ETRAX_DEBUG_PORT3)
+ REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
+#endif
+
+ /* input_data is set in head.S */
+ inbuf = input_data;
setup_normal_output_buffer();
@@ -307,11 +341,11 @@ decompress_kernel()
__asm__ volatile ("move $vr,%0" : "=rm" (revision));
if (revision < 32)
{
- puts("You need an ETRAX FS to run Linux 2.6/crisv32.\n");
+ puts("You need an ETRAX FS to run Linux 2.6/crisv32.\r\n");
while(1);
}
- puts("Uncompressing Linux...\n");
+ puts("Uncompressing Linux...\r\n");
gunzip();
- puts("Done. Now booting the kernel.\n");
+ puts("Done. Now booting the kernel.\r\n");
}
diff --git a/arch/cris/arch-v32/boot/rescue/Makefile b/arch/cris/arch-v32/boot/rescue/Makefile
index f668a819872..c0987795dcb 100644
--- a/arch/cris/arch-v32/boot/rescue/Makefile
+++ b/arch/cris/arch-v32/boot/rescue/Makefile
@@ -1,36 +1,27 @@
#
-# Makefile for rescue code
+# Makefile for rescue (bootstrap) code
#
-target = $(target_rescue_dir)
-src = $(src_rescue_dir)
CC = gcc-cris -mlinux -march=v32 $(LINUXINCLUDE)
-CFLAGS = -O2
+ccflags-y += -O2 -I $(srctree)/include/asm/arch/mach/ \
+ -I $(srctree)/include/asm/arch
+asflags-y += -I $(srctree)/include/asm/arch/mach/ -I $(srctree)/include/asm/arch
LD = gcc-cris -mlinux -march=v32 -nostdlib
+ldflags-y += -T $(obj)/rescue.ld
+LDPOSTFLAGS = -lgcc
OBJCOPY = objcopy-cris
OBJCOPYFLAGS = -O binary --remove-section=.bss
+obj-$(CONFIG_ETRAX_AXISFLASHMAP) = head.o
+OBJECT := $(obj)/head.o
-all: $(target)/rescue.bin
+targets := rescue.o rescue.bin
-rescue: rescue.bin
- # do nothing
+quiet_cmd_ldlibgcc = LD $@
+cmd_ldlibgcc = $(LD) $(LDFLAGS) $(filter-out FORCE,$^) $(LDPOSTFLAGS) -o $@
-$(target)/rescue.bin: $(target) $(target)/head.o
- $(LD) -T $(src)/rescue.ld -o $(target)/rescue.o $(target)/head.o
- $(OBJCOPY) $(OBJCOPYFLAGS) $(target)/rescue.o $(target)/rescue.bin
- cp -p $(target)/rescue.bin $(objtree)
+$(obj)/rescue.o: $(OBJECTS) FORCE
+ $(call if_changed,ldlibgcc)
-$(target):
- mkdir -p $(target)
-
-$(target)/head.o: $(src)/head.S
- $(CC) -D__ASSEMBLY__ -c $< -o $*.o
-
-clean:
- rm -f $(target)/*.o $(target)/*.bin
-
-fastdep:
-
-modules:
-
-modules-install:
+$(obj)/rescue.bin: $(obj)/rescue.o FORCE
+ $(call if_changed,objcopy)
+ cp -p $(obj)/rescue.bin $(objtree)
diff --git a/arch/cris/arch-v32/boot/rescue/head.S b/arch/cris/arch-v32/boot/rescue/head.S
index 8cdb4011bc1..5f846b7700a 100644
--- a/arch/cris/arch-v32/boot/rescue/head.S
+++ b/arch/cris/arch-v32/boot/rescue/head.S
@@ -1,38 +1,26 @@
-/* $Id: head.S,v 1.4 2004/11/01 16:10:28 starvik Exp $
+/*
+ * Just get started by jumping to CONFIG_ETRAX_PTABLE_SECTOR to start
+ * kernel decompressor.
+ *
+ * In practice, this only works for NOR flash (or some convoluted RAM boot)
+ * and hence is not really useful for Artpec-3, so it's Etrax FS / NOR only.
*
- * This used to be the rescue code but now that is handled by the
- * RedBoot based RFL instead. Nothing to see here, move along.
*/
-#include <asm/arch/hwregs/reg_map_asm.h>
-#include <asm/arch/hwregs/config_defs_asm.h>
+#include <mach/startup.inc>
- .text
+#ifdef CONFIG_ETRAX_AXISFLASHMAP
- ;; Start clocks for used blocks.
- move.d REG_ADDR(config, regi_config, rw_clk_ctrl), $r1
- move.d [$r1], $r0
- or.d REG_STATE(config, rw_clk_ctrl, cpu, yes) | \
- REG_STATE(config, rw_clk_ctrl, bif, yes) | \
- REG_STATE(config, rw_clk_ctrl, fix_io, yes), $r0
- move.d $r0, [$r1]
+;; Code
- ;; Copy 68KB NAND flash to Internal RAM (if NAND boot)
- move.d 0x38004000, $r10
- move.d 0x8000, $r11
- move.d 0x11000, $r12
- move.d copy_complete, $r13
- and.d 0x000fffff, $r13
- or.d 0x38000000, $r13
+ .text
+start:
-#include "../../lib/nand_init.S"
+ ;; Start clocks for used blocks.
+ START_CLOCKS
- ;; No NAND found
move.d CONFIG_ETRAX_PTABLE_SECTOR, $r10
- jump $r10 ; Jump to decompresser
+ jump $r10 ; Jump to decompressor
nop
-copy_complete:
- move.d 0x38000000 + CONFIG_ETRAX_PTABLE_SECTOR, $r10
- jump $r10 ; Jump to decompresser
- nop
+#endif
diff --git a/arch/cris/arch-v32/boot/rescue/rescue.ld b/arch/cris/arch-v32/boot/rescue/rescue.ld
index 42b11aa122b..8ac646bc1a2 100644
--- a/arch/cris/arch-v32/boot/rescue/rescue.ld
+++ b/arch/cris/arch-v32/boot/rescue/rescue.ld
@@ -1,20 +1,43 @@
+/*#OUTPUT_FORMAT(elf32-us-cris) */
+OUTPUT_ARCH (crisv32)
+/* Now that NAND support has been stripped, this file could be simplified,
+ * but it doesn't do any harm on the other hand so why bother. */
+
MEMORY
{
- flash : ORIGIN = 0x00000000,
- LENGTH = 0x00100000
+ bootblk : ORIGIN = 0x38000000,
+ LENGTH = 0x00004000
+ intmem : ORIGIN = 0x38004000,
+ LENGTH = 0x00005000
}
SECTIONS
{
.text :
{
- stext = . ;
+ _stext = . ;
*(.text)
- etext = . ;
- } > flash
+ *(.init.text)
+ *(.rodata)
+ *(.rodata.*)
+ _etext = . ;
+ } > bootblk
.data :
{
*(.data)
- edata = . ;
- } > flash
+ _edata = . ;
+ } > bootblk
+ .bss :
+ {
+ _bss = . ;
+ *(.bss)
+ _end = ALIGN( 0x10 ) ;
+ } > intmem
+
+ /* Get rid of stuff from EXPORT_SYMBOL(foo). */
+ /DISCARD/ :
+ {
+ *(__ksymtab_strings)
+ *(__ksymtab)
+ }
}
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index 9bccb5e2a96..2a92cb1886c 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -1,65 +1,105 @@
+if ETRAX_ARCH_V32
+
config ETRAX_ETHERNET
bool "Ethernet support"
depends on ETRAX_ARCH_V32
select NET_ETHERNET
+ select MII
help
This option enables the ETRAX FS built-in 10/100Mbit Ethernet
controller.
-config ETRAX_ETHERNET_HW_CSUM
- bool "Hardware accelerated ethernet checksum and scatter/gather"
+config ETRAX_NO_PHY
+ bool "PHY not present"
depends on ETRAX_ETHERNET
- depends on ETRAX_STREAMCOPROC
- default y
+ default N
help
- Hardware acceleration of checksumming and scatter/gather
+ This option disables all MDIO communication with an ethernet
+ transceiver connected to the MII interface. This option shall
+ typically be enabled if the MII interface is connected to a
+ switch. This option should normally be disabled. If enabled,
+ speed and duplex will be locked to 100 Mbit and full duplex.
config ETRAX_ETHERNET_IFACE0
depends on ETRAX_ETHERNET
bool "Enable network interface 0"
config ETRAX_ETHERNET_IFACE1
- depends on ETRAX_ETHERNET
+ depends on (ETRAX_ETHERNET && ETRAXFS)
bool "Enable network interface 1 (uses DMA6 and DMA7)"
+config ETRAX_ETHERNET_GBIT
+ depends on (ETRAX_ETHERNET && CRIS_MACH_ARTPEC3)
+ bool "Enable gigabit Ethernet support"
+
choice
- prompt "Network LED behavior"
- depends on ETRAX_ETHERNET
- default ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY
+ prompt "Eth0 led group"
+ depends on ETRAX_ETHERNET_IFACE0
+ default ETRAX_ETH0_USE_LEDGRP0
-config ETRAX_NETWORK_LED_ON_WHEN_LINK
- bool "LED_on_when_link"
+config ETRAX_ETH0_USE_LEDGRP0
+ bool "Use LED grp 0"
+ depends on ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO
help
- Selecting LED_on_when_link will light the LED when there is a
- connection and will flash off when there is activity.
-
- Selecting LED_on_when_activity will light the LED only when
- there is activity.
+ Use LED grp 0 for eth0
- This setting will also affect the behaviour of other activity LEDs
- e.g. Bluetooth.
+config ETRAX_ETH0_USE_LEDGRP1
+ bool "Use LED grp 1"
+ depends on ETRAX_NBR_LED_GRP_TWO
+ help
+ Use LED grp 1 for eth0
-config ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY
- bool "LED_on_when_activity"
+config ETRAX_ETH0_USE_LEDGRPNULL
+ bool "Use no LEDs for eth0"
help
- Selecting LED_on_when_link will light the LED when there is a
- connection and will flash off when there is activity.
+ Use no LEDs for eth0
+endchoice
+
+choice
+ prompt "Eth1 led group"
+ depends on ETRAX_ETHERNET_IFACE1
+ default ETRAX_ETH1_USE_LEDGRP1
- Selecting LED_on_when_activity will light the LED only when
- there is activity.
+config ETRAX_ETH1_USE_LEDGRP0
+ bool "Use LED grp 0"
+ depends on ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO
+ help
+ Use LED grp 0 for eth1
- This setting will also affect the behaviour of other activity LEDs
- e.g. Bluetooth.
+config ETRAX_ETH1_USE_LEDGRP1
+ bool "Use LED grp 1"
+ depends on ETRAX_NBR_LED_GRP_TWO
+ help
+ Use LED grp 1 for eth1
+config ETRAX_ETH1_USE_LEDGRPNULL
+ bool "Use no LEDs for eth1"
+ help
+ Use no LEDs for eth1
endchoice
config ETRAXFS_SERIAL
bool "Serial-port support"
depends on ETRAX_ARCH_V32
+ select SERIAL_CORE
+ select SERIAL_CORE_CONSOLE
help
Enables the ETRAX FS serial driver for ser0 (ttyS0)
You probably want this enabled.
+config ETRAX_RS485
+ bool "RS-485 support"
+ depends on ETRAXFS_SERIAL
+ help
+ Enables support for RS-485 serial communication.
+
+config ETRAX_RS485_DISABLE_RECEIVER
+ bool "Disable serial receiver"
+ depends on ETRAX_RS485
+ help
+ It is necessary to disable the serial receiver to avoid serial
+ loopback. Not all products are able to do this in software only.
+
config ETRAX_SERIAL_PORT0
bool "Serial port 0 enabled"
depends on ETRAXFS_SERIAL
@@ -70,50 +110,28 @@ config ETRAX_SERIAL_PORT0
ser0 can use dma4 or dma6 for output and dma5 or dma7 for input.
choice
- prompt "Ser0 DMA in channel "
+ prompt "Ser0 default port type "
depends on ETRAX_SERIAL_PORT0
- default ETRAX_SERIAL_PORT0_NO_DMA_IN
+ default ETRAX_SERIAL_PORT0_TYPE_232
help
- What DMA channel to use for ser0.
-
+ Type of serial port.
-config ETRAX_SERIAL_PORT0_NO_DMA_IN
- bool "Ser0 uses no DMA for input"
+config ETRAX_SERIAL_PORT0_TYPE_232
+ bool "Ser0 is a RS-232 port"
help
- Do not use DMA for ser0 input.
+ Configure serial port 0 to be a RS-232 port.
-config ETRAX_SERIAL_PORT0_DMA7_IN
- bool "Ser0 uses DMA7 for input"
- depends on ETRAX_SERIAL_PORT0
- help
- Enables the DMA7 input channel for ser0 (ttyS0).
- If you do not enable DMA, an interrupt for each character will be
- used when receiving data.
- Normally you want to use DMA, unless you use the DMA channel for
- something else.
-
-endchoice
-
-choice
- prompt "Ser0 DMA out channel"
- depends on ETRAX_SERIAL_PORT0
- default ETRAX_SERIAL_PORT0_NO_DMA_OUT
-
-config ETRAX_SERIAL_PORT0_NO_DMA_OUT
- bool "Ser0 uses no DMA for output"
+config ETRAX_SERIAL_PORT0_TYPE_485HD
+ bool "Ser0 is a half duplex RS-485 port"
+ depends on ETRAX_RS485
help
- Do not use DMA for ser0 output.
+ Configure serial port 0 to be a half duplex (two wires) RS-485 port.
-config ETRAX_SERIAL_PORT0_DMA6_OUT
- bool "Ser0 uses DMA6 for output"
- depends on ETRAX_SERIAL_PORT0
+config ETRAX_SERIAL_PORT0_TYPE_485FD
+ bool "Ser0 is a full duplex RS-485 port"
+ depends on ETRAX_RS485
help
- Enables the DMA6 output channel for ser0 (ttyS0).
- If you do not enable DMA, an interrupt for each character will be
- used when transmitting data.
- Normally you want to use DMA, unless you use the DMA channel for
- something else.
-
+ Configure serial port 0 to be a full duplex (four wires) RS-485 port.
endchoice
config ETRAX_SER0_DTR_BIT
@@ -139,52 +157,28 @@ config ETRAX_SERIAL_PORT1
Enables the ETRAX FS serial driver for ser1 (ttyS1).
choice
- prompt "Ser1 DMA in channel "
+ prompt "Ser1 default port type"
depends on ETRAX_SERIAL_PORT1
- default ETRAX_SERIAL_PORT1_NO_DMA_IN
- help
- What DMA channel to use for ser1.
-
-
-config ETRAX_SERIAL_PORT1_NO_DMA_IN
- bool "Ser1 uses no DMA for input"
+ default ETRAX_SERIAL_PORT1_TYPE_232
help
- Do not use DMA for ser1 input.
+ Type of serial port.
-config ETRAX_SERIAL_PORT1_DMA5_IN
- bool "Ser1 uses DMA5 for input"
- depends on ETRAX_SERIAL_PORT1
+config ETRAX_SERIAL_PORT1_TYPE_232
+ bool "Ser1 is a RS-232 port"
help
- Enables the DMA5 input channel for ser1 (ttyS1).
- If you do not enable DMA, an interrupt for each character will be
- used when receiving data.
- Normally you want this on, unless you use the DMA channel for
- something else.
+ Configure serial port 1 to be a RS-232 port.
-endchoice
-
-choice
- prompt "Ser1 DMA out channel "
- depends on ETRAX_SERIAL_PORT1
- default ETRAX_SERIAL_PORT1_NO_DMA_OUT
- help
- What DMA channel to use for ser1.
-
-config ETRAX_SERIAL_PORT1_NO_DMA_OUT
- bool "Ser1 uses no DMA for output"
+config ETRAX_SERIAL_PORT1_TYPE_485HD
+ bool "Ser1 is a half duplex RS-485 port"
+ depends on ETRAX_RS485
help
- Do not use DMA for ser1 output.
+ Configure serial port 1 to be a half duplex (two wires) RS-485 port.
-config ETRAX_SERIAL_PORT1_DMA4_OUT
- bool "Ser1 uses DMA4 for output"
- depends on ETRAX_SERIAL_PORT1
+config ETRAX_SERIAL_PORT1_TYPE_485FD
+ bool "Ser1 is a full duplex RS-485 port"
+ depends on ETRAX_RS485
help
- Enables the DMA4 output channel for ser1 (ttyS1).
- If you do not enable DMA, an interrupt for each character will be
- used when transmitting data.
- Normally you want this on, unless you use the DMA channel for
- something else.
-
+ Configure serial port 1 to be a full duplex (four wires) RS-485 port.
endchoice
config ETRAX_SER1_DTR_BIT
@@ -210,52 +204,31 @@ config ETRAX_SERIAL_PORT2
Enables the ETRAX FS serial driver for ser2 (ttyS2).
choice
- prompt "Ser2 DMA in channel "
+ prompt "Ser2 default port type"
depends on ETRAX_SERIAL_PORT2
- default ETRAX_SERIAL_PORT2_NO_DMA_IN
+ default ETRAX_SERIAL_PORT2_TYPE_232
help
- What DMA channel to use for ser2.
-
+ What DMA channel to use for ser2
-config ETRAX_SERIAL_PORT2_NO_DMA_IN
- bool "Ser2 uses no DMA for input"
+config ETRAX_SERIAL_PORT2_TYPE_232
+ bool "Ser2 is a RS-232 port"
help
- Do not use DMA for ser2 input.
+ Configure serial port 2 to be a RS-232 port.
-config ETRAX_SERIAL_PORT2_DMA3_IN
- bool "Ser2 uses DMA3 for input"
- depends on ETRAX_SERIAL_PORT2
- help
- Enables the DMA3 input channel for ser2 (ttyS2).
- If you do not enable DMA, an interrupt for each character will be
- used when receiving data.
- Normally you want to use DMA, unless you use the DMA channel for
- something else.
-
-endchoice
-
-choice
- prompt "Ser2 DMA out channel"
- depends on ETRAX_SERIAL_PORT2
- default ETRAX_SERIAL_PORT2_NO_DMA_OUT
-
-config ETRAX_SERIAL_PORT2_NO_DMA_OUT
- bool "Ser2 uses no DMA for output"
+config ETRAX_SERIAL_PORT2_TYPE_485HD
+ bool "Ser2 is a half duplex RS-485 port"
+ depends on ETRAX_RS485
help
- Do not use DMA for ser2 output.
+ Configure serial port 2 to be a half duplex (two wires) RS-485 port.
-config ETRAX_SERIAL_PORT2_DMA2_OUT
- bool "Ser2 uses DMA2 for output"
- depends on ETRAX_SERIAL_PORT2
+config ETRAX_SERIAL_PORT2_TYPE_485FD
+ bool "Ser2 is a full duplex RS-485 port"
+ depends on ETRAX_RS485
help
- Enables the DMA2 output channel for ser2 (ttyS2).
- If you do not enable DMA, an interrupt for each character will be
- used when transmitting data.
- Normally you want to use DMA, unless you use the DMA channel for
- something else.
-
+ Configure serial port 2 to be a full duplex (four wires) RS-485 port.
endchoice
+
config ETRAX_SER2_DTR_BIT
string "Ser 2 DTR bit (empty = not used)"
depends on ETRAX_SERIAL_PORT2
@@ -279,71 +252,121 @@ config ETRAX_SERIAL_PORT3
Enables the ETRAX FS serial driver for ser3 (ttyS3).
choice
- prompt "Ser3 DMA in channel "
+ prompt "Ser3 default port type"
depends on ETRAX_SERIAL_PORT3
- default ETRAX_SERIAL_PORT3_NO_DMA_IN
+ default ETRAX_SERIAL_PORT3_TYPE_232
help
What DMA channel to use for ser3.
+config ETRAX_SERIAL_PORT3_TYPE_232
+ bool "Ser3 is a RS-232 port"
+ help
+ Configure serial port 3 to be a RS-232 port.
-config ETRAX_SERIAL_PORT3_NO_DMA_IN
- bool "Ser3 uses no DMA for input"
+config ETRAX_SERIAL_PORT3_TYPE_485HD
+ bool "Ser3 is a half duplex RS-485 port"
+ depends on ETRAX_RS485
+ help
+ Configure serial port 3 to be a half duplex (two wires) RS-485 port.
+
+config ETRAX_SERIAL_PORT3_TYPE_485FD
+ bool "Ser3 is a full duplex RS-485 port"
+ depends on ETRAX_RS485
help
- Do not use DMA for ser3 input.
+ Configure serial port 3 to be a full duplex (four wires) RS-485 port.
+endchoice
-config ETRAX_SERIAL_PORT3_DMA9_IN
- bool "Ser3 uses DMA9 for input"
+config ETRAX_SER3_DTR_BIT
+ string "Ser 3 DTR bit (empty = not used)"
+ depends on ETRAX_SERIAL_PORT3
+
+config ETRAX_SER3_RI_BIT
+ string "Ser 3 RI bit (empty = not used)"
+ depends on ETRAX_SERIAL_PORT3
+
+config ETRAX_SER3_DSR_BIT
+ string "Ser 3 DSR bit (empty = not used)"
+ depends on ETRAX_SERIAL_PORT3
+
+config ETRAX_SER3_CD_BIT
+ string "Ser 3 CD bit (empty = not used)"
depends on ETRAX_SERIAL_PORT3
+
+config ETRAX_SERIAL_PORT4
+ bool "Serial port 4 enabled"
+ depends on ETRAXFS_SERIAL && CRIS_MACH_ARTPEC3
help
- Enables the DMA9 input channel for ser3 (ttyS3).
- If you do not enable DMA, an interrupt for each character will be
- used when receiving data.
- Normally you want to use DMA, unless you use the DMA channel for
- something else.
+ Enables the ETRAX FS serial driver for ser4 (ttyS4).
+
+choice
+ prompt "Ser4 default port type"
+ depends on ETRAX_SERIAL_PORT4
+ default ETRAX_SERIAL_PORT4_TYPE_232
+ help
+ What DMA channel to use for ser4.
+
+config ETRAX_SERIAL_PORT4_TYPE_232
+ bool "Ser4 is a RS-232 port"
+ help
+ Configure serial port 4 to be a RS-232 port.
+
+config ETRAX_SERIAL_PORT4_TYPE_485HD
+ bool "Ser4 is a half duplex RS-485 port"
+ depends on ETRAX_RS485
+ help
+ Configure serial port 4 to be a half duplex (two wires) RS-485 port.
+config ETRAX_SERIAL_PORT4_TYPE_485FD
+ bool "Ser4 is a full duplex RS-485 port"
+ depends on ETRAX_RS485
+ help
+ Configure serial port 4 to be a full duplex (four wires) RS-485 port.
endchoice
choice
- prompt "Ser3 DMA out channel"
- depends on ETRAX_SERIAL_PORT3
- default ETRAX_SERIAL_PORT3_NO_DMA_OUT
+ prompt "Ser4 DMA in channel "
+ depends on ETRAX_SERIAL_PORT4
+ default ETRAX_SERIAL_PORT4_NO_DMA_IN
+ help
+ What DMA channel to use for ser4.
-config ETRAX_SERIAL_PORT3_NO_DMA_OUT
- bool "Ser3 uses no DMA for output"
+
+config ETRAX_SERIAL_PORT4_NO_DMA_IN
+ bool "Ser4 uses no DMA for input"
help
- Do not use DMA for ser3 output.
+ Do not use DMA for ser4 input.
-config ETRAX_SERIAL_PORT3_DMA8_OUT
- bool "Ser3 uses DMA8 for output"
- depends on ETRAX_SERIAL_PORT3
+config ETRAX_SERIAL_PORT4_DMA9_IN
+ bool "Ser4 uses DMA9 for input"
+ depends on ETRAX_SERIAL_PORT4
help
- Enables the DMA8 output channel for ser3 (ttyS3).
+ Enables the DMA9 input channel for ser4 (ttyS4).
If you do not enable DMA, an interrupt for each character will be
- used when transmitting data.
+ used when receiveing data.
Normally you want to use DMA, unless you use the DMA channel for
something else.
endchoice
-config ETRAX_SER3_DTR_BIT
- string "Ser 3 DTR bit (empty = not used)"
- depends on ETRAX_SERIAL_PORT3
+config ETRAX_SER4_DTR_BIT
+ string "Ser 4 DTR bit (empty = not used)"
+ depends on ETRAX_SERIAL_PORT4
-config ETRAX_SER3_RI_BIT
- string "Ser 3 RI bit (empty = not used)"
- depends on ETRAX_SERIAL_PORT3
+config ETRAX_SER4_RI_BIT
+ string "Ser 4 RI bit (empty = not used)"
+ depends on ETRAX_SERIAL_PORT4
-config ETRAX_SER3_DSR_BIT
- string "Ser 3 DSR bit (empty = not used)"
- depends on ETRAX_SERIAL_PORT3
+config ETRAX_SER4_DSR_BIT
+ string "Ser 4 DSR bit (empty = not used)"
+ depends on ETRAX_SERIAL_PORT4
config ETRAX_SER3_CD_BIT
- string "Ser 3 CD bit (empty = not used)"
- depends on ETRAX_SERIAL_PORT3
+ string "Ser 4 CD bit (empty = not used)"
+ depends on ETRAX_SERIAL_PORT4
config ETRAX_RS485
bool "RS-485 support"
- depends on ETRAX_SERIAL
+ depends on ETRAXFS_SERIAL
help
Enables support for RS-485 serial communication. For a primer on
RS-485, see <http://www.hw.cz/english/docs/rs485/rs485.html>.
@@ -354,22 +377,6 @@ config ETRAX_RS485_DISABLE_RECEIVER
help
It is necessary to disable the serial receiver to avoid serial
loopback. Not all products are able to do this in software only.
- Axis 2400/2401 must disable receiver.
-
-config ETRAX_AXISFLASHMAP
- bool "Axis flash-map support"
- depends on ETRAX_ARCH_V32
- select MTD
- select MTD_CFI
- select MTD_CFI_AMDSTD
- select MTD_CHAR
- select MTD_BLOCK
- select MTD_PARTITIONS
- select MTD_CONCAT
- select MTD_COMPLEX_MAPPINGS
- help
- This option enables MTD mapping of flash devices. Needed to use
- flash memories. If unsure, say Y.
config ETRAX_SYNCHRONOUS_SERIAL
bool "Synchronous serial-port support"
@@ -392,7 +399,7 @@ config ETRAX_SYNCHRONOUS_SERIAL0_DMA
config ETRAX_SYNCHRONOUS_SERIAL_PORT1
bool "Synchronous serial port 1 enabled"
- depends on ETRAX_SYNCHRONOUS_SERIAL
+ depends on ETRAX_SYNCHRONOUS_SERIAL && ETRAXFS
help
Enabled synchronous serial port 1.
@@ -403,6 +410,31 @@ config ETRAX_SYNCHRONOUS_SERIAL1_DMA
A synchronous serial port can run in manual or DMA mode.
Selecting this option will make it run in DMA mode.
+config ETRAX_AXISFLASHMAP
+ bool "Axis flash-map support"
+ depends on ETRAX_ARCH_V32
+ select MTD
+ select MTD_CFI
+ select MTD_CFI_AMDSTD
+ select MTD_JEDECPROBE
+ select MTD_CHAR
+ select MTD_BLOCK
+ select MTD_PARTITIONS
+ select MTD_CONCAT
+ select MTD_COMPLEX_MAPPINGS
+ help
+ This option enables MTD mapping of flash devices. Needed to use
+ flash memories. If unsure, say Y.
+
+config ETRAX_AXISFLASHMAP_MTD0WHOLE
+ bool "MTD0 is whole boot flash device"
+ depends on ETRAX_AXISFLASHMAP
+ default N
+ help
+ When this option is not set, mtd0 refers to the first partition
+ on the boot flash device. When set, mtd0 refers to the whole
+ device, with mtd1 referring to the first partition etc.
+
config ETRAX_PTABLE_SECTOR
int "Byte-offset of partition table sector"
depends on ETRAX_AXISFLASHMAP
@@ -423,42 +455,32 @@ config ETRAX_NANDFLASH
This option enables MTD mapping of NAND flash devices. Needed to use
NAND flash memories. If unsure, say Y.
+config ETRAX_NANDBOOT
+ bool "Boot from NAND flash"
+ depends on ETRAX_NANDFLASH
+ help
+ This options enables booting from NAND flash devices.
+ Say Y if your boot code, kernel and root file system is in
+ NAND flash. Say N if they are in NOR flash.
+
config ETRAX_I2C
bool "I2C driver"
depends on ETRAX_ARCH_V32
help
- This option enabled the I2C driver used by e.g. the RTC driver.
+ This option enables the I2C driver used by e.g. the RTC driver.
-config ETRAX_I2C_DATA_PORT
+config ETRAX_V32_I2C_DATA_PORT
string "I2C data pin"
depends on ETRAX_I2C
help
The pin to use for I2C data.
-config ETRAX_I2C_CLK_PORT
+config ETRAX_V32_I2C_CLK_PORT
string "I2C clock pin"
depends on ETRAX_I2C
help
The pin to use for I2C clock.
-config ETRAX_RTC
- bool "Real Time Clock support"
- depends on ETRAX_ARCH_V32
- help
- Enabled RTC support.
-
-choice
- prompt "RTC chip"
- depends on ETRAX_RTC
- default ETRAX_PCF8563
-
-config ETRAX_PCF8563
- bool "PCF8563"
- help
- Philips PCF8563 RTC
-
-endchoice
-
config ETRAX_GPIO
bool "GPIO support"
depends on ETRAX_ARCH_V32
@@ -474,33 +496,36 @@ config ETRAX_GPIO
Remember that you need to setup the port directions appropriately in
the General configuration.
-config ETRAX_PA_BUTTON_BITMASK
- hex "PA-buttons bitmask"
+config ETRAX_VIRTUAL_GPIO
+ bool "Virtual GPIO support"
depends on ETRAX_GPIO
- default "0x02"
help
- This is a bitmask (8 bits) with information about what bits on PA
- that are used for buttons.
- Most products has a so called TEST button on PA1, if that is true
- use 0x02 here.
- Use 00 if there are no buttons on PA.
- If the bitmask is <> 00 a button driver will be included in the gpio
- driver. ETRAX general I/O support must be enabled.
+ Enables the virtual Etrax general port device (major 120, minor 6).
+ It uses an I/O expander for the I2C-bus.
+
+config ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN
+ int "Virtual GPIO interrupt pin on PA pin"
+ range 0 7
+ depends on ETRAX_VIRTUAL_GPIO
+ help
+ The pin to use on PA for virtual gpio interrupt.
config ETRAX_PA_CHANGEABLE_DIR
hex "PA user changeable dir mask"
depends on ETRAX_GPIO
- default "0x00"
+ default "0x00" if ETRAXFS
+ default "0x00000000" if !ETRAXFS
help
This is a bitmask (8 bits) with information of what bits in PA that a
user can change direction on using ioctl's.
Bit set = changeable.
- You probably want 0x00 here, but it depends on your hardware.
+ You probably want 0 here, but it depends on your hardware.
config ETRAX_PA_CHANGEABLE_BITS
hex "PA user changeable bits mask"
depends on ETRAX_GPIO
- default "0x00"
+ default "0x00" if ETRAXFS
+ default "0x00000000" if !ETRAXFS
help
This is a bitmask (8 bits) with information of what bits in PA
that a user can change the value on using ioctl's.
@@ -509,17 +534,19 @@ config ETRAX_PA_CHANGEABLE_BITS
config ETRAX_PB_CHANGEABLE_DIR
hex "PB user changeable dir mask"
depends on ETRAX_GPIO
- default "0x00000"
+ default "0x00000" if ETRAXFS
+ default "0x00000000" if !ETRAXFS
help
This is a bitmask (18 bits) with information of what bits in PB
that a user can change direction on using ioctl's.
Bit set = changeable.
- You probably want 0x00000 here, but it depends on your hardware.
+ You probably want 0 here, but it depends on your hardware.
config ETRAX_PB_CHANGEABLE_BITS
hex "PB user changeable bits mask"
depends on ETRAX_GPIO
- default "0x00000"
+ default "0x00000" if ETRAXFS
+ default "0x00000000" if !ETRAXFS
help
This is a bitmask (18 bits) with information of what bits in PB
that a user can change the value on using ioctl's.
@@ -528,17 +555,19 @@ config ETRAX_PB_CHANGEABLE_BITS
config ETRAX_PC_CHANGEABLE_DIR
hex "PC user changeable dir mask"
depends on ETRAX_GPIO
- default "0x00000"
+ default "0x00000" if ETRAXFS
+ default "0x00000000" if !ETRAXFS
help
This is a bitmask (18 bits) with information of what bits in PC
that a user can change direction on using ioctl's.
Bit set = changeable.
- You probably want 0x00000 here, but it depends on your hardware.
+ You probably want 0 here, but it depends on your hardware.
config ETRAX_PC_CHANGEABLE_BITS
hex "PC user changeable bits mask"
depends on ETRAX_GPIO
- default "0x00000"
+ default "0x00000" if ETRAXFS
+ default "0x00000000" if ETRAXFS
help
This is a bitmask (18 bits) with information of what bits in PC
that a user can change the value on using ioctl's.
@@ -546,7 +575,7 @@ config ETRAX_PC_CHANGEABLE_BITS
config ETRAX_PD_CHANGEABLE_DIR
hex "PD user changeable dir mask"
- depends on ETRAX_GPIO
+ depends on ETRAX_GPIO && ETRAXFS
default "0x00000"
help
This is a bitmask (18 bits) with information of what bits in PD
@@ -556,7 +585,7 @@ config ETRAX_PD_CHANGEABLE_DIR
config ETRAX_PD_CHANGEABLE_BITS
hex "PD user changeable bits mask"
- depends on ETRAX_GPIO
+ depends on ETRAX_GPIO && ETRAXFS
default "0x00000"
help
This is a bitmask (18 bits) with information of what bits in PD
@@ -565,7 +594,7 @@ config ETRAX_PD_CHANGEABLE_BITS
config ETRAX_PE_CHANGEABLE_DIR
hex "PE user changeable dir mask"
- depends on ETRAX_GPIO
+ depends on ETRAX_GPIO && ETRAXFS
default "0x00000"
help
This is a bitmask (18 bits) with information of what bits in PE
@@ -575,20 +604,36 @@ config ETRAX_PE_CHANGEABLE_DIR
config ETRAX_PE_CHANGEABLE_BITS
hex "PE user changeable bits mask"
- depends on ETRAX_GPIO
+ depends on ETRAX_GPIO && ETRAXFS
default "0x00000"
help
This is a bitmask (18 bits) with information of what bits in PE
that a user can change the value on using ioctl's.
Bit set = changeable.
+config ETRAX_PV_CHANGEABLE_DIR
+ hex "PV user changeable dir mask"
+ depends on ETRAX_VIRTUAL_GPIO
+ default "0x0000"
+ help
+ This is a bitmask (16 bits) with information of what bits in PV
+ that a user can change direction on using ioctl's.
+ Bit set = changeable.
+ You probably want 0x0000 here, but it depends on your hardware.
+
+config ETRAX_PV_CHANGEABLE_BITS
+ hex "PV user changeable bits mask"
+ depends on ETRAX_VIRTUAL_GPIO
+ default "0x0000"
+ help
+ This is a bitmask (16 bits) with information of what bits in PV
+ that a user can change the value on using ioctl's.
+ Bit set = changeable.
+
config ETRAX_CARDBUS
bool "Cardbus support"
depends on ETRAX_ARCH_V32
- select PCCARD
- select CARDBUS
select HOTPLUG
- select PCCARD_NONSTATIC
help
Enabled the ETRAX Cardbus driver.
@@ -610,3 +655,203 @@ config ETRAX_STREAMCOPROC
help
This option enables a driver for the stream co-processor
for cryptographic operations.
+
+source drivers/mmc/Kconfig
+
+config ETRAX_MMC_IOP
+ tristate "MMC/SD host driver using IO-processor"
+ depends on ETRAX_ARCH_V32 && MMC
+ help
+ This option enables the SD/MMC host controller interface.
+ The host controller is implemented using the built in
+ IO-Processor. Only the SPU is used in this implementation.
+
+config ETRAX_SPI_MMC
+# Make this one of several "choices" (possible simultaneously but
+# suggested uniquely) when an IOP driver emerges for "real" MMC/SD
+# protocol support.
+ tristate
+ depends on !ETRAX_MMC_IOP
+ default MMC
+ select SPI
+ select MMC_SPI
+ select ETRAX_SPI_MMC_BOARD
+
+# For the parts that can't be a module (due to restrictions in
+# framework elsewhere).
+config ETRAX_SPI_MMC_BOARD
+ boolean
+ default n
+
+# While the board info is MMC_SPI only, the drivers are written to be
+# independent of MMC_SPI, so we'll keep SPI non-dependent on the
+# MMC_SPI config choices (well, except for a single depends-on-line
+# for the board-info file until a separate non-MMC SPI board file
+# emerges).
+# FIXME: When that happens, we'll need to be able to ask for and
+# configure non-MMC SPI ports together with MMC_SPI ports (if multiple
+# SPI ports are enabled).
+
+config SPI_ETRAX_SSER
+ tristate
+ depends on SPI_MASTER && ETRAX_ARCH_V32 && EXPERIMENTAL
+ select SPI_BITBANG
+ help
+ This enables using an synchronous serial (sser) port as a
+ SPI master controller on Axis ETRAX FS and later. The
+ driver can be configured to use any sser port.
+
+config SPI_ETRAX_GPIO
+ tristate
+ depends on SPI_MASTER && ETRAX_ARCH_V32 && EXPERIMENTAL
+ select SPI_BITBANG
+ help
+ This enables using GPIO pins port as a SPI master controller
+ on Axis ETRAX FS and later. The driver can be configured to
+ use any GPIO pins.
+
+config ETRAX_SPI_SSER0
+ tristate "SPI using synchronous serial port 0 (sser0)"
+ depends on ETRAX_SPI_MMC
+ default m if MMC_SPI=m
+ default y if MMC_SPI=y
+ default y if MMC_SPI=n
+ select SPI_ETRAX_SSER
+ help
+ Say Y for an MMC/SD socket connected to synchronous serial port 0,
+ or for devices using the SPI protocol on that port. Say m if you
+ want to build it as a module, which will be named spi_crisv32_sser.
+ (You need to select MMC separately.)
+
+config ETRAX_SPI_SSER0_DMA
+ bool "DMA for SPI on sser0 enabled"
+ depends on ETRAX_SPI_SSER0
+ depends on !ETRAX_SERIAL_PORT1_DMA4_OUT && !ETRAX_SERIAL_PORT1_DMA5_IN
+ default y
+ help
+ Say Y if using DMA (dma4/dma5) for SPI on synchronous serial port 0.
+
+config ETRAX_SPI_MMC_CD_SSER0_PIN
+ string "MMC/SD card detect pin for SPI on sser0"
+ depends on ETRAX_SPI_SSER0 && MMC_SPI
+ default "pd11"
+ help
+ The pin to use for SD/MMC card detect. This pin should be pulled up
+ and grounded when a card is present. If defined as " " (space), no
+ pin is selected. A card must then always be inserted for proper
+ action.
+
+config ETRAX_SPI_MMC_WP_SSER0_PIN
+ string "MMC/SD card write-protect pin for SPI on sser0"
+ depends on ETRAX_SPI_SSER0 && MMC_SPI
+ default "pd10"
+ help
+ The pin to use for the SD/MMC write-protect signal for a memory
+ card. If defined as " " (space), the card is considered writable.
+
+config ETRAX_SPI_SSER1
+ tristate "SPI using synchronous serial port 1 (sser1)"
+ depends on ETRAX_SPI_MMC
+ default m if MMC_SPI=m && ETRAX_SPI_SSER0=n
+ default y if MMC_SPI=y && ETRAX_SPI_SSER0=n
+ default y if MMC_SPI=n && ETRAX_SPI_SSER0=n
+ select SPI_ETRAX_SSER
+ help
+ Say Y for an MMC/SD socket connected to synchronous serial port 1,
+ or for devices using the SPI protocol on that port. Say m if you
+ want to build it as a module, which will be named spi_crisv32_sser.
+ (You need to select MMC separately.)
+
+config ETRAX_SPI_SSER1_DMA
+ bool "DMA for SPI on sser1 enabled"
+ depends on ETRAX_SPI_SSER1 && !ETRAX_ETHERNET_IFACE1
+ depends on !ETRAX_SERIAL_PORT0_DMA6_OUT && !ETRAX_SERIAL_PORT0_DMA7_IN
+ default y
+ help
+ Say Y if using DMA (dma6/dma7) for SPI on synchronous serial port 1.
+
+config ETRAX_SPI_MMC_CD_SSER1_PIN
+ string "MMC/SD card detect pin for SPI on sser1"
+ depends on ETRAX_SPI_SSER1 && MMC_SPI
+ default "pd12"
+ help
+ The pin to use for SD/MMC card detect. This pin should be pulled up
+ and grounded when a card is present. If defined as " " (space), no
+ pin is selected. A card must then always be inserted for proper
+ action.
+
+config ETRAX_SPI_MMC_WP_SSER1_PIN
+ string "MMC/SD card write-protect pin for SPI on sser1"
+ depends on ETRAX_SPI_SSER1 && MMC_SPI
+ default "pd9"
+ help
+ The pin to use for the SD/MMC write-protect signal for a memory
+ card. If defined as " " (space), the card is considered writable.
+
+config ETRAX_SPI_GPIO
+ tristate "Bitbanged SPI using gpio pins"
+ depends on ETRAX_SPI_MMC
+ select SPI_ETRAX_GPIO
+ default m if MMC_SPI=m && ETRAX_SPI_SSER0=n && ETRAX_SPI_SSER1=n
+ default y if MMC_SPI=y && ETRAX_SPI_SSER0=n && ETRAX_SPI_SSER1=n
+ default y if MMC_SPI=n && ETRAX_SPI_SSER0=n && ETRAX_SPI_SSER1=n
+ help
+ Say Y for an MMC/SD socket connected to general I/O pins (but not
+ a complete synchronous serial ports), or for devices using the SPI
+ protocol on general I/O pins. Slow and slows down the system.
+ Say m to build it as a module, which will be called spi_crisv32_gpio.
+ (You need to select MMC separately.)
+
+# The default match that of sser0, only because that's how it was tested.
+config ETRAX_SPI_CS_PIN
+ string "SPI chip select pin"
+ depends on ETRAX_SPI_GPIO
+ default "pc3"
+ help
+ The pin to use for SPI chip select.
+
+config ETRAX_SPI_CLK_PIN
+ string "SPI clock pin"
+ depends on ETRAX_SPI_GPIO
+ default "pc1"
+ help
+ The pin to use for the SPI clock.
+
+config ETRAX_SPI_DATAIN_PIN
+ string "SPI MISO (data in) pin"
+ depends on ETRAX_SPI_GPIO
+ default "pc16"
+ help
+ The pin to use for SPI data in from the device.
+
+config ETRAX_SPI_DATAOUT_PIN
+ string "SPI MOSI (data out) pin"
+ depends on ETRAX_SPI_GPIO
+ default "pc0"
+ help
+ The pin to use for SPI data out to the device.
+
+config ETRAX_SPI_MMC_CD_GPIO_PIN
+ string "MMC/SD card detect pin for SPI using gpio (space for none)"
+ depends on ETRAX_SPI_GPIO && MMC_SPI
+ default "pd11"
+ help
+ The pin to use for SD/MMC card detect. This pin should be pulled up
+ and grounded when a card is present. If defined as " " (space), no
+ pin is selected. A card must then always be inserted for proper
+ action.
+
+config ETRAX_SPI_MMC_WP_GPIO_PIN
+ string "MMC/SD card write-protect pin for SPI using gpio (space for none)"
+ depends on ETRAX_SPI_GPIO && MMC_SPI
+ default "pd10"
+ help
+ The pin to use for the SD/MMC write-protect signal for a memory
+ card. If defined as " " (space), the card is considered writable.
+
+# Avoid choices causing non-working configs by conditionalizing the inclusion.
+if ETRAX_SPI_MMC
+source drivers/spi/Kconfig
+endif
+
+endif
diff --git a/arch/cris/arch-v32/drivers/Makefile b/arch/cris/arch-v32/drivers/Makefile
index a359cd20ae7..e8c02437eda 100644
--- a/arch/cris/arch-v32/drivers/Makefile
+++ b/arch/cris/arch-v32/drivers/Makefile
@@ -4,10 +4,11 @@
obj-$(CONFIG_ETRAX_STREAMCOPROC) += cryptocop.o
obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o
-obj-$(CONFIG_ETRAX_NANDFLASH) += nandflash.o
-obj-$(CONFIG_ETRAX_GPIO) += gpio.o
+obj-$(CONFIG_ETRAXFS) += mach-fs/
+obj-$(CONFIG_CRIS_MACH_ARTPEC3) += mach-a3/
obj-$(CONFIG_ETRAX_IOP_FW_LOAD) += iop_fw_load.o
obj-$(CONFIG_ETRAX_PCF8563) += pcf8563.o
obj-$(CONFIG_ETRAX_I2C) += i2c.o
obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o
obj-$(CONFIG_PCI) += pci/
+obj-$(CONFIG_ETRAX_SPI_MMC_BOARD) += board_mmcspi.o
diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c
index c5ff95e1826..51e1e85df96 100644
--- a/arch/cris/arch-v32/drivers/axisflashmap.c
+++ b/arch/cris/arch-v32/drivers/axisflashmap.c
@@ -1,7 +1,7 @@
/*
* Physical mapping layer for MTD using the Axis partitiontable format
*
- * Copyright (c) 2001, 2002, 2003 Axis Communications AB
+ * Copyright (c) 2001-2007 Axis Communications AB
*
* This file is under the GPL.
*
@@ -10,9 +10,6 @@
* tells us what other partitions to define. If there isn't, we use a default
* partition split defined below.
*
- * Copy of os/lx25/arch/cris/arch-v10/drivers/axisflashmap.c 1.5
- * with minor changes.
- *
*/
#include <linux/module.h>
@@ -27,7 +24,8 @@
#include <linux/mtd/mtdram.h>
#include <linux/mtd/partitions.h>
-#include <asm/arch/hwregs/config_defs.h>
+#include <linux/cramfs_fs.h>
+
#include <asm/axisflashmap.h>
#include <asm/mmu.h>
@@ -37,16 +35,24 @@
#define FLASH_UNCACHED_ADDR KSEG_E
#define FLASH_CACHED_ADDR KSEG_F
+#define PAGESIZE (512)
+
#if CONFIG_ETRAX_FLASH_BUSWIDTH==1
#define flash_data __u8
#elif CONFIG_ETRAX_FLASH_BUSWIDTH==2
#define flash_data __u16
#elif CONFIG_ETRAX_FLASH_BUSWIDTH==4
-#define flash_data __u16
+#define flash_data __u32
#endif
/* From head.S */
-extern unsigned long romfs_start, romfs_length, romfs_in_flash;
+extern unsigned long romfs_in_flash; /* 1 when romfs_start, _length in flash */
+extern unsigned long romfs_start, romfs_length;
+extern unsigned long nand_boot; /* 1 when booted from nand flash */
+
+struct partition_name {
+ char name[6];
+};
/* The master mtd for the entire flash. */
struct mtd_info* axisflash_mtd = NULL;
@@ -112,32 +118,20 @@ static struct map_info map_cse1 = {
.map_priv_1 = FLASH_UNCACHED_ADDR + MEM_CSE0_SIZE
};
-/* If no partition-table was found, we use this default-set. */
-#define MAX_PARTITIONS 7
-#define NUM_DEFAULT_PARTITIONS 3
+#define MAX_PARTITIONS 7
+#ifdef CONFIG_ETRAX_NANDBOOT
+#define NUM_DEFAULT_PARTITIONS 4
+#define DEFAULT_ROOTFS_PARTITION_NO 2
+#define DEFAULT_MEDIA_SIZE 0x2000000 /* 32 megs */
+#else
+#define NUM_DEFAULT_PARTITIONS 3
+#define DEFAULT_ROOTFS_PARTITION_NO (-1)
+#define DEFAULT_MEDIA_SIZE 0x800000 /* 8 megs */
+#endif
-/*
- * Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the
- * size of one flash block and "filesystem"-partition needs 5 blocks to be able
- * to use JFFS.
- */
-static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
- {
- .name = "boot firmware",
- .size = CONFIG_ETRAX_PTABLE_SECTOR,
- .offset = 0
- },
- {
- .name = "kernel",
- .size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR),
- .offset = CONFIG_ETRAX_PTABLE_SECTOR
- },
- {
- .name = "filesystem",
- .size = 5 * CONFIG_ETRAX_PTABLE_SECTOR,
- .offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR)
- }
-};
+#if (MAX_PARTITIONS < NUM_DEFAULT_PARTITIONS)
+#error MAX_PARTITIONS must be >= than NUM_DEFAULT_PARTITIONS
+#endif
/* Initialize the ones normally used. */
static struct mtd_partition axis_partitions[MAX_PARTITIONS] = {
@@ -178,6 +172,56 @@ static struct mtd_partition axis_partitions[MAX_PARTITIONS] = {
},
};
+
+/* If no partition-table was found, we use this default-set.
+ * Default flash size is 8MB (NOR). CONFIG_ETRAX_PTABLE_SECTOR is most
+ * likely the size of one flash block and "filesystem"-partition needs
+ * to be >=5 blocks to be able to use JFFS.
+ */
+static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
+ {
+ .name = "boot firmware",
+ .size = CONFIG_ETRAX_PTABLE_SECTOR,
+ .offset = 0
+ },
+ {
+ .name = "kernel",
+ .size = 10 * CONFIG_ETRAX_PTABLE_SECTOR,
+ .offset = CONFIG_ETRAX_PTABLE_SECTOR
+ },
+#define FILESYSTEM_SECTOR (11 * CONFIG_ETRAX_PTABLE_SECTOR)
+#ifdef CONFIG_ETRAX_NANDBOOT
+ {
+ .name = "rootfs",
+ .size = 10 * CONFIG_ETRAX_PTABLE_SECTOR,
+ .offset = FILESYSTEM_SECTOR
+ },
+#undef FILESYSTEM_SECTOR
+#define FILESYSTEM_SECTOR (21 * CONFIG_ETRAX_PTABLE_SECTOR)
+#endif
+ {
+ .name = "rwfs",
+ .size = DEFAULT_MEDIA_SIZE - FILESYSTEM_SECTOR,
+ .offset = FILESYSTEM_SECTOR
+ }
+};
+
+#ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE
+/* Main flash device */
+static struct mtd_partition main_partition = {
+ .name = "main",
+ .size = 0,
+ .offset = 0
+};
+#endif
+
+/* Auxilliary partition if we find another flash */
+static struct mtd_partition aux_partition = {
+ .name = "aux",
+ .size = 0,
+ .offset = 0
+};
+
/*
* Probe a chip select for AMD-compatible (JEDEC) or CFI-compatible flash
* chips in that order (because the amd_flash-driver is faster).
@@ -191,7 +235,7 @@ static struct mtd_info *probe_cs(struct map_info *map_cs)
map_cs->name, map_cs->size, map_cs->map_priv_1);
#ifdef CONFIG_MTD_CFI
- mtd_cs = do_map_probe("cfi_probe", map_cs);
+ mtd_cs = do_map_probe("cfi_probe", map_cs);
#endif
#ifdef CONFIG_MTD_JEDECPROBE
if (!mtd_cs)
@@ -204,7 +248,7 @@ static struct mtd_info *probe_cs(struct map_info *map_cs)
/*
* Probe each chip select individually for flash chips. If there are chips on
* both cse0 and cse1, the mtd_info structs will be concatenated to one struct
- * so that MTD partitions can cross chip boundaries.
+ * so that MTD partitions can cross chip boundries.
*
* The only known restriction to how you can mount your chips is that each
* chip select must hold similar flash chips. But you need external hardware
@@ -216,9 +260,8 @@ static struct mtd_info *flash_probe(void)
{
struct mtd_info *mtd_cse0;
struct mtd_info *mtd_cse1;
- struct mtd_info *mtd_nand = NULL;
struct mtd_info *mtd_total;
- struct mtd_info *mtds[3];
+ struct mtd_info *mtds[2];
int count = 0;
if ((mtd_cse0 = probe_cs(&map_cse0)) != NULL)
@@ -226,12 +269,7 @@ static struct mtd_info *flash_probe(void)
if ((mtd_cse1 = probe_cs(&map_cse1)) != NULL)
mtds[count++] = mtd_cse1;
-#ifdef CONFIG_ETRAX_NANDFLASH
- if ((mtd_nand = crisv32_nand_flash_probe()) != NULL)
- mtds[count++] = mtd_nand;
-#endif
-
- if (!mtd_cse0 && !mtd_cse1 && !mtd_nand) {
+ if (!mtd_cse0 && !mtd_cse1) {
/* No chip found. */
return NULL;
}
@@ -245,9 +283,7 @@ static struct mtd_info *flash_probe(void)
* So we use the MTD concatenation layer instead of further
* complicating the probing procedure.
*/
- mtd_total = mtd_concat_create(mtds,
- count,
- "cse0+cse1+nand");
+ mtd_total = mtd_concat_create(mtds, count, "cse0+cse1");
#else
printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
"(mis)configuration!\n", map_cse0.name, map_cse1.name);
@@ -255,61 +291,162 @@ static struct mtd_info *flash_probe(void)
#endif
if (!mtd_total) {
printk(KERN_ERR "%s and %s: Concatenation failed!\n",
- map_cse0.name, map_cse1.name);
+ map_cse0.name, map_cse1.name);
/* The best we can do now is to only use what we found
- * at cse0.
- */
+ * at cse0. */
mtd_total = mtd_cse0;
map_destroy(mtd_cse1);
}
- } else {
- mtd_total = mtd_cse0? mtd_cse0 : mtd_cse1 ? mtd_cse1 : mtd_nand;
-
- }
+ } else
+ mtd_total = mtd_cse0 ? mtd_cse0 : mtd_cse1;
return mtd_total;
}
-extern unsigned long crisv32_nand_boot;
-extern unsigned long crisv32_nand_cramfs_offset;
-
/*
* Probe the flash chip(s) and, if it succeeds, read the partition-table
* and register the partitions with MTD.
*/
static int __init init_axis_flash(void)
{
- struct mtd_info *mymtd;
+ struct mtd_info *main_mtd;
+ struct mtd_info *aux_mtd = NULL;
int err = 0;
int pidx = 0;
struct partitiontable_head *ptable_head = NULL;
struct partitiontable_entry *ptable;
- int use_default_ptable = 1; /* Until proven otherwise. */
- const char *pmsg = KERN_INFO " /dev/flash%d at 0x%08x, size 0x%08x\n";
- static char page[512];
+ int ptable_ok = 0;
+ static char page[PAGESIZE];
size_t len;
+ int ram_rootfs_partition = -1; /* -1 => no RAM rootfs partition */
+ int part;
+
+ /* We need a root fs. If it resides in RAM, we need to use an
+ * MTDRAM device, so it must be enabled in the kernel config,
+ * but its size must be configured as 0 so as not to conflict
+ * with our usage.
+ */
+#if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || (CONFIG_MTDRAM_ABS_POS != 0)
+ if (!romfs_in_flash && !nand_boot) {
+ printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM "
+ "device; configure CONFIG_MTD_MTDRAM with size = 0!\n");
+ panic("This kernel cannot boot from RAM!\n");
+ }
+#endif
+
+#ifndef CONFIG_ETRAX_VCS_SIM
+ main_mtd = flash_probe();
+ if (main_mtd)
+ printk(KERN_INFO "%s: 0x%08x bytes of NOR flash memory.\n",
+ main_mtd->name, main_mtd->size);
+
+#ifdef CONFIG_ETRAX_NANDFLASH
+ aux_mtd = crisv32_nand_flash_probe();
+ if (aux_mtd)
+ printk(KERN_INFO "%s: 0x%08x bytes of NAND flash memory.\n",
+ aux_mtd->name, aux_mtd->size);
+
+#ifdef CONFIG_ETRAX_NANDBOOT
+ {
+ struct mtd_info *tmp_mtd;
-#ifndef CONFIG_ETRAXFS_SIM
- mymtd = flash_probe();
- mymtd->read(mymtd, CONFIG_ETRAX_PTABLE_SECTOR, 512, &len, page);
- ptable_head = (struct partitiontable_head *)(page + PARTITION_TABLE_OFFSET);
+ printk(KERN_INFO "axisflashmap: Set to boot from NAND flash, "
+ "making NAND flash primary device.\n");
+ tmp_mtd = main_mtd;
+ main_mtd = aux_mtd;
+ aux_mtd = tmp_mtd;
+ }
+#endif /* CONFIG_ETRAX_NANDBOOT */
+#endif /* CONFIG_ETRAX_NANDFLASH */
- if (!mymtd) {
+ if (!main_mtd && !aux_mtd) {
/* There's no reason to use this module if no flash chip can
* be identified. Make sure that's understood.
*/
printk(KERN_INFO "axisflashmap: Found no flash chip.\n");
- } else {
- printk(KERN_INFO "%s: 0x%08x bytes of flash memory.\n",
- mymtd->name, mymtd->size);
- axisflash_mtd = mymtd;
}
- if (mymtd) {
- mymtd->owner = THIS_MODULE;
+#if 0 /* Dump flash memory so we can see what is going on */
+ if (main_mtd) {
+ int sectoraddr, i;
+ for (sectoraddr = 0; sectoraddr < 2*65536+4096;
+ sectoraddr += PAGESIZE) {
+ main_mtd->read(main_mtd, sectoraddr, PAGESIZE, &len,
+ page);
+ printk(KERN_INFO
+ "Sector at %d (length %d):\n",
+ sectoraddr, len);
+ for (i = 0; i < PAGESIZE; i += 16) {
+ printk(KERN_INFO
+ "%02x %02x %02x %02x "
+ "%02x %02x %02x %02x "
+ "%02x %02x %02x %02x "
+ "%02x %02x %02x %02x\n",
+ page[i] & 255, page[i+1] & 255,
+ page[i+2] & 255, page[i+3] & 255,
+ page[i+4] & 255, page[i+5] & 255,
+ page[i+6] & 255, page[i+7] & 255,
+ page[i+8] & 255, page[i+9] & 255,
+ page[i+10] & 255, page[i+11] & 255,
+ page[i+12] & 255, page[i+13] & 255,
+ page[i+14] & 255, page[i+15] & 255);
+ }
+ }
+ }
+#endif
+
+ if (main_mtd) {
+ main_mtd->owner = THIS_MODULE;
+ axisflash_mtd = main_mtd;
+
+ loff_t ptable_sector = CONFIG_ETRAX_PTABLE_SECTOR;
+
+ /* First partition (rescue) is always set to the default. */
+ pidx++;
+#ifdef CONFIG_ETRAX_NANDBOOT
+ /* We know where the partition table should be located,
+ * it will be in first good block after that.
+ */
+ int blockstat;
+ do {
+ blockstat = main_mtd->block_isbad(main_mtd,
+ ptable_sector);
+ if (blockstat < 0)
+ ptable_sector = 0; /* read error */
+ else if (blockstat)
+ ptable_sector += main_mtd->erasesize;
+ } while (blockstat && ptable_sector);
+#endif
+ if (ptable_sector) {
+ main_mtd->read(main_mtd, ptable_sector, PAGESIZE,
+ &len, page);
+ ptable_head = &((struct partitiontable *) page)->head;
+ }
+
+#if 0 /* Dump partition table so we can see what is going on */
+ printk(KERN_INFO
+ "axisflashmap: flash read %d bytes at 0x%08x, data: "
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ len, CONFIG_ETRAX_PTABLE_SECTOR,
+ page[0] & 255, page[1] & 255,
+ page[2] & 255, page[3] & 255,
+ page[4] & 255, page[5] & 255,
+ page[6] & 255, page[7] & 255);
+ printk(KERN_INFO
+ "axisflashmap: partition table offset %d, data: "
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ PARTITION_TABLE_OFFSET,
+ page[PARTITION_TABLE_OFFSET+0] & 255,
+ page[PARTITION_TABLE_OFFSET+1] & 255,
+ page[PARTITION_TABLE_OFFSET+2] & 255,
+ page[PARTITION_TABLE_OFFSET+3] & 255,
+ page[PARTITION_TABLE_OFFSET+4] & 255,
+ page[PARTITION_TABLE_OFFSET+5] & 255,
+ page[PARTITION_TABLE_OFFSET+6] & 255,
+ page[PARTITION_TABLE_OFFSET+7] & 255);
+#endif
}
- pidx++; /* First partition is always set to the default. */
if (ptable_head && (ptable_head->magic == PARTITION_TABLE_MAGIC)
&& (ptable_head->size <
@@ -322,7 +459,6 @@ static int __init init_axis_flash(void)
/* Looks like a start, sane length and end of a
* partition table, lets check csum etc.
*/
- int ptable_ok = 0;
struct partitiontable_entry *max_addr =
(struct partitiontable_entry *)
((unsigned long)ptable_head + sizeof(*ptable_head) +
@@ -346,104 +482,170 @@ static int __init init_axis_flash(void)
ptable_ok = (csum == ptable_head->checksum);
/* Read the entries and use/show the info. */
- printk(KERN_INFO " Found a%s partition table at 0x%p-0x%p.\n",
+ printk(KERN_INFO "axisflashmap: "
+ "Found a%s partition table at 0x%p-0x%p.\n",
(ptable_ok ? " valid" : "n invalid"), ptable_head,
max_addr);
/* We have found a working bootblock. Now read the
- * partition table. Scan the table. It ends when
- * there is 0xffffffff, that is, empty flash.
+ * partition table. Scan the table. It ends with 0xffffffff.
*/
while (ptable_ok
- && ptable->offset != 0xffffffff
+ && ptable->offset != PARTITIONTABLE_END_MARKER
&& ptable < max_addr
- && pidx < MAX_PARTITIONS) {
+ && pidx < MAX_PARTITIONS - 1) {
- axis_partitions[pidx].offset = offset + ptable->offset + (crisv32_nand_boot ? 16384 : 0);
- axis_partitions[pidx].size = ptable->size;
-
- printk(pmsg, pidx, axis_partitions[pidx].offset,
- axis_partitions[pidx].size);
+ axis_partitions[pidx].offset = offset + ptable->offset;
+#ifdef CONFIG_ETRAX_NANDFLASH
+ if (main_mtd->type == MTD_NANDFLASH) {
+ axis_partitions[pidx].size =
+ (((ptable+1)->offset ==
+ PARTITIONTABLE_END_MARKER) ?
+ main_mtd->size :
+ ((ptable+1)->offset + offset)) -
+ (ptable->offset + offset);
+
+ } else
+#endif /* CONFIG_ETRAX_NANDFLASH */
+ axis_partitions[pidx].size = ptable->size;
+#ifdef CONFIG_ETRAX_NANDBOOT
+ /* Save partition number of jffs2 ro partition.
+ * Needed if RAM booting or root file system in RAM.
+ */
+ if (!nand_boot &&
+ ram_rootfs_partition < 0 && /* not already set */
+ ptable->type == PARTITION_TYPE_JFFS2 &&
+ (ptable->flags & PARTITION_FLAGS_READONLY_MASK) ==
+ PARTITION_FLAGS_READONLY)
+ ram_rootfs_partition = pidx;
+#endif /* CONFIG_ETRAX_NANDBOOT */
pidx++;
ptable++;
}
- use_default_ptable = !ptable_ok;
}
- if (romfs_in_flash) {
- /* Add an overlapping device for the root partition (romfs). */
+ /* Decide whether to use default partition table. */
+ /* Only use default table if we actually have a device (main_mtd) */
- axis_partitions[pidx].name = "romfs";
- if (crisv32_nand_boot) {
- char* data = kmalloc(1024, GFP_KERNEL);
- int len;
- int offset = crisv32_nand_cramfs_offset & ~(1024-1);
- char* tmp;
-
- mymtd->read(mymtd, offset, 1024, &len, data);
- tmp = &data[crisv32_nand_cramfs_offset % 512];
- axis_partitions[pidx].size = *(unsigned*)(tmp + 4);
- axis_partitions[pidx].offset = crisv32_nand_cramfs_offset;
- kfree(data);
- } else {
- axis_partitions[pidx].size = romfs_length;
- axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR;
- }
+ struct mtd_partition *partition = &axis_partitions[0];
+ if (main_mtd && !ptable_ok) {
+ memcpy(axis_partitions, axis_default_partitions,
+ sizeof(axis_default_partitions));
+ pidx = NUM_DEFAULT_PARTITIONS;
+ ram_rootfs_partition = DEFAULT_ROOTFS_PARTITION_NO;
+ }
+ /* Add artificial partitions for rootfs if necessary */
+ if (romfs_in_flash) {
+ /* rootfs is in directly accessible flash memory = NOR flash.
+ Add an overlapping device for the rootfs partition. */
+ printk(KERN_INFO "axisflashmap: Adding partition for "
+ "overlapping root file system image\n");
+ axis_partitions[pidx].size = romfs_length;
+ axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR;
+ axis_partitions[pidx].name = "romfs";
axis_partitions[pidx].mask_flags |= MTD_WRITEABLE;
-
- printk(KERN_INFO
- " Adding readonly flash partition for romfs image:\n");
- printk(pmsg, pidx, axis_partitions[pidx].offset,
- axis_partitions[pidx].size);
+ ram_rootfs_partition = -1;
pidx++;
- }
-
- if (mymtd) {
- if (use_default_ptable) {
- printk(KERN_INFO " Using default partition table.\n");
- err = add_mtd_partitions(mymtd, axis_default_partitions,
- NUM_DEFAULT_PARTITIONS);
- } else {
- err = add_mtd_partitions(mymtd, axis_partitions, pidx);
+ } else if (romfs_length && !nand_boot) {
+ /* romfs exists in memory, but not in flash, so must be in RAM.
+ * Configure an MTDRAM partition. */
+ if (ram_rootfs_partition < 0) {
+ /* None set yet, put it at the end */
+ ram_rootfs_partition = pidx;
+ pidx++;
}
+ printk(KERN_INFO "axisflashmap: Adding partition for "
+ "root file system image in RAM\n");
+ axis_partitions[ram_rootfs_partition].size = romfs_length;
+ axis_partitions[ram_rootfs_partition].offset = romfs_start;
+ axis_partitions[ram_rootfs_partition].name = "romfs";
+ axis_partitions[ram_rootfs_partition].mask_flags |=
+ MTD_WRITEABLE;
+ }
- if (err) {
- panic("axisflashmap could not add MTD partitions!\n");
- }
+#ifdef CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE
+ if (main_mtd) {
+ main_partition.size = main_mtd->size;
+ err = add_mtd_partitions(main_mtd, &main_partition, 1);
+ if (err)
+ panic("axisflashmap: Could not initialize "
+ "partition for whole main mtd device!\n");
}
-/* CONFIG_EXTRAXFS_SIM */
#endif
- if (!romfs_in_flash) {
- /* Create an RAM device for the root partition (romfs). */
+ /* Now, register all partitions with mtd.
+ * We do this one at a time so we can slip in an MTDRAM device
+ * in the proper place if required. */
+
+ for (part = 0; part < pidx; part++) {
+ if (part == ram_rootfs_partition) {
+ /* add MTDRAM partition here */
+ struct mtd_info *mtd_ram;
+
+ mtd_ram = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
+ if (!mtd_ram)
+ panic("axisflashmap: Couldn't allocate memory "
+ "for mtd_info!\n");
+ printk(KERN_INFO "axisflashmap: Adding RAM partition "
+ "for rootfs image.\n");
+ err = mtdram_init_device(mtd_ram,
+ (void *)partition[part].offset,
+ partition[part].size,
+ partition[part].name);
+ if (err)
+ panic("axisflashmap: Could not initialize "
+ "MTD RAM device!\n");
+ /* JFFS2 likes to have an erasesize. Keep potential
+ * JFFS2 rootfs happy by providing one. Since image
+ * was most likely created for main mtd, use that
+ * erasesize, if available. Otherwise, make a guess. */
+ mtd_ram->erasesize = (main_mtd ? main_mtd->erasesize :
+ CONFIG_ETRAX_PTABLE_SECTOR);
+ } else {
+ err = add_mtd_partitions(main_mtd, &partition[part], 1);
+ if (err)
+ panic("axisflashmap: Could not add mtd "
+ "partition %d\n", part);
+ }
+ }
+#endif /* CONFIG_EXTRAX_VCS_SIM */
+
+#ifdef CONFIG_ETRAX_VCS_SIM
+ /* For simulator, always use a RAM partition.
+ * The rootfs will be found after the kernel in RAM,
+ * with romfs_start and romfs_end indicating location and size.
+ */
+ struct mtd_info *mtd_ram;
+
+ mtd_ram = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
+ if (!mtd_ram) {
+ panic("axisflashmap: Couldn't allocate memory for "
+ "mtd_info!\n");
+ }
-#if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) || (CONFIG_MTDRAM_ABS_POS != 0)
- /* No use trying to boot this kernel from RAM. Panic! */
- printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM "
- "device due to kernel (mis)configuration!\n");
- panic("This kernel cannot boot from RAM!\n");
-#else
- struct mtd_info *mtd_ram;
+ printk(KERN_INFO "axisflashmap: Adding RAM partition for romfs, "
+ "at %u, size %u\n",
+ (unsigned) romfs_start, (unsigned) romfs_length);
- mtd_ram = kmalloc(sizeof(struct mtd_info),
- GFP_KERNEL);
- if (!mtd_ram) {
- panic("axisflashmap couldn't allocate memory for "
- "mtd_info!\n");
- }
+ err = mtdram_init_device(mtd_ram, (void *)romfs_start,
+ romfs_length, "romfs");
+ if (err) {
+ panic("axisflashmap: Could not initialize MTD RAM "
+ "device!\n");
+ }
+#endif /* CONFIG_EXTRAX_VCS_SIM */
- printk(KERN_INFO " Adding RAM partition for romfs image:\n");
- printk(pmsg, pidx, romfs_start, romfs_length);
+#ifndef CONFIG_ETRAX_VCS_SIM
+ if (aux_mtd) {
+ aux_partition.size = aux_mtd->size;
+ err = add_mtd_partitions(aux_mtd, &aux_partition, 1);
+ if (err)
+ panic("axisflashmap: Could not initialize "
+ "aux mtd device!\n");
- err = mtdram_init_device(mtd_ram, (void*)romfs_start,
- romfs_length, "romfs");
- if (err) {
- panic("axisflashmap could not initialize MTD RAM "
- "device!\n");
- }
-#endif
}
+#endif /* CONFIG_EXTRAX_VCS_SIM */
return err;
}
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index e8914d40169..9fb58202be9 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -1,8 +1,7 @@
-/* $Id: cryptocop.c,v 1.13 2005/04/21 17:27:55 henriken Exp $
- *
+/*
* Stream co-processor driver for the ETRAX FS
*
- * Copyright (C) 2003-2005 Axis Communications AB
+ * Copyright (C) 2003-2007 Axis Communications AB
*/
#include <linux/init.h>
@@ -25,17 +24,29 @@
#include <asm/signal.h>
#include <asm/irq.h>
-#include <asm/arch/dma.h>
-#include <asm/arch/hwregs/dma.h>
-#include <asm/arch/hwregs/reg_map.h>
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/intr_vect_defs.h>
-
-#include <asm/arch/hwregs/strcop.h>
-#include <asm/arch/hwregs/strcop_defs.h>
-#include <asm/arch/cryptocop.h>
-
-
+#include <dma.h>
+#include <hwregs/dma.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/intr_vect_defs.h>
+
+#include <hwregs/strcop.h>
+#include <hwregs/strcop_defs.h>
+#include <cryptocop.h>
+
+#ifdef CONFIG_ETRAXFS
+#define IN_DMA 9
+#define OUT_DMA 8
+#define IN_DMA_INST regi_dma9
+#define OUT_DMA_INST regi_dma8
+#define DMA_IRQ DMA9_INTR_VECT
+#else
+#define IN_DMA 3
+#define OUT_DMA 2
+#define IN_DMA_INST regi_dma3
+#define OUT_DMA_INST regi_dma2
+#define DMA_IRQ DMA3_INTR_VECT
+#endif
#define DESCR_ALLOC_PAD (31)
@@ -1886,14 +1897,14 @@ static void cryptocop_do_tasklet(unsigned long unused)
}
static irqreturn_t
-dma_done_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+dma_done_interrupt(int irq, void *dev_id)
{
struct cryptocop_prio_job *done_job;
reg_dma_rw_ack_intr ack_intr = {
.data = 1,
};
- REG_WR (dma, regi_dma9, rw_ack_intr, ack_intr);
+ REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
DEBUG(printk("cryptocop DMA done\n"));
@@ -1937,7 +1948,6 @@ dma_done_interrupt(int irq, void *dev_id, struct pt_regs * regs)
static int init_cryptocop(void)
{
unsigned long flags;
- reg_intr_vect_rw_mask intr_mask;
reg_dma_rw_cfg dma_cfg = {.en = 1};
reg_dma_rw_intr_mask intr_mask_in = {.data = regk_dma_yes}; /* Only want descriptor interrupts from the DMA in channel. */
reg_dma_rw_ack_intr ack_intr = {.data = 1,.in_eop = 1 };
@@ -1950,10 +1960,14 @@ static int init_cryptocop(void)
.en = 1
};
- if (request_irq(DMA9_INTR_VECT, dma_done_interrupt, 0, "stream co-processor DMA", NULL)) panic("request_irq stream co-processor irq dma9");
+ if (request_irq(DMA_IRQ, dma_done_interrupt, 0,
+ "stream co-processor DMA", NULL))
+ panic("request_irq stream co-processor irq dma9");
- (void)crisv32_request_dma(8, "strcop", DMA_PANIC_ON_ERROR, 0, dma_strp);
- (void)crisv32_request_dma(9, "strcop", DMA_PANIC_ON_ERROR, 0, dma_strp);
+ (void)crisv32_request_dma(OUT_DMA, "strcop", DMA_PANIC_ON_ERROR,
+ 0, dma_strp);
+ (void)crisv32_request_dma(IN_DMA, "strcop", DMA_PANIC_ON_ERROR,
+ 0, dma_strp);
local_irq_save(flags);
@@ -1963,24 +1977,19 @@ static int init_cryptocop(void)
strcop_cfg.en = 1;
REG_WR(strcop, regi_strcop, rw_cfg, strcop_cfg);
- /* Enable DMA9 interrupt */
- intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);
- intr_mask.dma9 = 1;
- REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
-
/* Enable DMAs. */
- REG_WR(dma, regi_dma9, rw_cfg, dma_cfg); /* input DMA */
- REG_WR(dma, regi_dma8, rw_cfg, dma_cfg); /* output DMA */
+ REG_WR(dma, IN_DMA_INST, rw_cfg, dma_cfg); /* input DMA */
+ REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_cfg); /* output DMA */
/* Set up wordsize = 4 for DMAs. */
- DMA_WR_CMD (regi_dma8, regk_dma_set_w_size4);
- DMA_WR_CMD (regi_dma9, regk_dma_set_w_size4);
+ DMA_WR_CMD(OUT_DMA_INST, regk_dma_set_w_size4);
+ DMA_WR_CMD(IN_DMA_INST, regk_dma_set_w_size4);
/* Enable interrupts. */
- REG_WR(dma, regi_dma9, rw_intr_mask, intr_mask_in);
+ REG_WR(dma, IN_DMA_INST, rw_intr_mask, intr_mask_in);
/* Clear intr ack. */
- REG_WR(dma, regi_dma9, rw_ack_intr, ack_intr);
+ REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
local_irq_restore(flags);
@@ -1991,7 +2000,6 @@ static int init_cryptocop(void)
static void release_cryptocop(void)
{
unsigned long flags;
- reg_intr_vect_rw_mask intr_mask;
reg_dma_rw_cfg dma_cfg = {.en = 0};
reg_dma_rw_intr_mask intr_mask_in = {0};
reg_dma_rw_ack_intr ack_intr = {.data = 1,.in_eop = 1 };
@@ -1999,26 +2007,21 @@ static void release_cryptocop(void)
local_irq_save(flags);
/* Clear intr ack. */
- REG_WR(dma, regi_dma9, rw_ack_intr, ack_intr);
-
- /* Disable DMA9 interrupt */
- intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);
- intr_mask.dma9 = 0;
- REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
+ REG_WR(dma, IN_DMA_INST, rw_ack_intr, ack_intr);
/* Disable DMAs. */
- REG_WR(dma, regi_dma9, rw_cfg, dma_cfg); /* input DMA */
- REG_WR(dma, regi_dma8, rw_cfg, dma_cfg); /* output DMA */
+ REG_WR(dma, IN_DMA_INST, rw_cfg, dma_cfg); /* input DMA */
+ REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_cfg); /* output DMA */
/* Disable interrupts. */
- REG_WR(dma, regi_dma9, rw_intr_mask, intr_mask_in);
+ REG_WR(dma, IN_DMA_INST, rw_intr_mask, intr_mask_in);
local_irq_restore(flags);
- free_irq(DMA9_INTR_VECT, NULL);
+ free_irq(DMA_IRQ, NULL);
- (void)crisv32_free_dma(8);
- (void)crisv32_free_dma(9);
+ (void)crisv32_free_dma(OUT_DMA);
+ (void)crisv32_free_dma(IN_DMA);
}
@@ -2076,13 +2079,13 @@ static void cryptocop_job_queue_close(void)
reg_dma_rw_cfg dma_out_cfg, dma_in_cfg;
/* Stop DMA. */
- dma_out_cfg = REG_RD(dma, regi_dma8, rw_cfg);
+ dma_out_cfg = REG_RD(dma, OUT_DMA_INST, rw_cfg);
dma_out_cfg.en = regk_dma_no;
- REG_WR(dma, regi_dma8, rw_cfg, dma_out_cfg);
+ REG_WR(dma, OUT_DMA_INST, rw_cfg, dma_out_cfg);
- dma_in_cfg = REG_RD(dma, regi_dma9, rw_cfg);
+ dma_in_cfg = REG_RD(dma, IN_DMA_INST, rw_cfg);
dma_in_cfg.en = regk_dma_no;
- REG_WR(dma, regi_dma9, rw_cfg, dma_in_cfg);
+ REG_WR(dma, IN_DMA_INST, rw_cfg, dma_in_cfg);
/* Disble the cryptocop. */
rw_cfg = REG_RD(strcop, regi_strcop, rw_cfg);
@@ -2226,10 +2229,11 @@ static void cryptocop_start_job(void)
&pj->iop->ctx_out, (char*)virt_to_phys(&pj->iop->ctx_out)));
/* Start input DMA. */
- DMA_START_CONTEXT(regi_dma9, virt_to_phys(&pj->iop->ctx_in));
+ flush_dma_context(&pj->iop->ctx_in);
+ DMA_START_CONTEXT(IN_DMA_INST, virt_to_phys(&pj->iop->ctx_in));
/* Start output DMA. */
- DMA_START_CONTEXT(regi_dma8, virt_to_phys(&pj->iop->ctx_out));
+ DMA_START_CONTEXT(OUT_DMA_INST, virt_to_phys(&pj->iop->ctx_out));
spin_unlock_irqrestore(&running_job_lock, running_job_flags);
DEBUG(printk("cryptocop_start_job: exiting\n"));
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index f1edd2e359b..c2fb7a5c139 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -19,10 +19,10 @@
*!
*! ---------------------------------------------------------------------------
*!
-*! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN
+*! (C) Copyright 1999-2007 Axis Communications AB, LUND, SWEDEN
*!
*!***************************************************************************/
-/* $Id: i2c.c,v 1.2 2005/05/09 15:29:49 starvik Exp $ */
+
/****************** INCLUDE FILES SECTION ***********************************/
#include <linux/module.h>
@@ -79,6 +79,8 @@ static const char i2c_name[] = "i2c";
#define i2c_delay(usecs) udelay(usecs)
+static DEFINE_SPINLOCK(i2c_lock); /* Protect directions etc */
+
/****************** VARIABLE SECTION ************************************/
static struct crisv32_iopin cris_i2c_clk;
@@ -252,6 +254,7 @@ i2c_getack(void)
* generate ACK clock pulse
*/
i2c_clk(I2C_CLOCK_HIGH);
+#if 0
/*
* Use PORT PB instead of I2C
* for input. (I2C not working)
@@ -264,6 +267,8 @@ i2c_getack(void)
i2c_data(1);
i2c_disable();
i2c_dir_in();
+#endif
+
/*
* now wait for ack
*/
@@ -271,11 +276,11 @@ i2c_getack(void)
/*
* check for ack
*/
- if(i2c_getbit())
+ if (i2c_getbit())
ack = 0;
i2c_delay(CLOCK_HIGH_TIME/2);
- if(!ack){
- if(!i2c_getbit()) /* receiver pulled SDA low */
+ if (!ack) {
+ if (!i2c_getbit()) /* receiver pulld SDA low */
ack = 1;
i2c_delay(CLOCK_HIGH_TIME/2);
}
@@ -285,6 +290,7 @@ i2c_getack(void)
* before we enable our output. If we keep data high
* and enable output, we would generate a stop condition.
*/
+#if 0
i2c_data(I2C_DATA_LOW);
/*
@@ -292,6 +298,7 @@ i2c_getack(void)
*/
i2c_enable();
i2c_dir_out();
+#endif
i2c_clk(I2C_CLOCK_LOW);
i2c_delay(CLOCK_HIGH_TIME/4);
/*
@@ -375,6 +382,121 @@ i2c_sendnack(void)
/*#---------------------------------------------------------------------------
*#
+*# FUNCTION NAME: i2c_write
+*#
+*# DESCRIPTION : Writes a value to an I2C device
+*#
+*#--------------------------------------------------------------------------*/
+int
+i2c_write(unsigned char theSlave, void *data, size_t nbytes)
+{
+ int error, cntr = 3;
+ unsigned char bytes_wrote = 0;
+ unsigned char value;
+ unsigned long flags;
+
+ spin_lock_irqsave(&i2c_lock, flags);
+
+ do {
+ error = 0;
+
+ i2c_start();
+ /*
+ * send slave address
+ */
+ i2c_outbyte((theSlave & 0xfe));
+ /*
+ * wait for ack
+ */
+ if (!i2c_getack())
+ error = 1;
+ /*
+ * send data
+ */
+ for (bytes_wrote = 0; bytes_wrote < nbytes; bytes_wrote++) {
+ memcpy(&value, data + bytes_wrote, sizeof value);
+ i2c_outbyte(value);
+ /*
+ * now it's time to wait for ack
+ */
+ if (!i2c_getack())
+ error |= 4;
+ }
+ /*
+ * end byte stream
+ */
+ i2c_stop();
+
+ } while (error && cntr--);
+
+ i2c_delay(CLOCK_LOW_TIME);
+
+ spin_unlock_irqrestore(&i2c_lock, flags);
+
+ return -error;
+}
+
+/*#---------------------------------------------------------------------------
+*#
+*# FUNCTION NAME: i2c_read
+*#
+*# DESCRIPTION : Reads a value from an I2C device
+*#
+*#--------------------------------------------------------------------------*/
+int
+i2c_read(unsigned char theSlave, void *data, size_t nbytes)
+{
+ unsigned char b = 0;
+ unsigned char bytes_read = 0;
+ int error, cntr = 3;
+ unsigned long flags;
+
+ spin_lock_irqsave(&i2c_lock, flags);
+
+ do {
+ error = 0;
+ memset(data, 0, nbytes);
+ /*
+ * generate start condition
+ */
+ i2c_start();
+ /*
+ * send slave address
+ */
+ i2c_outbyte((theSlave | 0x01));
+ /*
+ * wait for ack
+ */
+ if (!i2c_getack())
+ error = 1;
+ /*
+ * fetch data
+ */
+ for (bytes_read = 0; bytes_read < nbytes; bytes_read++) {
+ b = i2c_inbyte();
+ memcpy(data + bytes_read, &b, sizeof b);
+
+ if (bytes_read < (nbytes - 1))
+ i2c_sendack();
+ }
+ /*
+ * last received byte needs to be nacked
+ * instead of acked
+ */
+ i2c_sendnack();
+ /*
+ * end sequence
+ */
+ i2c_stop();
+ } while (error && cntr--);
+
+ spin_unlock_irqrestore(&i2c_lock, flags);
+
+ return -error;
+}
+
+/*#---------------------------------------------------------------------------
+*#
*# FUNCTION NAME: i2c_writereg
*#
*# DESCRIPTION : Writes a value to an I2C device
@@ -387,12 +509,10 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg,
int error, cntr = 3;
unsigned long flags;
+ spin_lock_irqsave(&i2c_lock, flags);
+
do {
error = 0;
- /*
- * we don't like to be interrupted
- */
- local_irq_save(flags);
i2c_start();
/*
@@ -427,15 +547,12 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg,
* end byte stream
*/
i2c_stop();
- /*
- * enable interrupt again
- */
- local_irq_restore(flags);
-
} while(error && cntr--);
i2c_delay(CLOCK_LOW_TIME);
+ spin_unlock_irqrestore(&i2c_lock, flags);
+
return -error;
}
@@ -453,13 +570,11 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
int error, cntr = 3;
unsigned long flags;
+ spin_lock_irqsave(&i2c_lock, flags);
+
do {
error = 0;
/*
- * we don't like to be interrupted
- */
- local_irq_save(flags);
- /*
* generate start condition
*/
i2c_start();
@@ -482,7 +597,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
* now it's time to wait for ack
*/
if(!i2c_getack())
- error = 1;
+ error |= 2;
/*
* repeat start condition
*/
@@ -496,7 +611,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
* wait for ack
*/
if(!i2c_getack())
- error = 1;
+ error |= 4;
/*
* fetch register
*/
@@ -510,13 +625,11 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
* end sequence
*/
i2c_stop();
- /*
- * enable interrupt again
- */
- local_irq_restore(flags);
} while(error && cntr--);
+ spin_unlock_irqrestore(&i2c_lock, flags);
+
return b;
}
@@ -540,7 +653,7 @@ i2c_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) {
- return -EINVAL;
+ return -ENOTTY;
}
switch (_IOC_NR(cmd)) {
@@ -580,31 +693,52 @@ static const struct file_operations i2c_fops = {
.release = i2c_release,
};
-int __init
-i2c_init(void)
+static int __init i2c_init(void)
{
- int res;
+ static int res;
+ static int first = 1;
- /* Setup and enable the Port B I2C interface */
+ if (!first)
+ return res;
- crisv32_io_get_name(&cris_i2c_data, CONFIG_ETRAX_I2C_DATA_PORT);
- crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_I2C_CLK_PORT);
+ first = 0;
+
+ /* Setup and enable the DATA and CLK pins */
+
+ res = crisv32_io_get_name(&cris_i2c_data,
+ CONFIG_ETRAX_V32_I2C_DATA_PORT);
+ if (res < 0)
+ return res;
+
+ res = crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_V32_I2C_CLK_PORT);
+ crisv32_io_set_dir(&cris_i2c_clk, crisv32_io_dir_out);
+
+ return res;
+}
+
+
+static int __init i2c_register(void)
+{
+ int res;
+
+ res = i2c_init();
+ if (res < 0)
+ return res;
/* register char device */
res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops);
- if(res < 0) {
+ if (res < 0) {
printk(KERN_ERR "i2c: couldn't get a major number.\n");
return res;
}
- printk(KERN_INFO "I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n");
+ printk(KERN_INFO
+ "I2C driver v2.2, (c) 1999-2007 Axis Communications AB\n");
return 0;
}
-
/* this makes sure that i2c_init is called during boot */
-
-module_init(i2c_init);
+module_init(i2c_register);
/****************** END OF FILE i2c.c ********************************/
diff --git a/arch/cris/arch-v32/drivers/i2c.h b/arch/cris/arch-v32/drivers/i2c.h
index bfe1a13f9f3..c073cf4ba01 100644
--- a/arch/cris/arch-v32/drivers/i2c.h
+++ b/arch/cris/arch-v32/drivers/i2c.h
@@ -3,6 +3,8 @@
/* High level I2C actions */
int __init i2c_init(void);
+int i2c_write(unsigned char theSlave, void *data, size_t nbytes);
+int i2c_read(unsigned char theSlave, void *data, size_t nbytes);
int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue);
unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg);
diff --git a/arch/cris/arch-v32/drivers/iop_fw_load.c b/arch/cris/arch-v32/drivers/iop_fw_load.c
index f4bdc1dfa32..3b3857ec1f1 100644
--- a/arch/cris/arch-v32/drivers/iop_fw_load.c
+++ b/arch/cris/arch-v32/drivers/iop_fw_load.c
@@ -1,5 +1,4 @@
-/* $Id: iop_fw_load.c,v 1.4 2005/04/07 09:27:46 larsv Exp $
- *
+/*
* Firmware loader for ETRAX FS IO-Processor
*
* Copyright (C) 2004 Axis Communications AB
@@ -11,12 +10,13 @@
#include <linux/device.h>
#include <linux/firmware.h>
-#include <asm/arch/hwregs/reg_map.h>
-#include <asm/arch/hwregs/iop/iop_reg_space.h>
-#include <asm/arch/hwregs/iop/iop_mpu_macros.h>
-#include <asm/arch/hwregs/iop/iop_mpu_defs.h>
-#include <asm/arch/hwregs/iop/iop_spu_defs.h>
-#include <asm/arch/hwregs/iop/iop_sw_cpu_defs.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/iop/iop_reg_space.h>
+#include <hwregs/iop/iop_mpu_macros.h>
+#include <hwregs/iop/iop_mpu_defs.h>
+#include <hwregs/iop/iop_spu_defs.h>
+#include <hwregs/iop/iop_sw_cpu_defs.h>
#define IOP_TIMEOUT 100
diff --git a/arch/cris/arch-v32/drivers/mach-a3/Makefile b/arch/cris/arch-v32/drivers/mach-a3/Makefile
new file mode 100644
index 00000000000..5c6d2a2a080
--- /dev/null
+++ b/arch/cris/arch-v32/drivers/mach-a3/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Etrax-specific drivers
+#
+
+obj-$(CONFIG_ETRAX_NANDFLASH) += nandflash.o
+obj-$(CONFIG_ETRAX_GPIO) += gpio.o
diff --git a/arch/cris/arch-v32/drivers/mach-a3/gpio.c b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
new file mode 100644
index 00000000000..de107dad9f4
--- /dev/null
+++ b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
@@ -0,0 +1,984 @@
+/*
+ * Artec-3 general port I/O device
+ *
+ * Copyright (c) 2007 Axis Communications AB
+ *
+ * Authors: Bjorn Wesen (initial version)
+ * Ola Knutsson (LED handling)
+ * Johan Adolfsson (read/set directions, write, port G,
+ * port to ETRAX FS.
+ * Ricard Wanderlof (PWM for Artpec-3)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
+#include <asm/etraxgpio.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/gio_defs.h>
+#include <hwregs/intr_vect_defs.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/arch/mach/pinmux.h>
+
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+#include "../i2c.h"
+
+#define VIRT_I2C_ADDR 0x40
+#endif
+
+/* The following gio ports on ARTPEC-3 is available:
+ * pa 32 bits
+ * pb 32 bits
+ * pc 16 bits
+ * each port has a rw_px_dout, r_px_din and rw_px_oe register.
+ */
+
+#define GPIO_MAJOR 120 /* experimental MAJOR number */
+
+#define I2C_INTERRUPT_BITS 0x300 /* i2c0_done and i2c1_done bits */
+
+#define D(x)
+
+#if 0
+static int dp_cnt;
+#define DP(x) \
+ do { \
+ dp_cnt++; \
+ if (dp_cnt % 1000 == 0) \
+ x; \
+ } while (0)
+#else
+#define DP(x)
+#endif
+
+static char gpio_name[] = "etrax gpio";
+
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg);
+#endif
+static int gpio_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static ssize_t gpio_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *off);
+static int gpio_open(struct inode *inode, struct file *filp);
+static int gpio_release(struct inode *inode, struct file *filp);
+static unsigned int gpio_poll(struct file *filp,
+ struct poll_table_struct *wait);
+
+/* private data per open() of this driver */
+
+struct gpio_private {
+ struct gpio_private *next;
+ /* The IO_CFG_WRITE_MODE_VALUE only support 8 bits: */
+ unsigned char clk_mask;
+ unsigned char data_mask;
+ unsigned char write_msb;
+ unsigned char pad1;
+ /* These fields are generic */
+ unsigned long highalarm, lowalarm;
+ wait_queue_head_t alarm_wq;
+ int minor;
+};
+
+static void gpio_set_alarm(struct gpio_private *priv);
+static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
+static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd,
+ unsigned long arg);
+
+
+/* linked list of alarms to check for */
+
+static struct gpio_private *alarmlist;
+
+static int wanted_interrupts;
+
+static DEFINE_SPINLOCK(gpio_lock);
+
+#define NUM_PORTS (GPIO_MINOR_LAST+1)
+#define GIO_REG_RD_ADDR(reg) \
+ (unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg)
+#define GIO_REG_WR_ADDR(reg) \
+ (unsigned long *)(regi_gio + REG_WR_ADDR_gio_##reg)
+static unsigned long led_dummy;
+static unsigned long port_d_dummy; /* Only input on Artpec-3 */
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+static unsigned long port_e_dummy; /* Non existent on Artpec-3 */
+static unsigned long virtual_dummy;
+static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE;
+static unsigned short cached_virtual_gpio_read;
+#endif
+
+static unsigned long *data_out[NUM_PORTS] = {
+ GIO_REG_WR_ADDR(rw_pa_dout),
+ GIO_REG_WR_ADDR(rw_pb_dout),
+ &led_dummy,
+ GIO_REG_WR_ADDR(rw_pc_dout),
+ &port_d_dummy,
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ &port_e_dummy,
+ &virtual_dummy,
+#endif
+};
+
+static unsigned long *data_in[NUM_PORTS] = {
+ GIO_REG_RD_ADDR(r_pa_din),
+ GIO_REG_RD_ADDR(r_pb_din),
+ &led_dummy,
+ GIO_REG_RD_ADDR(r_pc_din),
+ GIO_REG_RD_ADDR(r_pd_din),
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ &port_e_dummy,
+ &virtual_dummy,
+#endif
+};
+
+static unsigned long changeable_dir[NUM_PORTS] = {
+ CONFIG_ETRAX_PA_CHANGEABLE_DIR,
+ CONFIG_ETRAX_PB_CHANGEABLE_DIR,
+ 0,
+ CONFIG_ETRAX_PC_CHANGEABLE_DIR,
+ 0,
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ 0,
+ CONFIG_ETRAX_PV_CHANGEABLE_DIR,
+#endif
+};
+
+static unsigned long changeable_bits[NUM_PORTS] = {
+ CONFIG_ETRAX_PA_CHANGEABLE_BITS,
+ CONFIG_ETRAX_PB_CHANGEABLE_BITS,
+ 0,
+ CONFIG_ETRAX_PC_CHANGEABLE_BITS,
+ 0,
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ 0,
+ CONFIG_ETRAX_PV_CHANGEABLE_BITS,
+#endif
+};
+
+static unsigned long *dir_oe[NUM_PORTS] = {
+ GIO_REG_WR_ADDR(rw_pa_oe),
+ GIO_REG_WR_ADDR(rw_pb_oe),
+ &led_dummy,
+ GIO_REG_WR_ADDR(rw_pc_oe),
+ &port_d_dummy,
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ &port_e_dummy,
+ &virtual_rw_pv_oe,
+#endif
+};
+
+static void gpio_set_alarm(struct gpio_private *priv)
+{
+ int bit;
+ int intr_cfg;
+ int mask;
+ int pins;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+ intr_cfg = REG_RD_INT(gio, regi_gio, rw_intr_cfg);
+ pins = REG_RD_INT(gio, regi_gio, rw_intr_pins);
+ mask = REG_RD_INT(gio, regi_gio, rw_intr_mask) & I2C_INTERRUPT_BITS;
+
+ for (bit = 0; bit < 32; bit++) {
+ int intr = bit % 8;
+ int pin = bit / 8;
+ if (priv->minor < GPIO_MINOR_LEDS)
+ pin += priv->minor * 4;
+ else
+ pin += (priv->minor - 1) * 4;
+
+ if (priv->highalarm & (1<<bit)) {
+ intr_cfg |= (regk_gio_hi << (intr * 3));
+ mask |= 1 << intr;
+ wanted_interrupts = mask & 0xff;
+ pins |= pin << (intr * 4);
+ } else if (priv->lowalarm & (1<<bit)) {
+ intr_cfg |= (regk_gio_lo << (intr * 3));
+ mask |= 1 << intr;
+ wanted_interrupts = mask & 0xff;
+ pins |= pin << (intr * 4);
+ }
+ }
+
+ REG_WR_INT(gio, regi_gio, rw_intr_cfg, intr_cfg);
+ REG_WR_INT(gio, regi_gio, rw_intr_pins, pins);
+ REG_WR_INT(gio, regi_gio, rw_intr_mask, mask);
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+}
+
+static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait)
+{
+ unsigned int mask = 0;
+ struct gpio_private *priv = file->private_data;
+ unsigned long data;
+ unsigned long tmp;
+
+ if (priv->minor >= GPIO_MINOR_PWM0 &&
+ priv->minor <= GPIO_MINOR_LAST_PWM)
+ return 0;
+
+ poll_wait(file, &priv->alarm_wq, wait);
+ if (priv->minor <= GPIO_MINOR_D) {
+ data = readl(data_in[priv->minor]);
+ REG_WR_INT(gio, regi_gio, rw_ack_intr, wanted_interrupts);
+ tmp = REG_RD_INT(gio, regi_gio, rw_intr_mask);
+ tmp &= I2C_INTERRUPT_BITS;
+ tmp |= wanted_interrupts;
+ REG_WR_INT(gio, regi_gio, rw_intr_mask, tmp);
+ } else
+ return 0;
+
+ if ((data & priv->highalarm) || (~data & priv->lowalarm))
+ mask = POLLIN|POLLRDNORM;
+
+ DP(printk(KERN_DEBUG "gpio_poll ready: mask 0x%08X\n", mask));
+ return mask;
+}
+
+static irqreturn_t gpio_interrupt(int irq, void *dev_id)
+{
+ reg_gio_rw_intr_mask intr_mask;
+ reg_gio_r_masked_intr masked_intr;
+ reg_gio_rw_ack_intr ack_intr;
+ unsigned long flags;
+ unsigned long tmp;
+ unsigned long tmp2;
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ unsigned char enable_gpiov_ack = 0;
+#endif
+
+ /* Find what PA interrupts are active */
+ masked_intr = REG_RD(gio, regi_gio, r_masked_intr);
+ tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr);
+
+ /* Find those that we have enabled */
+ spin_lock_irqsave(&gpio_lock, flags);
+ tmp &= wanted_interrupts;
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ /* Something changed on virtual GPIO. Interrupt is acked by
+ * reading the device.
+ */
+ if (tmp & (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN)) {
+ i2c_read(VIRT_I2C_ADDR, (void *)&cached_virtual_gpio_read,
+ sizeof(cached_virtual_gpio_read));
+ enable_gpiov_ack = 1;
+ }
+#endif
+
+ /* Ack them */
+ ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp);
+ REG_WR(gio, regi_gio, rw_ack_intr, ack_intr);
+
+ /* Disable those interrupts.. */
+ intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);
+ tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask);
+ tmp2 &= ~tmp;
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ /* Do not disable interrupt on virtual GPIO. Changes on virtual
+ * pins are only noticed by an interrupt.
+ */
+ if (enable_gpiov_ack)
+ tmp2 |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
+#endif
+ intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2);
+ REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);
+
+ return IRQ_RETVAL(tmp);
+}
+
+static void gpio_write_bit(unsigned long *port, unsigned char data, int bit,
+ unsigned char clk_mask, unsigned char data_mask)
+{
+ unsigned long shadow = readl(port) & ~clk_mask;
+ writel(shadow, port);
+ if (data & 1 << bit)
+ shadow |= data_mask;
+ else
+ shadow &= ~data_mask;
+ writel(shadow, port);
+ /* For FPGA: min 5.0ns (DCC) before CCLK high */
+ shadow |= clk_mask;
+ writel(shadow, port);
+}
+
+static void gpio_write_byte(struct gpio_private *priv, unsigned long *port,
+ unsigned char data)
+{
+ int i;
+
+ if (priv->write_msb)
+ for (i = 7; i >= 0; i--)
+ gpio_write_bit(port, data, i, priv->clk_mask,
+ priv->data_mask);
+ else
+ for (i = 0; i <= 7; i++)
+ gpio_write_bit(port, data, i, priv->clk_mask,
+ priv->data_mask);
+}
+
+
+static ssize_t gpio_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ struct gpio_private *priv = file->private_data;
+ unsigned long flags;
+ ssize_t retval = count;
+ /* Only bits 0-7 may be used for write operations but allow all
+ devices except leds... */
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ if (priv->minor == GPIO_MINOR_V)
+ return -EFAULT;
+#endif
+ if (priv->minor == GPIO_MINOR_LEDS)
+ return -EFAULT;
+
+ if (priv->minor >= GPIO_MINOR_PWM0 &&
+ priv->minor <= GPIO_MINOR_LAST_PWM)
+ return -EFAULT;
+
+ if (!access_ok(VERIFY_READ, buf, count))
+ return -EFAULT;
+
+ /* It must have been configured using the IO_CFG_WRITE_MODE */
+ /* Perhaps a better error code? */
+ if (priv->clk_mask == 0 || priv->data_mask == 0)
+ return -EPERM;
+
+ D(printk(KERN_DEBUG "gpio_write: %lu to data 0x%02X clk 0x%02X "
+ "msb: %i\n",
+ count, priv->data_mask, priv->clk_mask, priv->write_msb));
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ while (count--)
+ gpio_write_byte(priv, data_out[priv->minor], *buf++);
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ return retval;
+}
+
+static int gpio_open(struct inode *inode, struct file *filp)
+{
+ struct gpio_private *priv;
+ int p = iminor(inode);
+
+ if (p > GPIO_MINOR_LAST_PWM ||
+ (p > GPIO_MINOR_LAST && p < GPIO_MINOR_PWM0))
+ return -EINVAL;
+
+ priv = kmalloc(sizeof(struct gpio_private), GFP_KERNEL);
+
+ if (!priv)
+ return -ENOMEM;
+ memset(priv, 0, sizeof(*priv));
+
+ priv->minor = p;
+ filp->private_data = priv;
+
+ /* initialize the io/alarm struct, not for PWM ports though */
+ if (p <= GPIO_MINOR_LAST) {
+
+ priv->clk_mask = 0;
+ priv->data_mask = 0;
+ priv->highalarm = 0;
+ priv->lowalarm = 0;
+
+ init_waitqueue_head(&priv->alarm_wq);
+
+ /* link it into our alarmlist */
+ spin_lock_irq(&gpio_lock);
+ priv->next = alarmlist;
+ alarmlist = priv;
+ spin_unlock_irq(&gpio_lock);
+ }
+
+ return 0;
+}
+
+static int gpio_release(struct inode *inode, struct file *filp)
+{
+ struct gpio_private *p;
+ struct gpio_private *todel;
+ /* local copies while updating them: */
+ unsigned long a_high, a_low;
+
+ /* prepare to free private structure */
+ todel = filp->private_data;
+
+ /* unlink from alarmlist - only for non-PWM ports though */
+ if (todel->minor <= GPIO_MINOR_LAST) {
+ spin_lock_irq(&gpio_lock);
+ p = alarmlist;
+
+ if (p == todel)
+ alarmlist = todel->next;
+ else {
+ while (p->next != todel)
+ p = p->next;
+ p->next = todel->next;
+ }
+
+ /* Check if there are still any alarms set */
+ p = alarmlist;
+ a_high = 0;
+ a_low = 0;
+ while (p) {
+ if (p->minor == GPIO_MINOR_A) {
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ p->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
+#endif
+ a_high |= p->highalarm;
+ a_low |= p->lowalarm;
+ }
+
+ p = p->next;
+ }
+
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ /* Variable 'a_low' needs to be set here again
+ * to ensure that interrupt for virtual GPIO is handled.
+ */
+ a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
+#endif
+
+ spin_unlock_irq(&gpio_lock);
+ }
+ kfree(todel);
+
+ return 0;
+}
+
+/* Main device API. ioctl's to read/set/clear bits, as well as to
+ * set alarms to wait for using a subsequent select().
+ */
+
+inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg)
+{
+ /* Set direction 0=unchanged 1=input,
+ * return mask with 1=input
+ */
+ unsigned long flags;
+ unsigned long dir_shadow;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ dir_shadow = readl(dir_oe[priv->minor]) &
+ ~(arg & changeable_dir[priv->minor]);
+ writel(dir_shadow, dir_oe[priv->minor]);
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ if (priv->minor == GPIO_MINOR_C)
+ dir_shadow ^= 0xFFFF; /* Only 16 bits */
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ else if (priv->minor == GPIO_MINOR_V)
+ dir_shadow ^= 0xFFFF; /* Only 16 bits */
+#endif
+ else
+ dir_shadow ^= 0xFFFFFFFF; /* PA, PB and PD 32 bits */
+
+ return dir_shadow;
+
+} /* setget_input */
+
+static inline unsigned long setget_output(struct gpio_private *priv,
+ unsigned long arg)
+{
+ unsigned long flags;
+ unsigned long dir_shadow;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ dir_shadow = readl(dir_oe[priv->minor]) |
+ (arg & changeable_dir[priv->minor]);
+ writel(dir_shadow, dir_oe[priv->minor]);
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ return dir_shadow;
+} /* setget_output */
+
+static int gpio_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ unsigned long flags;
+ unsigned long val;
+ unsigned long shadow;
+ struct gpio_private *priv = file->private_data;
+
+ if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE)
+ return -ENOTTY;
+
+ /* Check for special ioctl handlers first */
+
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ if (priv->minor == GPIO_MINOR_V)
+ return virtual_gpio_ioctl(file, cmd, arg);
+#endif
+
+ if (priv->minor == GPIO_MINOR_LEDS)
+ return gpio_leds_ioctl(cmd, arg);
+
+ if (priv->minor >= GPIO_MINOR_PWM0 &&
+ priv->minor <= GPIO_MINOR_LAST_PWM)
+ return gpio_pwm_ioctl(priv, cmd, arg);
+
+ switch (_IOC_NR(cmd)) {
+ case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
+ /* Read the port. */
+ return readl(data_in[priv->minor]);
+ case IO_SETBITS:
+ spin_lock_irqsave(&gpio_lock, flags);
+ /* Set changeable bits with a 1 in arg. */
+ shadow = readl(data_out[priv->minor]) |
+ (arg & changeable_bits[priv->minor]);
+ writel(shadow, data_out[priv->minor]);
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ break;
+ case IO_CLRBITS:
+ spin_lock_irqsave(&gpio_lock, flags);
+ /* Clear changeable bits with a 1 in arg. */
+ shadow = readl(data_out[priv->minor]) &
+ ~(arg & changeable_bits[priv->minor]);
+ writel(shadow, data_out[priv->minor]);
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ break;
+ case IO_HIGHALARM:
+ /* Set alarm when bits with 1 in arg go high. */
+ priv->highalarm |= arg;
+ gpio_set_alarm(priv);
+ break;
+ case IO_LOWALARM:
+ /* Set alarm when bits with 1 in arg go low. */
+ priv->lowalarm |= arg;
+ gpio_set_alarm(priv);
+ break;
+ case IO_CLRALARM:
+ /* Clear alarm for bits with 1 in arg. */
+ priv->highalarm &= ~arg;
+ priv->lowalarm &= ~arg;
+ gpio_set_alarm(priv);
+ break;
+ case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
+ /* Read direction 0=input 1=output */
+ return readl(dir_oe[priv->minor]);
+
+ case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
+ /* Set direction 0=unchanged 1=input,
+ * return mask with 1=input
+ */
+ return setget_input(priv, arg);
+
+ case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
+ /* Set direction 0=unchanged 1=output,
+ * return mask with 1=output
+ */
+ return setget_output(priv, arg);
+
+ case IO_CFG_WRITE_MODE:
+ {
+ int res = -EPERM;
+ unsigned long dir_shadow, clk_mask, data_mask, write_msb;
+
+ clk_mask = arg & 0xFF;
+ data_mask = (arg >> 8) & 0xFF;
+ write_msb = (arg >> 16) & 0x01;
+
+ /* Check if we're allowed to change the bits and
+ * the direction is correct
+ */
+ spin_lock_irqsave(&gpio_lock, flags);
+ dir_shadow = readl(dir_oe[priv->minor]);
+ if ((clk_mask & changeable_bits[priv->minor]) &&
+ (data_mask & changeable_bits[priv->minor]) &&
+ (clk_mask & dir_shadow) &&
+ (data_mask & dir_shadow)) {
+ priv->clk_mask = clk_mask;
+ priv->data_mask = data_mask;
+ priv->write_msb = write_msb;
+ res = 0;
+ }
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ return res;
+ }
+ case IO_READ_INBITS:
+ /* *arg is result of reading the input pins */
+ val = readl(data_in[priv->minor]);
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ return 0;
+ case IO_READ_OUTBITS:
+ /* *arg is result of reading the output shadow */
+ val = *data_out[priv->minor];
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ break;
+ case IO_SETGET_INPUT:
+ /* bits set in *arg is set to input,
+ * *arg updated with current input pins.
+ */
+ if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
+ return -EFAULT;
+ val = setget_input(priv, val);
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ break;
+ case IO_SETGET_OUTPUT:
+ /* bits set in *arg is set to output,
+ * *arg updated with current output pins.
+ */
+ if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
+ return -EFAULT;
+ val = setget_output(priv, val);
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ break;
+ default:
+ return -EINVAL;
+ } /* switch */
+
+ return 0;
+}
+
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned long flags;
+ unsigned short val;
+ unsigned short shadow;
+ struct gpio_private *priv = file->private_data;
+
+ switch (_IOC_NR(cmd)) {
+ case IO_SETBITS:
+ spin_lock_irqsave(&gpio_lock, flags);
+ /* Set changeable bits with a 1 in arg. */
+ i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
+ shadow |= ~readl(dir_oe[priv->minor]) |
+ (arg & changeable_bits[priv->minor]);
+ i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
+ spin_lock_irqrestore(&gpio_lock, flags);
+ break;
+ case IO_CLRBITS:
+ spin_lock_irqsave(&gpio_lock, flags);
+ /* Clear changeable bits with a 1 in arg. */
+ i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
+ shadow |= ~readl(dir_oe[priv->minor]) &
+ ~(arg & changeable_bits[priv->minor]);
+ i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
+ spin_lock_irqrestore(&gpio_lock, flags);
+ break;
+ case IO_HIGHALARM:
+ /* Set alarm when bits with 1 in arg go high. */
+ priv->highalarm |= arg;
+ break;
+ case IO_LOWALARM:
+ /* Set alarm when bits with 1 in arg go low. */
+ priv->lowalarm |= arg;
+ break;
+ case IO_CLRALARM:
+ /* Clear alarm for bits with 1 in arg. */
+ priv->highalarm &= ~arg;
+ priv->lowalarm &= ~arg;
+ break;
+ case IO_CFG_WRITE_MODE:
+ {
+ unsigned long dir_shadow;
+ dir_shadow = readl(dir_oe[priv->minor]);
+
+ priv->clk_mask = arg & 0xFF;
+ priv->data_mask = (arg >> 8) & 0xFF;
+ priv->write_msb = (arg >> 16) & 0x01;
+ /* Check if we're allowed to change the bits and
+ * the direction is correct
+ */
+ if (!((priv->clk_mask & changeable_bits[priv->minor]) &&
+ (priv->data_mask & changeable_bits[priv->minor]) &&
+ (priv->clk_mask & dir_shadow) &&
+ (priv->data_mask & dir_shadow))) {
+ priv->clk_mask = 0;
+ priv->data_mask = 0;
+ return -EPERM;
+ }
+ break;
+ }
+ case IO_READ_INBITS:
+ /* *arg is result of reading the input pins */
+ val = cached_virtual_gpio_read & ~readl(dir_oe[priv->minor]);
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ return 0;
+
+ case IO_READ_OUTBITS:
+ /* *arg is result of reading the output shadow */
+ i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val));
+ val &= readl(dir_oe[priv->minor]);
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ break;
+ case IO_SETGET_INPUT:
+ {
+ /* bits set in *arg is set to input,
+ * *arg updated with current input pins.
+ */
+ unsigned short input_mask = ~readl(dir_oe[priv->minor]);
+ if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
+ return -EFAULT;
+ val = setget_input(priv, val);
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ if ((input_mask & val) != input_mask) {
+ /* Input pins changed. All ports desired as input
+ * should be set to logic 1.
+ */
+ unsigned short change = input_mask ^ val;
+ i2c_read(VIRT_I2C_ADDR, (void *)&shadow,
+ sizeof(shadow));
+ shadow &= ~change;
+ shadow |= val;
+ i2c_write(VIRT_I2C_ADDR, (void *)&shadow,
+ sizeof(shadow));
+ }
+ break;
+ }
+ case IO_SETGET_OUTPUT:
+ /* bits set in *arg is set to output,
+ * *arg updated with current output pins.
+ */
+ if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
+ return -EFAULT;
+ val = setget_output(priv, val);
+ if (copy_to_user((void __user *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ break;
+ default:
+ return -EINVAL;
+ } /* switch */
+ return 0;
+}
+#endif /* CONFIG_ETRAX_VIRTUAL_GPIO */
+
+static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
+{
+ unsigned char green;
+ unsigned char red;
+
+ switch (_IOC_NR(cmd)) {
+ case IO_LEDACTIVE_SET:
+ green = ((unsigned char) arg) & 1;
+ red = (((unsigned char) arg) >> 1) & 1;
+ CRIS_LED_ACTIVE_SET_G(green);
+ CRIS_LED_ACTIVE_SET_R(red);
+ break;
+
+ default:
+ return -EINVAL;
+ } /* switch */
+
+ return 0;
+}
+
+static int gpio_pwm_set_mode(unsigned long arg, int pwm_port)
+{
+ int pinmux_pwm = pinmux_pwm0 + pwm_port;
+ int mode;
+ reg_gio_rw_pwm0_ctrl rw_pwm_ctrl = {
+ .ccd_val = 0,
+ .ccd_override = regk_gio_no,
+ .mode = regk_gio_no
+ };
+ int allocstatus;
+
+ if (get_user(mode, &((struct io_pwm_set_mode *) arg)->mode))
+ return -EFAULT;
+ rw_pwm_ctrl.mode = mode;
+ if (mode != PWM_OFF)
+ allocstatus = crisv32_pinmux_alloc_fixed(pinmux_pwm);
+ else
+ allocstatus = crisv32_pinmux_dealloc_fixed(pinmux_pwm);
+ if (allocstatus)
+ return allocstatus;
+ REG_WRITE(reg_gio_rw_pwm0_ctrl, REG_ADDR(gio, regi_gio, rw_pwm0_ctrl) +
+ 12 * pwm_port, rw_pwm_ctrl);
+ return 0;
+}
+
+static int gpio_pwm_set_period(unsigned long arg, int pwm_port)
+{
+ struct io_pwm_set_period periods;
+ reg_gio_rw_pwm0_var rw_pwm_widths;
+
+ if (copy_from_user(&periods, (void __user *)arg, sizeof(periods)))
+ return -EFAULT;
+ if (periods.lo > 8191 || periods.hi > 8191)
+ return -EINVAL;
+ rw_pwm_widths.lo = periods.lo;
+ rw_pwm_widths.hi = periods.hi;
+ REG_WRITE(reg_gio_rw_pwm0_var, REG_ADDR(gio, regi_gio, rw_pwm0_var) +
+ 12 * pwm_port, rw_pwm_widths);
+ return 0;
+}
+
+static int gpio_pwm_set_duty(unsigned long arg, int pwm_port)
+{
+ unsigned int duty;
+ reg_gio_rw_pwm0_data rw_pwm_duty;
+
+ if (get_user(duty, &((struct io_pwm_set_duty *) arg)->duty))
+ return -EFAULT;
+ if (duty > 255)
+ return -EINVAL;
+ rw_pwm_duty.data = duty;
+ REG_WRITE(reg_gio_rw_pwm0_data, REG_ADDR(gio, regi_gio, rw_pwm0_data) +
+ 12 * pwm_port, rw_pwm_duty);
+ return 0;
+}
+
+static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd,
+ unsigned long arg)
+{
+ int pwm_port = priv->minor - GPIO_MINOR_PWM0;
+
+ switch (_IOC_NR(cmd)) {
+ case IO_PWM_SET_MODE:
+ return gpio_pwm_set_mode(arg, pwm_port);
+ case IO_PWM_SET_PERIOD:
+ return gpio_pwm_set_period(arg, pwm_port);
+ case IO_PWM_SET_DUTY:
+ return gpio_pwm_set_duty(arg, pwm_port);
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static const struct file_operations gpio_fops = {
+ .owner = THIS_MODULE,
+ .poll = gpio_poll,
+ .ioctl = gpio_ioctl,
+ .write = gpio_write,
+ .open = gpio_open,
+ .release = gpio_release,
+};
+
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+static void __init virtual_gpio_init(void)
+{
+ reg_gio_rw_intr_cfg intr_cfg;
+ reg_gio_rw_intr_mask intr_mask;
+ unsigned short shadow;
+
+ shadow = ~virtual_rw_pv_oe; /* Input ports should be set to logic 1 */
+ shadow |= CONFIG_ETRAX_DEF_GIO_PV_OUT;
+ i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
+
+ /* Set interrupt mask and on what state the interrupt shall trigger.
+ * For virtual gpio the interrupt shall trigger on logic '0'.
+ */
+ intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg);
+ intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);
+
+ switch (CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN) {
+ case 0:
+ intr_cfg.pa0 = regk_gio_lo;
+ intr_mask.pa0 = regk_gio_yes;
+ break;
+ case 1:
+ intr_cfg.pa1 = regk_gio_lo;
+ intr_mask.pa1 = regk_gio_yes;
+ break;
+ case 2:
+ intr_cfg.pa2 = regk_gio_lo;
+ intr_mask.pa2 = regk_gio_yes;
+ break;
+ case 3:
+ intr_cfg.pa3 = regk_gio_lo;
+ intr_mask.pa3 = regk_gio_yes;
+ break;
+ case 4:
+ intr_cfg.pa4 = regk_gio_lo;
+ intr_mask.pa4 = regk_gio_yes;
+ break;
+ case 5:
+ intr_cfg.pa5 = regk_gio_lo;
+ intr_mask.pa5 = regk_gio_yes;
+ break;
+ case 6:
+ intr_cfg.pa6 = regk_gio_lo;
+ intr_mask.pa6 = regk_gio_yes;
+ break;
+ case 7:
+ intr_cfg.pa7 = regk_gio_lo;
+ intr_mask.pa7 = regk_gio_yes;
+ break;
+ }
+
+ REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg);
+ REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);
+}
+#endif
+
+/* main driver initialization routine, called from mem.c */
+
+static int __init gpio_init(void)
+{
+ int res;
+
+ printk(KERN_INFO "ETRAX FS GPIO driver v2.7, (c) 2003-2008 "
+ "Axis Communications AB\n");
+
+ /* do the formalities */
+
+ res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
+ if (res < 0) {
+ printk(KERN_ERR "gpio: couldn't get a major number.\n");
+ return res;
+ }
+
+ /* Clear all leds */
+ CRIS_LED_NETWORK_GRP0_SET(0);
+ CRIS_LED_NETWORK_GRP1_SET(0);
+ CRIS_LED_ACTIVE_SET(0);
+ CRIS_LED_DISK_READ(0);
+ CRIS_LED_DISK_WRITE(0);
+
+ int res2 = request_irq(GIO_INTR_VECT, gpio_interrupt,
+ IRQF_SHARED | IRQF_DISABLED, "gpio", &alarmlist);
+ if (res2) {
+ printk(KERN_ERR "err: irq for gpio\n");
+ return res2;
+ }
+
+ /* No IRQs by default. */
+ REG_WR_INT(gio, regi_gio, rw_intr_pins, 0);
+
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ virtual_gpio_init();
+#endif
+
+ return res;
+}
+
+/* this makes sure that gpio_init is called during kernel boot */
+
+module_init(gpio_init);
diff --git a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
new file mode 100644
index 00000000000..01ed0be2d0d
--- /dev/null
+++ b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
@@ -0,0 +1,180 @@
+/*
+ * arch/cris/arch-v32/drivers/nandflash.c
+ *
+ * Copyright (c) 2007
+ *
+ * Derived from drivers/mtd/nand/spia.c
+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.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.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <asm/arch/memmap.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/pio_defs.h>
+#include <pinmux.h>
+#include <asm/io.h>
+
+#define MANUAL_ALE_CLE_CONTROL 1
+
+#define regf_ALE a0
+#define regf_CLE a1
+#define regf_NCE ce0_n
+
+#define CLE_BIT 10
+#define ALE_BIT 11
+#define CE_BIT 12
+
+struct mtd_info_wrapper {
+ struct mtd_info info;
+ struct nand_chip chip;
+};
+
+/* Bitmask for control pins */
+#define PIN_BITMASK ((1 << CE_BIT) | (1 << CLE_BIT) | (1 << ALE_BIT))
+
+static struct mtd_info *crisv32_mtd;
+/*
+ * hardware specific access to control-lines
+ */
+static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
+{
+ unsigned long flags;
+ reg_pio_rw_dout dout;
+ struct nand_chip *this = mtd->priv;
+
+ local_irq_save(flags);
+
+ /* control bits change */
+ if (ctrl & NAND_CTRL_CHANGE) {
+ dout = REG_RD(pio, regi_pio, rw_dout);
+ dout.regf_NCE = (ctrl & NAND_NCE) ? 0 : 1;
+
+#if !MANUAL_ALE_CLE_CONTROL
+ if (ctrl & NAND_ALE) {
+ /* A0 = ALE high */
+ this->IO_ADDR_W = (void __iomem *)REG_ADDR(pio,
+ regi_pio, rw_io_access1);
+ } else if (ctrl & NAND_CLE) {
+ /* A1 = CLE high */
+ this->IO_ADDR_W = (void __iomem *)REG_ADDR(pio,
+ regi_pio, rw_io_access2);
+ } else {
+ /* A1 = CLE and A0 = ALE low */
+ this->IO_ADDR_W = (void __iomem *)REG_ADDR(pio,
+ regi_pio, rw_io_access0);
+ }
+#else
+
+ dout.regf_CLE = (ctrl & NAND_CLE) ? 1 : 0;
+ dout.regf_ALE = (ctrl & NAND_ALE) ? 1 : 0;
+#endif
+ REG_WR(pio, regi_pio, rw_dout, dout);
+ }
+
+ /* command to chip */
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
+
+ local_irq_restore(flags);
+}
+
+/*
+* read device ready pin
+*/
+static int crisv32_device_ready(struct mtd_info *mtd)
+{
+ reg_pio_r_din din = REG_RD(pio, regi_pio, r_din);
+ return din.rdy;
+}
+
+/*
+ * Main initialization routine
+ */
+struct mtd_info *__init crisv32_nand_flash_probe(void)
+{
+ void __iomem *read_cs;
+ void __iomem *write_cs;
+
+ struct mtd_info_wrapper *wrapper;
+ struct nand_chip *this;
+ int err = 0;
+
+ reg_pio_rw_man_ctrl man_ctrl = {
+ .regf_NCE = regk_pio_yes,
+#if MANUAL_ALE_CLE_CONTROL
+ .regf_ALE = regk_pio_yes,
+ .regf_CLE = regk_pio_yes
+#endif
+ };
+ reg_pio_rw_oe oe = {
+ .regf_NCE = regk_pio_yes,
+#if MANUAL_ALE_CLE_CONTROL
+ .regf_ALE = regk_pio_yes,
+ .regf_CLE = regk_pio_yes
+#endif
+ };
+ reg_pio_rw_dout dout = { .regf_NCE = 1 };
+
+ /* Allocate pio pins to pio */
+ crisv32_pinmux_alloc_fixed(pinmux_pio);
+ /* Set up CE, ALE, CLE (ce0_n, a0, a1) for manual control and output */
+ REG_WR(pio, regi_pio, rw_man_ctrl, man_ctrl);
+ REG_WR(pio, regi_pio, rw_dout, dout);
+ REG_WR(pio, regi_pio, rw_oe, oe);
+
+ /* Allocate memory for MTD device structure and private data */
+ wrapper = kzalloc(sizeof(struct mtd_info_wrapper), GFP_KERNEL);
+ if (!wrapper) {
+ printk(KERN_ERR "Unable to allocate CRISv32 NAND MTD "
+ "device structure.\n");
+ err = -ENOMEM;
+ return NULL;
+ }
+
+ read_cs = write_cs = (void __iomem *)REG_ADDR(pio, regi_pio,
+ rw_io_access0);
+
+ /* Get pointer to private data */
+ this = &wrapper->chip;
+ crisv32_mtd = &wrapper->info;
+
+ /* Link the private data with the MTD structure */
+ crisv32_mtd->priv = this;
+
+ /* Set address of NAND IO lines */
+ this->IO_ADDR_R = read_cs;
+ this->IO_ADDR_W = write_cs;
+ this->cmd_ctrl = crisv32_hwcontrol;
+ this->dev_ready = crisv32_device_ready;
+ /* 20 us command delay time */
+ this->chip_delay = 20;
+ this->ecc.mode = NAND_ECC_SOFT;
+
+ /* Enable the following for a flash based bad block table */
+ /* this->options = NAND_USE_FLASH_BBT; */
+
+ /* Scan to find existance of the device */
+ if (nand_scan(crisv32_mtd, 1)) {
+ err = -ENXIO;
+ goto out_mtd;
+ }
+
+ return crisv32_mtd;
+
+out_mtd:
+ kfree(wrapper);
+ return NULL;
+}
+
diff --git a/arch/cris/arch-v32/drivers/mach-fs/Makefile b/arch/cris/arch-v32/drivers/mach-fs/Makefile
new file mode 100644
index 00000000000..5c6d2a2a080
--- /dev/null
+++ b/arch/cris/arch-v32/drivers/mach-fs/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Etrax-specific drivers
+#
+
+obj-$(CONFIG_ETRAX_NANDFLASH) += nandflash.o
+obj-$(CONFIG_ETRAX_GPIO) += gpio.o
diff --git a/arch/cris/arch-v32/drivers/gpio.c b/arch/cris/arch-v32/drivers/mach-fs/gpio.c
index d82c5c56113..7863fd4efc2 100644
--- a/arch/cris/arch-v32/drivers/gpio.c
+++ b/arch/cris/arch-v32/drivers/mach-fs/gpio.c
@@ -1,68 +1,15 @@
-/* $Id: gpio.c,v 1.16 2005/06/19 17:06:49 starvik Exp $
- *
+/*
* ETRAX CRISv32 general port I/O device
*
- * Copyright (c) 1999, 2000, 2001, 2002, 2003 Axis Communications AB
+ * Copyright (c) 1999-2006 Axis Communications AB
*
* Authors: Bjorn Wesen (initial version)
* Ola Knutsson (LED handling)
* Johan Adolfsson (read/set directions, write, port G,
* port to ETRAX FS.
*
- * $Log: gpio.c,v $
- * Revision 1.16 2005/06/19 17:06:49 starvik
- * Merge of Linux 2.6.12.
- *
- * Revision 1.15 2005/05/25 08:22:20 starvik
- * Changed GPIO port order to fit packages/devices/axis-2.4.
- *
- * Revision 1.14 2005/04/24 18:35:08 starvik
- * Updated with final register headers.
- *
- * Revision 1.13 2005/03/15 15:43:00 starvik
- * dev_id needs to be supplied for shared IRQs.
- *
- * Revision 1.12 2005/03/10 17:12:00 starvik
- * Protect alarm list with spinlock.
- *
- * Revision 1.11 2005/01/05 06:08:59 starvik
- * No need to do local_irq_disable after local_irq_save.
- *
- * Revision 1.10 2004/11/19 08:38:31 starvik
- * Removed old crap.
- *
- * Revision 1.9 2004/05/14 07:58:02 starvik
- * Merge of changes from 2.4
- *
- * Revision 1.8 2003/09/11 07:29:50 starvik
- * Merge of Linux 2.6.0-test5
- *
- * Revision 1.7 2003/07/10 13:25:46 starvik
- * Compiles for 2.5.74
- * Lindented ethernet.c
- *
- * Revision 1.6 2003/07/04 08:27:46 starvik
- * Merge of Linux 2.5.74
- *
- * Revision 1.5 2003/06/10 08:26:37 johana
- * Etrax -> ETRAX CRISv32
- *
- * Revision 1.4 2003/06/05 14:22:48 johana
- * Initialise some_alarms.
- *
- * Revision 1.3 2003/06/05 10:15:46 johana
- * New INTR_VECT macros.
- * Enable interrupts in global config.
- *
- * Revision 1.2 2003/06/03 15:52:50 johana
- * Initial CRIS v32 version.
- *
- * Revision 1.1 2003/06/03 08:53:15 johana
- * Copy of os/lx25/arch/cris/arch-v10/drivers/gpio.c version 1.7.
- *
*/
-
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -77,14 +24,20 @@
#include <linux/spinlock.h>
#include <asm/etraxgpio.h>
-#include <asm/arch/hwregs/reg_map.h>
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/gio_defs.h>
-#include <asm/arch/hwregs/intr_vect_defs.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/gio_defs.h>
+#include <hwregs/intr_vect_defs.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/irq.h>
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+#include "../i2c.h"
+
+#define VIRT_I2C_ADDR 0x40
+#endif
+
/* The following gio ports on ETRAX FS is available:
* pa 8 bits, supports interrupts off, hi, low, set, posedge, negedge anyedge
* pb 18 bits
@@ -100,7 +53,12 @@
#if 0
static int dp_cnt;
-#define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0)
+#define DP(x) \
+ do { \
+ dp_cnt++; \
+ if (dp_cnt % 1000 == 0) \
+ x; \
+ } while (0)
#else
#define DP(x)
#endif
@@ -111,13 +69,18 @@ static char gpio_name[] = "etrax gpio";
static wait_queue_head_t *gpio_wq;
#endif
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg);
+#endif
static int gpio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
-static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
- loff_t *off);
+ unsigned int cmd, unsigned long arg);
+static ssize_t gpio_write(struct file *file, const char *buf, size_t count,
+ loff_t *off);
static int gpio_open(struct inode *inode, struct file *filp);
static int gpio_release(struct inode *inode, struct file *filp);
-static unsigned int gpio_poll(struct file *filp, struct poll_table_struct *wait);
+static unsigned int gpio_poll(struct file *filp,
+ struct poll_table_struct *wait);
/* private data per open() of this driver */
@@ -136,18 +99,25 @@ struct gpio_private {
/* linked list of alarms to check for */
-static struct gpio_private *alarmlist = 0;
+static struct gpio_private *alarmlist;
-static int gpio_some_alarms = 0; /* Set if someone uses alarm */
-static unsigned long gpio_pa_high_alarms = 0;
-static unsigned long gpio_pa_low_alarms = 0;
+static int gpio_some_alarms; /* Set if someone uses alarm */
+static unsigned long gpio_pa_high_alarms;
+static unsigned long gpio_pa_low_alarms;
static DEFINE_SPINLOCK(alarm_lock);
#define NUM_PORTS (GPIO_MINOR_LAST+1)
-#define GIO_REG_RD_ADDR(reg) (volatile unsigned long*) (regi_gio + REG_RD_ADDR_gio_##reg )
-#define GIO_REG_WR_ADDR(reg) (volatile unsigned long*) (regi_gio + REG_RD_ADDR_gio_##reg )
+#define GIO_REG_RD_ADDR(reg) \
+ (volatile unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg)
+#define GIO_REG_WR_ADDR(reg) \
+ (volatile unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg)
unsigned long led_dummy;
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+static unsigned long virtual_dummy;
+static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE;
+static unsigned short cached_virtual_gpio_read;
+#endif
static volatile unsigned long *data_out[NUM_PORTS] = {
GIO_REG_WR_ADDR(rw_pa_dout),
@@ -156,6 +126,9 @@ static volatile unsigned long *data_out[NUM_PORTS] = {
GIO_REG_WR_ADDR(rw_pc_dout),
GIO_REG_WR_ADDR(rw_pd_dout),
GIO_REG_WR_ADDR(rw_pe_dout),
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ &virtual_dummy,
+#endif
};
static volatile unsigned long *data_in[NUM_PORTS] = {
@@ -165,6 +138,9 @@ static volatile unsigned long *data_in[NUM_PORTS] = {
GIO_REG_RD_ADDR(r_pc_din),
GIO_REG_RD_ADDR(r_pd_din),
GIO_REG_RD_ADDR(r_pe_din),
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ &virtual_dummy,
+#endif
};
static unsigned long changeable_dir[NUM_PORTS] = {
@@ -174,6 +150,9 @@ static unsigned long changeable_dir[NUM_PORTS] = {
CONFIG_ETRAX_PC_CHANGEABLE_DIR,
CONFIG_ETRAX_PD_CHANGEABLE_DIR,
CONFIG_ETRAX_PE_CHANGEABLE_DIR,
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ CONFIG_ETRAX_PV_CHANGEABLE_DIR,
+#endif
};
static unsigned long changeable_bits[NUM_PORTS] = {
@@ -183,6 +162,9 @@ static unsigned long changeable_bits[NUM_PORTS] = {
CONFIG_ETRAX_PC_CHANGEABLE_BITS,
CONFIG_ETRAX_PD_CHANGEABLE_BITS,
CONFIG_ETRAX_PE_CHANGEABLE_BITS,
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ CONFIG_ETRAX_PV_CHANGEABLE_BITS,
+#endif
};
static volatile unsigned long *dir_oe[NUM_PORTS] = {
@@ -192,13 +174,14 @@ static volatile unsigned long *dir_oe[NUM_PORTS] = {
GIO_REG_WR_ADDR(rw_pc_oe),
GIO_REG_WR_ADDR(rw_pd_oe),
GIO_REG_WR_ADDR(rw_pe_oe),
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ &virtual_rw_pv_oe,
+#endif
};
-static unsigned int
-gpio_poll(struct file *file,
- poll_table *wait)
+static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait)
{
unsigned int mask = 0;
struct gpio_private *priv = (struct gpio_private *)file->private_data;
@@ -210,65 +193,50 @@ gpio_poll(struct file *file,
unsigned long flags;
local_irq_save(flags);
- data = REG_TYPE_CONV(unsigned long, reg_gio_r_pa_din, REG_RD(gio, regi_gio, r_pa_din));
+ data = REG_TYPE_CONV(unsigned long, reg_gio_r_pa_din,
+ REG_RD(gio, regi_gio, r_pa_din));
/* PA has support for interrupt
* lets activate high for those low and with highalarm set
*/
intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg);
tmp = ~data & priv->highalarm & 0xFF;
- if (tmp & (1 << 0)) {
+ if (tmp & (1 << 0))
intr_cfg.pa0 = regk_gio_hi;
- }
- if (tmp & (1 << 1)) {
+ if (tmp & (1 << 1))
intr_cfg.pa1 = regk_gio_hi;
- }
- if (tmp & (1 << 2)) {
+ if (tmp & (1 << 2))
intr_cfg.pa2 = regk_gio_hi;
- }
- if (tmp & (1 << 3)) {
+ if (tmp & (1 << 3))
intr_cfg.pa3 = regk_gio_hi;
- }
- if (tmp & (1 << 4)) {
+ if (tmp & (1 << 4))
intr_cfg.pa4 = regk_gio_hi;
- }
- if (tmp & (1 << 5)) {
+ if (tmp & (1 << 5))
intr_cfg.pa5 = regk_gio_hi;
- }
- if (tmp & (1 << 6)) {
+ if (tmp & (1 << 6))
intr_cfg.pa6 = regk_gio_hi;
- }
- if (tmp & (1 << 7)) {
+ if (tmp & (1 << 7))
intr_cfg.pa7 = regk_gio_hi;
- }
/*
* lets activate low for those high and with lowalarm set
*/
tmp = data & priv->lowalarm & 0xFF;
- if (tmp & (1 << 0)) {
+ if (tmp & (1 << 0))
intr_cfg.pa0 = regk_gio_lo;
- }
- if (tmp & (1 << 1)) {
+ if (tmp & (1 << 1))
intr_cfg.pa1 = regk_gio_lo;
- }
- if (tmp & (1 << 2)) {
+ if (tmp & (1 << 2))
intr_cfg.pa2 = regk_gio_lo;
- }
- if (tmp & (1 << 3)) {
+ if (tmp & (1 << 3))
intr_cfg.pa3 = regk_gio_lo;
- }
- if (tmp & (1 << 4)) {
+ if (tmp & (1 << 4))
intr_cfg.pa4 = regk_gio_lo;
- }
- if (tmp & (1 << 5)) {
+ if (tmp & (1 << 5))
intr_cfg.pa5 = regk_gio_lo;
- }
- if (tmp & (1 << 6)) {
+ if (tmp & (1 << 6))
intr_cfg.pa6 = regk_gio_lo;
- }
- if (tmp & (1 << 7)) {
+ if (tmp & (1 << 7))
intr_cfg.pa7 = regk_gio_lo;
- }
REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg);
local_irq_restore(flags);
@@ -277,50 +245,65 @@ gpio_poll(struct file *file,
else
return 0;
- if ((data & priv->highalarm) ||
- (~data & priv->lowalarm)) {
+ if ((data & priv->highalarm) || (~data & priv->lowalarm))
mask = POLLIN|POLLRDNORM;
- }
- DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
+ DP(printk(KERN_DEBUG "gpio_poll ready: mask 0x%08X\n", mask));
return mask;
}
int etrax_gpio_wake_up_check(void)
{
- struct gpio_private *priv = alarmlist;
+ struct gpio_private *priv;
unsigned long data = 0;
- int ret = 0;
+ unsigned long flags;
+ int ret = 0;
+ spin_lock_irqsave(&alarm_lock, flags);
+ priv = alarmlist;
while (priv) {
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ if (priv->minor == GPIO_MINOR_V)
+ data = (unsigned long)cached_virtual_gpio_read;
+ else {
+ data = *data_in[priv->minor];
+ if (priv->minor == GPIO_MINOR_A)
+ priv->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
+ }
+#else
data = *data_in[priv->minor];
+#endif
if ((data & priv->highalarm) ||
(~data & priv->lowalarm)) {
- DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor));
+ DP(printk(KERN_DEBUG
+ "etrax_gpio_wake_up_check %i\n", priv->minor));
wake_up_interruptible(&priv->alarm_wq);
- ret = 1;
+ ret = 1;
}
priv = priv->next;
}
- return ret;
+ spin_unlock_irqrestore(&alarm_lock, flags);
+ return ret;
}
static irqreturn_t
-gpio_poll_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+gpio_poll_timer_interrupt(int irq, void *dev_id)
{
- if (gpio_some_alarms) {
+ if (gpio_some_alarms)
return IRQ_RETVAL(etrax_gpio_wake_up_check());
- }
- return IRQ_NONE;
+ return IRQ_NONE;
}
static irqreturn_t
-gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+gpio_pa_interrupt(int irq, void *dev_id)
{
reg_gio_rw_intr_mask intr_mask;
reg_gio_r_masked_intr masked_intr;
reg_gio_rw_ack_intr ack_intr;
unsigned long tmp;
unsigned long tmp2;
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ unsigned char enable_gpiov_ack = 0;
+#endif
/* Find what PA interrupts are active */
masked_intr = REG_RD(gio, regi_gio, r_masked_intr);
@@ -331,6 +314,17 @@ gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
tmp &= (gpio_pa_high_alarms | gpio_pa_low_alarms);
spin_unlock(&alarm_lock);
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ /* Something changed on virtual GPIO. Interrupt is acked by
+ * reading the device.
+ */
+ if (tmp & (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN)) {
+ i2c_read(VIRT_I2C_ADDR, (void *)&cached_virtual_gpio_read,
+ sizeof(cached_virtual_gpio_read));
+ enable_gpiov_ack = 1;
+ }
+#endif
+
/* Ack them */
ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp);
REG_WR(gio, regi_gio, rw_ack_intr, ack_intr);
@@ -339,18 +333,24 @@ gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);
tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask);
tmp2 &= ~tmp;
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ /* Do not disable interrupt on virtual GPIO. Changes on virtual
+ * pins are only noticed by an interrupt.
+ */
+ if (enable_gpiov_ack)
+ tmp2 |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
+#endif
intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2);
REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);
- if (gpio_some_alarms) {
+ if (gpio_some_alarms)
return IRQ_RETVAL(etrax_gpio_wake_up_check());
- }
- return IRQ_NONE;
+ return IRQ_NONE;
}
-static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
- loff_t *off)
+static ssize_t gpio_write(struct file *file, const char *buf, size_t count,
+ loff_t *off)
{
struct gpio_private *priv = (struct gpio_private *)file->private_data;
unsigned char data, clk_mask, data_mask, write_msb;
@@ -360,29 +360,31 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
ssize_t retval = count;
/* Only bits 0-7 may be used for write operations but allow all
devices except leds... */
- if (priv->minor == GPIO_MINOR_LEDS) {
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ if (priv->minor == GPIO_MINOR_V)
+ return -EFAULT;
+#endif
+ if (priv->minor == GPIO_MINOR_LEDS)
return -EFAULT;
- }
- if (!access_ok(VERIFY_READ, buf, count)) {
+ if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
- }
clk_mask = priv->clk_mask;
data_mask = priv->data_mask;
/* It must have been configured using the IO_CFG_WRITE_MODE */
/* Perhaps a better error code? */
- if (clk_mask == 0 || data_mask == 0) {
+ if (clk_mask == 0 || data_mask == 0)
return -EPERM;
- }
write_msb = priv->write_msb;
- D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
+ D(printk(KERN_DEBUG "gpio_write: %lu to data 0x%02X clk 0x%02X "
+ "msb: %i\n", count, data_mask, clk_mask, write_msb));
port = data_out[priv->minor];
while (count--) {
int i;
data = *buf++;
if (priv->write_msb) {
- for (i = 7; i >= 0;i--) {
+ for (i = 7; i >= 0; i--) {
local_irq_save(flags);
shadow = *port;
*port = shadow &= ~clk_mask;
@@ -395,7 +397,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
local_irq_restore(flags);
}
} else {
- for (i = 0; i <= 7;i++) {
+ for (i = 0; i <= 7; i++) {
local_irq_save(flags);
shadow = *port;
*port = shadow &= ~clk_mask;
@@ -423,18 +425,16 @@ gpio_open(struct inode *inode, struct file *filp)
if (p > GPIO_MINOR_LAST)
return -EINVAL;
- priv = kmalloc(sizeof(struct gpio_private),
- GFP_KERNEL);
+ priv = kmalloc(sizeof(struct gpio_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ memset(priv, 0, sizeof(*priv));
priv->minor = p;
- /* initialize the io/alarm struct and link it into our alarmlist */
+ /* initialize the io/alarm struct */
- priv->next = alarmlist;
- alarmlist = priv;
priv->clk_mask = 0;
priv->data_mask = 0;
priv->highalarm = 0;
@@ -443,20 +443,30 @@ gpio_open(struct inode *inode, struct file *filp)
filp->private_data = (void *)priv;
+ /* link it into our alarmlist */
+ spin_lock_irq(&alarm_lock);
+ priv->next = alarmlist;
+ alarmlist = priv;
+ spin_unlock_irq(&alarm_lock);
+
return 0;
}
static int
gpio_release(struct inode *inode, struct file *filp)
{
- struct gpio_private *p = alarmlist;
- struct gpio_private *todel = (struct gpio_private *)filp->private_data;
+ struct gpio_private *p;
+ struct gpio_private *todel;
/* local copies while updating them: */
unsigned long a_high, a_low;
unsigned long some_alarms;
/* unlink from alarmlist and free the private structure */
+ spin_lock_irq(&alarm_lock);
+ p = alarmlist;
+ todel = (struct gpio_private *)filp->private_data;
+
if (p == todel) {
alarmlist = todel->next;
} else {
@@ -468,26 +478,35 @@ gpio_release(struct inode *inode, struct file *filp)
kfree(todel);
/* Check if there are still any alarms set */
p = alarmlist;
- some_alarms = 0;
+ some_alarms = 0;
a_high = 0;
a_low = 0;
while (p) {
if (p->minor == GPIO_MINOR_A) {
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ p->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
+#endif
a_high |= p->highalarm;
a_low |= p->lowalarm;
}
- if (p->highalarm | p->lowalarm) {
+ if (p->highalarm | p->lowalarm)
some_alarms = 1;
- }
p = p->next;
}
- spin_lock(&alarm_lock);
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ /* Variables 'some_alarms' and 'a_low' needs to be set here again
+ * to ensure that interrupt for virtual GPIO is handled.
+ */
+ some_alarms = 1;
+ a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
+#endif
+
gpio_some_alarms = some_alarms;
gpio_pa_high_alarms = a_high;
gpio_pa_low_alarms = a_low;
- spin_unlock(&alarm_lock);
+ spin_unlock_irq(&alarm_lock);
return 0;
}
@@ -496,7 +515,7 @@ gpio_release(struct inode *inode, struct file *filp)
* set alarms to wait for using a subsequent select().
*/
-unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
+inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg)
{
/* Set direction 0=unchanged 1=input,
* return mask with 1=input
@@ -512,13 +531,17 @@ unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
if (priv->minor == GPIO_MINOR_A)
dir_shadow ^= 0xFF; /* Only 8 bits */
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ else if (priv->minor == GPIO_MINOR_V)
+ dir_shadow ^= 0xFFFF; /* Only 16 bits */
+#endif
else
dir_shadow ^= 0x3FFFF; /* Only 18 bits */
return dir_shadow;
} /* setget_input */
-unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
+inline unsigned long setget_output(struct gpio_private *priv, unsigned long arg)
{
unsigned long flags;
unsigned long dir_shadow;
@@ -542,20 +565,22 @@ gpio_ioctl(struct inode *inode, struct file *file,
unsigned long val;
unsigned long shadow;
struct gpio_private *priv = (struct gpio_private *)file->private_data;
- if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
+ if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE)
return -EINVAL;
- }
+
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ if (priv->minor == GPIO_MINOR_V)
+ return virtual_gpio_ioctl(file, cmd, arg);
+#endif
switch (_IOC_NR(cmd)) {
case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
- // read the port
+ /* Read the port. */
return *data_in[priv->minor];
break;
case IO_SETBITS:
local_irq_save(flags);
- if (arg & 0x04)
- printk("GPIO SET 2\n");
- // set changeable bits with a 1 in arg
+ /* Set changeable bits with a 1 in arg. */
shadow = *data_out[priv->minor];
shadow |= (arg & changeable_bits[priv->minor]);
*data_out[priv->minor] = shadow;
@@ -563,46 +588,42 @@ gpio_ioctl(struct inode *inode, struct file *file,
break;
case IO_CLRBITS:
local_irq_save(flags);
- if (arg & 0x04)
- printk("GPIO CLR 2\n");
- // clear changeable bits with a 1 in arg
+ /* Clear changeable bits with a 1 in arg. */
shadow = *data_out[priv->minor];
shadow &= ~(arg & changeable_bits[priv->minor]);
*data_out[priv->minor] = shadow;
local_irq_restore(flags);
break;
case IO_HIGHALARM:
- // set alarm when bits with 1 in arg go high
+ /* Set alarm when bits with 1 in arg go high. */
priv->highalarm |= arg;
- spin_lock(&alarm_lock);
+ spin_lock_irqsave(&alarm_lock, flags);
gpio_some_alarms = 1;
- if (priv->minor == GPIO_MINOR_A) {
+ if (priv->minor == GPIO_MINOR_A)
gpio_pa_high_alarms |= arg;
- }
- spin_unlock(&alarm_lock);
+ spin_unlock_irqrestore(&alarm_lock, flags);
break;
case IO_LOWALARM:
- // set alarm when bits with 1 in arg go low
+ /* Set alarm when bits with 1 in arg go low. */
priv->lowalarm |= arg;
- spin_lock(&alarm_lock);
+ spin_lock_irqsave(&alarm_lock, flags);
gpio_some_alarms = 1;
- if (priv->minor == GPIO_MINOR_A) {
+ if (priv->minor == GPIO_MINOR_A)
gpio_pa_low_alarms |= arg;
- }
- spin_unlock(&alarm_lock);
+ spin_unlock_irqrestore(&alarm_lock, flags);
break;
case IO_CLRALARM:
- // clear alarm for bits with 1 in arg
+ /* Clear alarm for bits with 1 in arg. */
priv->highalarm &= ~arg;
priv->lowalarm &= ~arg;
- spin_lock(&alarm_lock);
+ spin_lock_irqsave(&alarm_lock, flags);
if (priv->minor == GPIO_MINOR_A) {
if (gpio_pa_high_alarms & arg ||
- gpio_pa_low_alarms & arg) {
+ gpio_pa_low_alarms & arg)
/* Must update the gpio_pa_*alarms masks */
- }
+ ;
}
- spin_unlock(&alarm_lock);
+ spin_unlock_irqrestore(&alarm_lock, flags);
break;
case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
/* Read direction 0=input 1=output */
@@ -633,8 +654,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
if (!((priv->clk_mask & changeable_bits[priv->minor]) &&
(priv->data_mask & changeable_bits[priv->minor]) &&
(priv->clk_mask & dir_shadow) &&
- (priv->data_mask & dir_shadow)))
- {
+ (priv->data_mask & dir_shadow))) {
priv->clk_mask = 0;
priv->data_mask = 0;
return -EPERM;
@@ -644,34 +664,34 @@ gpio_ioctl(struct inode *inode, struct file *file,
case IO_READ_INBITS:
/* *arg is result of reading the input pins */
val = *data_in[priv->minor];
- if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
return -EFAULT;
return 0;
break;
case IO_READ_OUTBITS:
/* *arg is result of reading the output shadow */
val = *data_out[priv->minor];
- if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
return -EFAULT;
break;
case IO_SETGET_INPUT:
/* bits set in *arg is set to input,
* *arg updated with current input pins.
*/
- if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
+ if (copy_from_user(&val, (unsigned long *)arg, sizeof(val)))
return -EFAULT;
val = setget_input(priv, val);
- if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
return -EFAULT;
break;
case IO_SETGET_OUTPUT:
/* bits set in *arg is set to output,
* *arg updated with current output pins.
*/
- if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
+ if (copy_from_user(&val, (unsigned long *)arg, sizeof(val)))
return -EFAULT;
val = setget_output(priv, val);
- if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
+ if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
return -EFAULT;
break;
default:
@@ -684,6 +704,133 @@ gpio_ioctl(struct inode *inode, struct file *file,
return 0;
}
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+static int
+virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ unsigned long flags;
+ unsigned short val;
+ unsigned short shadow;
+ struct gpio_private *priv = (struct gpio_private *)file->private_data;
+
+ switch (_IOC_NR(cmd)) {
+ case IO_SETBITS:
+ local_irq_save(flags);
+ /* Set changeable bits with a 1 in arg. */
+ i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
+ shadow |= ~*dir_oe[priv->minor];
+ shadow |= (arg & changeable_bits[priv->minor]);
+ i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
+ local_irq_restore(flags);
+ break;
+ case IO_CLRBITS:
+ local_irq_save(flags);
+ /* Clear changeable bits with a 1 in arg. */
+ i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
+ shadow |= ~*dir_oe[priv->minor];
+ shadow &= ~(arg & changeable_bits[priv->minor]);
+ i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
+ local_irq_restore(flags);
+ break;
+ case IO_HIGHALARM:
+ /* Set alarm when bits with 1 in arg go high. */
+ priv->highalarm |= arg;
+ spin_lock(&alarm_lock);
+ gpio_some_alarms = 1;
+ spin_unlock(&alarm_lock);
+ break;
+ case IO_LOWALARM:
+ /* Set alarm when bits with 1 in arg go low. */
+ priv->lowalarm |= arg;
+ spin_lock(&alarm_lock);
+ gpio_some_alarms = 1;
+ spin_unlock(&alarm_lock);
+ break;
+ case IO_CLRALARM:
+ /* Clear alarm for bits with 1 in arg. */
+ priv->highalarm &= ~arg;
+ priv->lowalarm &= ~arg;
+ spin_lock(&alarm_lock);
+ spin_unlock(&alarm_lock);
+ break;
+ case IO_CFG_WRITE_MODE:
+ {
+ unsigned long dir_shadow;
+ dir_shadow = *dir_oe[priv->minor];
+
+ priv->clk_mask = arg & 0xFF;
+ priv->data_mask = (arg >> 8) & 0xFF;
+ priv->write_msb = (arg >> 16) & 0x01;
+ /* Check if we're allowed to change the bits and
+ * the direction is correct
+ */
+ if (!((priv->clk_mask & changeable_bits[priv->minor]) &&
+ (priv->data_mask & changeable_bits[priv->minor]) &&
+ (priv->clk_mask & dir_shadow) &&
+ (priv->data_mask & dir_shadow))) {
+ priv->clk_mask = 0;
+ priv->data_mask = 0;
+ return -EPERM;
+ }
+ break;
+ }
+ case IO_READ_INBITS:
+ /* *arg is result of reading the input pins */
+ val = cached_virtual_gpio_read;
+ val &= ~*dir_oe[priv->minor];
+ if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ return 0;
+ break;
+ case IO_READ_OUTBITS:
+ /* *arg is result of reading the output shadow */
+ i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val));
+ val &= *dir_oe[priv->minor];
+ if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ break;
+ case IO_SETGET_INPUT:
+ {
+ /* bits set in *arg is set to input,
+ * *arg updated with current input pins.
+ */
+ unsigned short input_mask = ~*dir_oe[priv->minor];
+ if (copy_from_user(&val, (unsigned long *)arg, sizeof(val)))
+ return -EFAULT;
+ val = setget_input(priv, val);
+ if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ if ((input_mask & val) != input_mask) {
+ /* Input pins changed. All ports desired as input
+ * should be set to logic 1.
+ */
+ unsigned short change = input_mask ^ val;
+ i2c_read(VIRT_I2C_ADDR, (void *)&shadow,
+ sizeof(shadow));
+ shadow &= ~change;
+ shadow |= val;
+ i2c_write(VIRT_I2C_ADDR, (void *)&shadow,
+ sizeof(shadow));
+ }
+ break;
+ }
+ case IO_SETGET_OUTPUT:
+ /* bits set in *arg is set to output,
+ * *arg updated with current output pins.
+ */
+ if (copy_from_user(&val, (unsigned long *)arg, sizeof(val)))
+ return -EFAULT;
+ val = setget_output(priv, val);
+ if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
+ return -EFAULT;
+ break;
+ default:
+ return -EINVAL;
+ } /* switch */
+ return 0;
+}
+#endif /* CONFIG_ETRAX_VIRTUAL_GPIO */
+
static int
gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
{
@@ -694,8 +841,8 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
case IO_LEDACTIVE_SET:
green = ((unsigned char) arg) & 1;
red = (((unsigned char) arg) >> 1) & 1;
- LED_ACTIVE_SET_G(green);
- LED_ACTIVE_SET_R(red);
+ CRIS_LED_ACTIVE_SET_G(green);
+ CRIS_LED_ACTIVE_SET_R(red);
break;
default:
@@ -705,7 +852,7 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
return 0;
}
-const struct file_operations gpio_fops = {
+struct file_operations gpio_fops = {
.owner = THIS_MODULE,
.poll = gpio_poll,
.ioctl = gpio_ioctl,
@@ -714,6 +861,66 @@ const struct file_operations gpio_fops = {
.release = gpio_release,
};
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+static void
+virtual_gpio_init(void)
+{
+ reg_gio_rw_intr_cfg intr_cfg;
+ reg_gio_rw_intr_mask intr_mask;
+ unsigned short shadow;
+
+ shadow = ~virtual_rw_pv_oe; /* Input ports should be set to logic 1 */
+ shadow |= CONFIG_ETRAX_DEF_GIO_PV_OUT;
+ i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
+
+ /* Set interrupt mask and on what state the interrupt shall trigger.
+ * For virtual gpio the interrupt shall trigger on logic '0'.
+ */
+ intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg);
+ intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);
+
+ switch (CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN) {
+ case 0:
+ intr_cfg.pa0 = regk_gio_lo;
+ intr_mask.pa0 = regk_gio_yes;
+ break;
+ case 1:
+ intr_cfg.pa1 = regk_gio_lo;
+ intr_mask.pa1 = regk_gio_yes;
+ break;
+ case 2:
+ intr_cfg.pa2 = regk_gio_lo;
+ intr_mask.pa2 = regk_gio_yes;
+ break;
+ case 3:
+ intr_cfg.pa3 = regk_gio_lo;
+ intr_mask.pa3 = regk_gio_yes;
+ break;
+ case 4:
+ intr_cfg.pa4 = regk_gio_lo;
+ intr_mask.pa4 = regk_gio_yes;
+ break;
+ case 5:
+ intr_cfg.pa5 = regk_gio_lo;
+ intr_mask.pa5 = regk_gio_yes;
+ break;
+ case 6:
+ intr_cfg.pa6 = regk_gio_lo;
+ intr_mask.pa6 = regk_gio_yes;
+ break;
+ case 7:
+ intr_cfg.pa7 = regk_gio_lo;
+ intr_mask.pa7 = regk_gio_yes;
+ break;
+ }
+
+ REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg);
+ REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);
+
+ gpio_pa_low_alarms |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
+ gpio_some_alarms = 1;
+}
+#endif
/* main driver initialization routine, called from mem.c */
@@ -721,7 +928,6 @@ static __init int
gpio_init(void)
{
int res;
- reg_intr_vect_rw_mask intr_mask;
/* do the formalities */
@@ -732,30 +938,30 @@ gpio_init(void)
}
/* Clear all leds */
- LED_NETWORK_SET(0);
- LED_ACTIVE_SET(0);
- LED_DISK_READ(0);
- LED_DISK_WRITE(0);
-
- printk("ETRAX FS GPIO driver v2.5, (c) 2003-2005 Axis Communications AB\n");
+ CRIS_LED_NETWORK_GRP0_SET(0);
+ CRIS_LED_NETWORK_GRP1_SET(0);
+ CRIS_LED_ACTIVE_SET(0);
+ CRIS_LED_DISK_READ(0);
+ CRIS_LED_DISK_WRITE(0);
+
+ printk(KERN_INFO "ETRAX FS GPIO driver v2.5, (c) 2003-2007 "
+ "Axis Communications AB\n");
/* We call etrax_gpio_wake_up_check() from timer interrupt and
* from cpu_idle() in kernel/process.c
* The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
* in some tests.
*/
- if (request_irq(TIMER_INTR_VECT, gpio_poll_timer_interrupt,
- IRQF_SHARED | IRQF_DISABLED,"gpio poll", &alarmlist)) {
- printk("err: timer0 irq for gpio\n");
- }
- if (request_irq(GEN_IO_INTR_VECT, gpio_pa_interrupt,
- IRQF_SHARED | IRQF_DISABLED,"gpio PA", &alarmlist)) {
- printk("err: PA irq for gpio\n");
- }
- /* enable the gio and timer irq in global config */
- intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);
- intr_mask.timer = 1;
- intr_mask.gen_io = 1;
- REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
+ if (request_irq(TIMER0_INTR_VECT, gpio_poll_timer_interrupt,
+ IRQF_SHARED | IRQF_DISABLED, "gpio poll", &alarmlist))
+ printk(KERN_ERR "timer0 irq for gpio\n");
+
+ if (request_irq(GIO_INTR_VECT, gpio_pa_interrupt,
+ IRQF_SHARED | IRQF_DISABLED, "gpio PA", &alarmlist))
+ printk(KERN_ERR "PA irq for gpio\n");
+
+#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
+ virtual_gpio_init();
+#endif
return res;
}
diff --git a/arch/cris/arch-v32/drivers/nandflash.c b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
index 5ce015c6bb0..aa01b134458 100644
--- a/arch/cris/arch-v32/drivers/nandflash.c
+++ b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
@@ -4,9 +4,7 @@
* Copyright (c) 2004
*
* Derived from drivers/mtd/nand/spia.c
- * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
- *
- * $Id: nandflash.c,v 1.3 2005/06/01 10:57:12 starvik Exp $
+ * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.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
@@ -21,10 +19,10 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/arch/memmap.h>
-#include <asm/arch/hwregs/reg_map.h>
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/gio_defs.h>
-#include <asm/arch/hwregs/bif_core_defs.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/gio_defs.h>
+#include <hwregs/bif_core_defs.h>
#include <asm/io.h>
#define CE_BIT 4
@@ -32,44 +30,65 @@
#define ALE_BIT 6
#define BY_BIT 7
-static struct mtd_info *crisv32_mtd = NULL;
+struct mtd_info_wrapper {
+ struct mtd_info info;
+ struct nand_chip chip;
+};
+
+/* Bitmask for control pins */
+#define PIN_BITMASK ((1 << CE_BIT) | (1 << CLE_BIT) | (1 << ALE_BIT))
+
+/* Bitmask for mtd nand control bits */
+#define CTRL_BITMASK (NAND_NCE | NAND_CLE | NAND_ALE)
+
+
+static struct mtd_info *crisv32_mtd;
/*
* hardware specific access to control-lines
-*/
-static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd)
+ */
+static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd,
+ unsigned int ctrl)
{
unsigned long flags;
- reg_gio_rw_pa_dout dout = REG_RD(gio, regi_gio, rw_pa_dout);
+ reg_gio_rw_pa_dout dout;
+ struct nand_chip *this = mtd->priv;
local_irq_save(flags);
- switch(cmd){
- case NAND_CTL_SETCLE:
- dout.data |= (1<<CLE_BIT);
- break;
- case NAND_CTL_CLRCLE:
- dout.data &= ~(1<<CLE_BIT);
- break;
- case NAND_CTL_SETALE:
- dout.data |= (1<<ALE_BIT);
- break;
- case NAND_CTL_CLRALE:
- dout.data &= ~(1<<ALE_BIT);
- break;
- case NAND_CTL_SETNCE:
- dout.data |= (1<<CE_BIT);
- break;
- case NAND_CTL_CLRNCE:
- dout.data &= ~(1<<CE_BIT);
- break;
+
+ /* control bits change */
+ if (ctrl & NAND_CTRL_CHANGE) {
+ dout = REG_RD(gio, regi_gio, rw_pa_dout);
+ dout.data &= ~PIN_BITMASK;
+
+#if (CE_BIT == 4 && NAND_NCE == 1 && \
+ CLE_BIT == 5 && NAND_CLE == 2 && \
+ ALE_BIT == 6 && NAND_ALE == 4)
+ /* Pins in same order as control bits, but shifted.
+ * Optimize for this case; works for 2.6.18 */
+ dout.data |= ((ctrl & CTRL_BITMASK) ^ NAND_NCE) << CE_BIT;
+#else
+ /* the slow way */
+ if (!(ctrl & NAND_NCE))
+ dout.data |= (1 << CE_BIT);
+ if (ctrl & NAND_CLE)
+ dout.data |= (1 << CLE_BIT);
+ if (ctrl & NAND_ALE)
+ dout.data |= (1 << ALE_BIT);
+#endif
+ REG_WR(gio, regi_gio, rw_pa_dout, dout);
}
- REG_WR(gio, regi_gio, rw_pa_dout, dout);
+
+ /* command to chip */
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
+
local_irq_restore(flags);
}
/*
* read device ready pin
*/
-int crisv32_device_ready(struct mtd_info *mtd)
+static int crisv32_device_ready(struct mtd_info *mtd)
{
reg_gio_r_pa_din din = REG_RD(gio, regi_gio, r_pa_din);
return ((din.data & (1 << BY_BIT)) >> BY_BIT);
@@ -78,21 +97,23 @@ int crisv32_device_ready(struct mtd_info *mtd)
/*
* Main initialization routine
*/
-struct mtd_info* __init crisv32_nand_flash_probe (void)
+struct mtd_info *__init crisv32_nand_flash_probe(void)
{
void __iomem *read_cs;
void __iomem *write_cs;
- reg_bif_core_rw_grp3_cfg bif_cfg = REG_RD(bif_core, regi_bif_core, rw_grp3_cfg);
+ reg_bif_core_rw_grp3_cfg bif_cfg = REG_RD(bif_core, regi_bif_core,
+ rw_grp3_cfg);
reg_gio_rw_pa_oe pa_oe = REG_RD(gio, regi_gio, rw_pa_oe);
+ struct mtd_info_wrapper *wrapper;
struct nand_chip *this;
int err = 0;
/* Allocate memory for MTD device structure and private data */
- crisv32_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
- GFP_KERNEL);
- if (!crisv32_mtd) {
- printk ("Unable to allocate CRISv32 NAND MTD device structure.\n");
+ wrapper = kzalloc(sizeof(struct mtd_info_wrapper), GFP_KERNEL);
+ if (!wrapper) {
+ printk(KERN_ERR "Unable to allocate CRISv32 NAND MTD "
+ "device structure.\n");
err = -ENOMEM;
return NULL;
}
@@ -101,45 +122,42 @@ struct mtd_info* __init crisv32_nand_flash_probe (void)
write_cs = ioremap(MEM_CSP1_START | MEM_NON_CACHEABLE, 8192);
if (!read_cs || !write_cs) {
- printk("CRISv32 NAND ioremap failed\n");
+ printk(KERN_ERR "CRISv32 NAND ioremap failed\n");
err = -EIO;
goto out_mtd;
}
/* Get pointer to private data */
- this = (struct nand_chip *) (&crisv32_mtd[1]);
+ this = &wrapper->chip;
+ crisv32_mtd = &wrapper->info;
pa_oe.oe |= 1 << CE_BIT;
pa_oe.oe |= 1 << ALE_BIT;
pa_oe.oe |= 1 << CLE_BIT;
- pa_oe.oe &= ~ (1 << BY_BIT);
+ pa_oe.oe &= ~(1 << BY_BIT);
REG_WR(gio, regi_gio, rw_pa_oe, pa_oe);
bif_cfg.gated_csp0 = regk_bif_core_rd;
bif_cfg.gated_csp1 = regk_bif_core_wr;
REG_WR(bif_core, regi_bif_core, rw_grp3_cfg, bif_cfg);
- /* Initialize structures */
- memset((char *) crisv32_mtd, 0, sizeof(struct mtd_info));
- memset((char *) this, 0, sizeof(struct nand_chip));
-
/* Link the private data with the MTD structure */
crisv32_mtd->priv = this;
/* Set address of NAND IO lines */
this->IO_ADDR_R = read_cs;
this->IO_ADDR_W = write_cs;
- this->hwcontrol = crisv32_hwcontrol;
+ this->cmd_ctrl = crisv32_hwcontrol;
this->dev_ready = crisv32_device_ready;
/* 20 us command delay time */
this->chip_delay = 20;
- this->eccmode = NAND_ECC_SOFT;
+ this->ecc.mode = NAND_ECC_SOFT;
/* Enable the following for a flash based bad block table */
- this->options = NAND_USE_FLASH_BBT;
+ /* this->options = NAND_USE_FLASH_BBT; */
- /* Scan to find existence of the device */
- if (nand_scan (crisv32_mtd, 1)) {
+ /* Scan to find existance of the device */
+ if (nand_scan(crisv32_mtd, 1)) {
err = -ENXIO;
goto out_ior;
}
@@ -150,7 +168,7 @@ out_ior:
iounmap((void *)read_cs);
iounmap((void *)write_cs);
out_mtd:
- kfree (crisv32_mtd);
- return NULL;
+ kfree(wrapper);
+ return NULL;
}
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
index 6dbd700d3d6..53db3870ba0 100644
--- a/arch/cris/arch-v32/drivers/pcf8563.c
+++ b/arch/cris/arch-v32/drivers/pcf8563.c
@@ -10,7 +10,7 @@
* 400 kbits/s. The built-in word address register is incremented
* automatically after each written or read byte.
*
- * Copyright (c) 2002-2003, Axis Communications AB
+ * Copyright (c) 2002-2007, Axis Communications AB
* All rights reserved.
*
* Author: Tobias Anderberg <tobiasa@axis.com>.
@@ -26,6 +26,7 @@
#include <linux/ioctl.h>
#include <linux/delay.h>
#include <linux/bcd.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -37,24 +38,27 @@
#define PCF8563_MAJOR 121 /* Local major number. */
#define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */
#define PCF8563_NAME "PCF8563"
-#define DRIVER_VERSION "$Revision: 1.1 $"
+#define DRIVER_VERSION "$Revision: 1.17 $"
/* Two simple wrapper macros, saves a few keystrokes. */
#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
+static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
+
static const unsigned char days_in_month[] =
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
-int pcf8563_open(struct inode *, struct file *);
-int pcf8563_release(struct inode *, struct file *);
+
+/* Cache VL bit value read at driver init since writing the RTC_SECOND
+ * register clears the VL status.
+ */
+static int voltage_low;
static const struct file_operations pcf8563_fops = {
.owner = THIS_MODULE,
- .ioctl = pcf8563_ioctl,
- .open = pcf8563_open,
- .release = pcf8563_release,
+ .ioctl = pcf8563_ioctl
};
unsigned char
@@ -62,7 +66,7 @@ pcf8563_readreg(int reg)
{
unsigned char res = rtc_read(reg);
- /* The PCF8563 does not return 0 for unimplemented bits */
+ /* The PCF8563 does not return 0 for unimplemented bits. */
switch (reg) {
case RTC_SECONDS:
case RTC_MINUTES:
@@ -95,11 +99,6 @@ pcf8563_readreg(int reg)
void
pcf8563_writereg(int reg, unsigned char val)
{
-#ifdef CONFIG_ETRAX_RTC_READONLY
- if (reg == RTC_CONTROL1 || (reg >= RTC_SECONDS && reg <= RTC_YEAR))
- return;
-#endif
-
rtc_write(reg, val);
}
@@ -114,11 +113,13 @@ get_rtc_time(struct rtc_time *tm)
tm->tm_mon = rtc_read(RTC_MONTH);
tm->tm_year = rtc_read(RTC_YEAR);
- if (tm->tm_sec & 0x80)
- printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "
+ if (tm->tm_sec & 0x80) {
+ printk(KERN_ERR "%s: RTC Voltage Low - reliable date/time "
"information is no longer guaranteed!\n", PCF8563_NAME);
+ }
- tm->tm_year = BCD_TO_BIN(tm->tm_year) + ((tm->tm_mon & 0x80) ? 100 : 0);
+ tm->tm_year = BCD_TO_BIN(tm->tm_year) +
+ ((tm->tm_mon & 0x80) ? 100 : 0);
tm->tm_sec &= 0x7F;
tm->tm_min &= 0x7F;
tm->tm_hour &= 0x3F;
@@ -137,8 +138,19 @@ get_rtc_time(struct rtc_time *tm)
int __init
pcf8563_init(void)
{
+ static int res;
+ static int first = 1;
+
+ if (!first)
+ return res;
+ first = 0;
+
/* Initiate the i2c protocol. */
- i2c_init();
+ res = i2c_init();
+ if (res < 0) {
+ printk(KERN_CRIT "pcf8563_init: Failed to init i2c.\n");
+ return res;
+ }
/*
* First of all we need to reset the chip. This is done by
@@ -170,24 +182,20 @@ pcf8563_init(void)
if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0)
goto err;
- if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
- printk(KERN_INFO "%s: Unable to get major number %d for RTC device.\n",
- PCF8563_NAME, PCF8563_MAJOR);
- return -1;
+ /* Check for low voltage, and warn about it. */
+ if (rtc_read(RTC_SECONDS) & 0x80) {
+ voltage_low = 1;
+ printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
+ "date/time information is no longer guaranteed!\n",
+ PCF8563_NAME);
}
- printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);
-
- /* Check for low voltage, and warn about it.. */
- if (rtc_read(RTC_SECONDS) & 0x80)
- printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "
- "information is no longer guaranteed!\n", PCF8563_NAME);
-
- return 0;
+ return res;
err:
printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME);
- return -1;
+ res = -1;
+ return res;
}
void __exit
@@ -200,8 +208,8 @@ pcf8563_exit(void)
* ioctl calls for this driver. Why return -ENOTTY upon error? Because
* POSIX says so!
*/
-int
-pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
{
/* Some sanity checks. */
if (_IOC_TYPE(cmd) != RTC_MAGIC)
@@ -211,125 +219,147 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
return -ENOTTY;
switch (cmd) {
- case RTC_RD_TIME:
- {
- struct rtc_time tm;
-
- memset(&tm, 0, sizeof (struct rtc_time));
- get_rtc_time(&tm);
-
- if (copy_to_user((struct rtc_time *) arg, &tm, sizeof tm)) {
- return -EFAULT;
- }
-
- return 0;
+ case RTC_RD_TIME:
+ {
+ struct rtc_time tm;
+
+ mutex_lock(&rtc_lock);
+ memset(&tm, 0, sizeof tm);
+ get_rtc_time(&tm);
+
+ if (copy_to_user((struct rtc_time *) arg, &tm,
+ sizeof tm)) {
+ spin_unlock(&rtc_lock);
+ return -EFAULT;
}
- case RTC_SET_TIME:
- {
-#ifdef CONFIG_ETRAX_RTC_READONLY
+ mutex_unlock(&rtc_lock);
+
+ return 0;
+ }
+ case RTC_SET_TIME:
+ {
+ int leap;
+ int year;
+ int century;
+ struct rtc_time tm;
+
+ memset(&tm, 0, sizeof tm);
+ if (!capable(CAP_SYS_TIME))
return -EPERM;
-#else
- int leap;
- int year;
- int century;
- struct rtc_time tm;
-
- if (!capable(CAP_SYS_TIME))
- return -EPERM;
-
- if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof tm))
- return -EFAULT;
-
- /* Convert from struct tm to struct rtc_time. */
- tm.tm_year += 1900;
- tm.tm_mon += 1;
-
- /*
- * Check if tm.tm_year is a leap year. A year is a leap
- * year if it is divisible by 4 but not 100, except
- * that years divisible by 400 _are_ leap years.
- */
- year = tm.tm_year;
- leap = (tm.tm_mon == 2) && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
-
- /* Perform some sanity checks. */
- if ((tm.tm_year < 1970) ||
- (tm.tm_mon > 12) ||
- (tm.tm_mday == 0) ||
- (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
- (tm.tm_wday >= 7) ||
- (tm.tm_hour >= 24) ||
- (tm.tm_min >= 60) ||
- (tm.tm_sec >= 60))
- return -EINVAL;
-
- century = (tm.tm_year >= 2000) ? 0x80 : 0;
- tm.tm_year = tm.tm_year % 100;
-
- BIN_TO_BCD(tm.tm_year);
- BIN_TO_BCD(tm.tm_mday);
- BIN_TO_BCD(tm.tm_hour);
- BIN_TO_BCD(tm.tm_min);
- BIN_TO_BCD(tm.tm_sec);
- tm.tm_mon |= century;
-
- rtc_write(RTC_YEAR, tm.tm_year);
- rtc_write(RTC_MONTH, tm.tm_mon);
- rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */
- rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
- rtc_write(RTC_HOURS, tm.tm_hour);
- rtc_write(RTC_MINUTES, tm.tm_min);
- rtc_write(RTC_SECONDS, tm.tm_sec);
-
- return 0;
-#endif /* !CONFIG_ETRAX_RTC_READONLY */
- }
- case RTC_VLOW_RD:
- {
- int vl_bit = 0;
+ if (copy_from_user(&tm, (struct rtc_time *) arg,
+ sizeof tm))
+ return -EFAULT;
+
+ /* Convert from struct tm to struct rtc_time. */
+ tm.tm_year += 1900;
+ tm.tm_mon += 1;
+
+ /*
+ * Check if tm.tm_year is a leap year. A year is a leap
+ * year if it is divisible by 4 but not 100, except
+ * that years divisible by 400 _are_ leap years.
+ */
+ year = tm.tm_year;
+ leap = (tm.tm_mon == 2) &&
+ ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
+
+ /* Perform some sanity checks. */
+ if ((tm.tm_year < 1970) ||
+ (tm.tm_mon > 12) ||
+ (tm.tm_mday == 0) ||
+ (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
+ (tm.tm_wday >= 7) ||
+ (tm.tm_hour >= 24) ||
+ (tm.tm_min >= 60) ||
+ (tm.tm_sec >= 60))
+ return -EINVAL;
+
+ century = (tm.tm_year >= 2000) ? 0x80 : 0;
+ tm.tm_year = tm.tm_year % 100;
+
+ BIN_TO_BCD(tm.tm_year);
+ BIN_TO_BCD(tm.tm_mon);
+ BIN_TO_BCD(tm.tm_mday);
+ BIN_TO_BCD(tm.tm_hour);
+ BIN_TO_BCD(tm.tm_min);
+ BIN_TO_BCD(tm.tm_sec);
+ tm.tm_mon |= century;
+
+ mutex_lock(&rtc_lock);
+
+ rtc_write(RTC_YEAR, tm.tm_year);
+ rtc_write(RTC_MONTH, tm.tm_mon);
+ rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */
+ rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
+ rtc_write(RTC_HOURS, tm.tm_hour);
+ rtc_write(RTC_MINUTES, tm.tm_min);
+ rtc_write(RTC_SECONDS, tm.tm_sec);
+
+ mutex_unlock(&rtc_lock);
+
+ return 0;
+ }
+ case RTC_VL_READ:
+ if (voltage_low)
+ printk(KERN_ERR "%s: RTC Voltage Low - "
+ "reliable date/time information is no "
+ "longer guaranteed!\n", PCF8563_NAME);
- if (rtc_read(RTC_SECONDS) & 0x80) {
- vl_bit = 1;
- printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
- "date/time information is no longer guaranteed!\n",
- PCF8563_NAME);
- }
- if (copy_to_user((int *) arg, &vl_bit, sizeof(int)))
- return -EFAULT;
+ if (copy_to_user((int *) arg, &voltage_low, sizeof(int)))
+ return -EFAULT;
+ return 0;
- return 0;
- }
+ case RTC_VL_CLR:
+ {
+ /* Clear the VL bit in the seconds register in case
+ * the time has not been set already (which would
+ * have cleared it). This does not really matter
+ * because of the cached voltage_low value but do it
+ * anyway for consistency. */
- case RTC_VLOW_SET:
- {
- /* Clear the VL bit in the seconds register */
- int ret = rtc_read(RTC_SECONDS);
+ int ret = rtc_read(RTC_SECONDS);
- rtc_write(RTC_SECONDS, (ret & 0x7F));
+ rtc_write(RTC_SECONDS, (ret & 0x7F));
- return 0;
- }
+ /* Clear the cached value. */
+ voltage_low = 0;
- default:
- return -ENOTTY;
+ return 0;
+ }
+ default:
+ return -ENOTTY;
}
return 0;
}
-int
-pcf8563_open(struct inode *inode, struct file *filp)
+static int __init pcf8563_register(void)
{
- return 0;
-}
+ if (pcf8563_init() < 0) {
+ printk(KERN_INFO "%s: Unable to initialize Real-Time Clock "
+ "Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);
+ return -1;
+ }
+
+ if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
+ printk(KERN_INFO "%s: Unable to get major numer %d for RTC "
+ "device.\n", PCF8563_NAME, PCF8563_MAJOR);
+ return -1;
+ }
+
+ printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME,
+ DRIVER_VERSION);
+
+ /* Check for low voltage, and warn about it. */
+ if (voltage_low) {
+ printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "
+ "information is no longer guaranteed!\n", PCF8563_NAME);
+ }
-int
-pcf8563_release(struct inode *inode, struct file *filp)
-{
return 0;
}
-module_init(pcf8563_init);
+module_init(pcf8563_register);
module_exit(pcf8563_exit);
diff --git a/arch/cris/arch-v32/drivers/pci/dma.c b/arch/cris/arch-v32/drivers/pci/dma.c
index 66f9500fbc0..e0364654fc4 100644
--- a/arch/cris/arch-v32/drivers/pci/dma.c
+++ b/arch/cris/arch-v32/drivers/pci/dma.c
@@ -93,7 +93,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
if (!dev->dma_mem)
- goto out;
+ goto iounmap_out;
dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
if (!dev->dma_mem->bitmap)
goto free1_out;
@@ -110,6 +110,8 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
free1_out:
kfree(dev->dma_mem);
+ iounmap_out:
+ iounmap(mem_base);
out:
return 0;
}
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c
index d581b0a92a3..47c377df6fb 100644
--- a/arch/cris/arch-v32/drivers/sync_serial.c
+++ b/arch/cris/arch-v32/drivers/sync_serial.c
@@ -1,5 +1,5 @@
/*
- * Simple synchronous serial port driver for ETRAX FS.
+ * Simple synchronous serial port driver for ETRAX FS and Artpec-3.
*
* Copyright (c) 2005 Axis Communications AB
*
@@ -21,17 +21,18 @@
#include <linux/spinlock.h>
#include <asm/io.h>
-#include <asm/arch/dma.h>
-#include <asm/arch/pinmux.h>
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/sser_defs.h>
-#include <asm/arch/hwregs/dma_defs.h>
-#include <asm/arch/hwregs/dma.h>
-#include <asm/arch/hwregs/intr_vect_defs.h>
-#include <asm/arch/hwregs/intr_vect.h>
-#include <asm/arch/hwregs/reg_map.h>
+#include <dma.h>
+#include <pinmux.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/sser_defs.h>
+#include <hwregs/dma_defs.h>
+#include <hwregs/dma.h>
+#include <hwregs/intr_vect_defs.h>
+#include <hwregs/intr_vect.h>
+#include <hwregs/reg_map.h>
#include <asm/sync_serial.h>
+
/* The receiver is a bit tricky beacuse of the continuous stream of data.*/
/* */
/* Three DMA descriptors are linked together. Each DMA descriptor is */
@@ -63,8 +64,10 @@
/* words can be handled */
#define IN_BUFFER_SIZE 12288
#define IN_DESCR_SIZE 256
-#define NUM_IN_DESCR (IN_BUFFER_SIZE/IN_DESCR_SIZE)
-#define OUT_BUFFER_SIZE 4096
+#define NBR_IN_DESCR (IN_BUFFER_SIZE/IN_DESCR_SIZE)
+
+#define OUT_BUFFER_SIZE 1024*8
+#define NBR_OUT_DESCR 8
#define DEFAULT_FRAME_RATE 0
#define DEFAULT_WORD_RATE 7
@@ -78,6 +81,8 @@
#define DEBUGPOLL(x)
#define DEBUGRXINT(x)
#define DEBUGTXINT(x)
+#define DEBUGTRDMA(x)
+#define DEBUGOUTBUF(x)
typedef struct sync_port
{
@@ -97,10 +102,11 @@ typedef struct sync_port
int output;
int input;
- volatile unsigned int out_count; /* Remaining bytes for current transfer */
- unsigned char* outp; /* Current position in out_buffer */
- volatile unsigned char* volatile readp; /* Next byte to be read by application */
- volatile unsigned char* volatile writep; /* Next byte to be written by etrax */
+ /* Next byte to be read by application */
+ volatile unsigned char *volatile readp;
+ /* Next byte to be written by etrax */
+ volatile unsigned char *volatile writep;
+
unsigned int in_buffer_size;
unsigned int inbufchunk;
unsigned char out_buffer[OUT_BUFFER_SIZE] __attribute__ ((aligned(32)));
@@ -108,11 +114,30 @@ typedef struct sync_port
unsigned char flip[IN_BUFFER_SIZE] __attribute__ ((aligned(32)));
struct dma_descr_data* next_rx_desc;
struct dma_descr_data* prev_rx_desc;
+
+ /* Pointer to the first available descriptor in the ring,
+ * unless active_tr_descr == catch_tr_descr and a dma
+ * transfer is active */
+ struct dma_descr_data *active_tr_descr;
+
+ /* Pointer to the first allocated descriptor in the ring */
+ struct dma_descr_data *catch_tr_descr;
+
+ /* Pointer to the descriptor with the current end-of-list */
+ struct dma_descr_data *prev_tr_descr;
int full;
- dma_descr_data in_descr[NUM_IN_DESCR] __attribute__ ((__aligned__(16)));
+ /* Pointer to the first byte being read by DMA
+ * or current position in out_buffer if not using DMA. */
+ unsigned char *out_rd_ptr;
+
+ /* Number of bytes currently locked for being read by DMA */
+ int out_buf_count;
+
+ dma_descr_data in_descr[NBR_IN_DESCR] __attribute__ ((__aligned__(16)));
dma_descr_context in_context __attribute__ ((__aligned__(32)));
- dma_descr_data out_descr __attribute__ ((__aligned__(16)));
+ dma_descr_data out_descr[NBR_OUT_DESCR]
+ __attribute__ ((__aligned__(16)));
dma_descr_context out_context __attribute__ ((__aligned__(32)));
wait_queue_head_t out_wait_q;
wait_queue_head_t in_wait_q;
@@ -143,11 +168,11 @@ static ssize_t sync_serial_read(struct file *file, char *buf,
#endif
static void send_word(sync_port* port);
-static void start_dma(struct sync_port *port, const char* data, int count);
+static void start_dma_out(struct sync_port *port, const char *data, int count);
static void start_dma_in(sync_port* port);
#ifdef SYNC_SER_DMA
-static irqreturn_t tr_interrupt(int irq, void *dev_id, struct pt_regs * regs);
-static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t tr_interrupt(int irq, void *dev_id);
+static irqreturn_t rx_interrupt(int irq, void *dev_id);
#endif
#if (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \
@@ -157,22 +182,49 @@ static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs);
#define SYNC_SER_MANUAL
#endif
#ifdef SYNC_SER_MANUAL
-static irqreturn_t manual_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t manual_interrupt(int irq, void *dev_id);
+#endif
+
+#ifdef CONFIG_ETRAXFS /* ETRAX FS */
+#define OUT_DMA_NBR 4
+#define IN_DMA_NBR 5
+#define PINMUX_SSER pinmux_sser0
+#define SYNCSER_INST regi_sser0
+#define SYNCSER_INTR_VECT SSER0_INTR_VECT
+#define OUT_DMA_INST regi_dma4
+#define IN_DMA_INST regi_dma5
+#define DMA_OUT_INTR_VECT DMA4_INTR_VECT
+#define DMA_IN_INTR_VECT DMA5_INTR_VECT
+#define REQ_DMA_SYNCSER dma_sser0
+#else /* Artpec-3 */
+#define OUT_DMA_NBR 6
+#define IN_DMA_NBR 7
+#define PINMUX_SSER pinmux_sser
+#define SYNCSER_INST regi_sser
+#define SYNCSER_INTR_VECT SSER_INTR_VECT
+#define OUT_DMA_INST regi_dma6
+#define IN_DMA_INST regi_dma7
+#define DMA_OUT_INTR_VECT DMA6_INTR_VECT
+#define DMA_IN_INTR_VECT DMA7_INTR_VECT
+#define REQ_DMA_SYNCSER dma_sser
#endif
/* The ports */
static struct sync_port ports[]=
{
{
- .regi_sser = regi_sser0,
- .regi_dmaout = regi_dma4,
- .regi_dmain = regi_dma5,
+ .regi_sser = SYNCSER_INST,
+ .regi_dmaout = OUT_DMA_INST,
+ .regi_dmain = IN_DMA_INST,
#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)
.use_dma = 1,
#else
.use_dma = 0,
#endif
- },
+ }
+#ifdef CONFIG_ETRAXFS
+ ,
+
{
.regi_sser = regi_sser1,
.regi_dmaout = regi_dma6,
@@ -183,9 +235,10 @@ static struct sync_port ports[]=
.use_dma = 0,
#endif
}
+#endif
};
-#define NUMBER_OF_PORTS ARRAY_SIZE(ports)
+#define NBR_PORTS ARRAY_SIZE(ports)
static const struct file_operations sync_serial_fops = {
.owner = THIS_MODULE,
@@ -200,19 +253,21 @@ static const struct file_operations sync_serial_fops = {
static int __init etrax_sync_serial_init(void)
{
ports[0].enabled = 0;
+#ifdef CONFIG_ETRAXFS
ports[1].enabled = 0;
-
- if (register_chrdev(SYNC_SERIAL_MAJOR,"sync serial", &sync_serial_fops) <0 )
- {
- printk("unable to get major for synchronous serial port\n");
+#endif
+ if (register_chrdev(SYNC_SERIAL_MAJOR, "sync serial",
+ &sync_serial_fops) < 0) {
+ printk(KERN_WARNING
+ "Unable to get major for synchronous serial port\n");
return -EBUSY;
}
/* Initialize Ports */
#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0)
- if (crisv32_pinmux_alloc_fixed(pinmux_sser0))
- {
- printk("Unable to allocate pins for syncrhronous serial port 0\n");
+ if (crisv32_pinmux_alloc_fixed(PINMUX_SSER)) {
+ printk(KERN_WARNING
+ "Unable to alloc pins for synchronous serial port 0\n");
return -EIO;
}
ports[0].enabled = 1;
@@ -220,33 +275,40 @@ static int __init etrax_sync_serial_init(void)
#endif
#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1)
- if (crisv32_pinmux_alloc_fixed(pinmux_sser1))
- {
- printk("Unable to allocate pins for syncrhronous serial port 0\n");
+ if (crisv32_pinmux_alloc_fixed(pinmux_sser1)) {
+ printk(KERN_WARNING
+ "Unable to alloc pins for synchronous serial port 0\n");
return -EIO;
}
ports[1].enabled = 1;
initialize_port(1);
#endif
- printk("ETRAX FS synchronous serial port driver\n");
+#ifdef CONFIG_ETRAXFS
+ printk(KERN_INFO "ETRAX FS synchronous serial port driver\n");
+#else
+ printk(KERN_INFO "Artpec-3 synchronous serial port driver\n");
+#endif
return 0;
}
static void __init initialize_port(int portnbr)
{
- struct sync_port* port = &ports[portnbr];
+ int __attribute__((unused)) i;
+ struct sync_port *port = &ports[portnbr];
reg_sser_rw_cfg cfg = {0};
reg_sser_rw_frm_cfg frm_cfg = {0};
reg_sser_rw_tr_cfg tr_cfg = {0};
reg_sser_rw_rec_cfg rec_cfg = {0};
- DEBUG(printk("Init sync serial port %d\n", portnbr));
+ DEBUG(printk(KERN_DEBUG "Init sync serial port %d\n", portnbr));
port->port_nbr = portnbr;
port->init_irqs = 1;
- port->outp = port->out_buffer;
+ port->out_rd_ptr = port->out_buffer;
+ port->out_buf_count = 0;
+
port->output = 1;
port->input = 0;
@@ -255,7 +317,7 @@ static void __init initialize_port(int portnbr)
port->in_buffer_size = IN_BUFFER_SIZE;
port->inbufchunk = IN_DESCR_SIZE;
port->next_rx_desc = &port->in_descr[0];
- port->prev_rx_desc = &port->in_descr[NUM_IN_DESCR-1];
+ port->prev_rx_desc = &port->in_descr[NBR_IN_DESCR-1];
port->prev_rx_desc->eol = 1;
init_waitqueue_head(&port->out_wait_q);
@@ -286,8 +348,13 @@ static void __init initialize_port(int portnbr)
tr_cfg.sample_size = 7;
tr_cfg.sh_dir = regk_sser_msbfirst;
tr_cfg.use_dma = port->use_dma ? regk_sser_yes : regk_sser_no;
+#if 0
tr_cfg.rate_ctrl = regk_sser_bulk;
tr_cfg.data_pin_use = regk_sser_dout;
+#else
+ tr_cfg.rate_ctrl = regk_sser_iso;
+ tr_cfg.data_pin_use = regk_sser_dout;
+#endif
tr_cfg.bulk_wspace = 1;
REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg);
@@ -296,6 +363,27 @@ static void __init initialize_port(int portnbr)
rec_cfg.use_dma = port->use_dma ? regk_sser_yes : regk_sser_no;
rec_cfg.fifo_thr = regk_sser_inf;
REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg);
+
+#ifdef SYNC_SER_DMA
+ /* Setup the descriptor ring for dma out/transmit. */
+ for (i = 0; i < NBR_OUT_DESCR; i++) {
+ port->out_descr[i].wait = 0;
+ port->out_descr[i].intr = 1;
+ port->out_descr[i].eol = 0;
+ port->out_descr[i].out_eop = 0;
+ port->out_descr[i].next =
+ (dma_descr_data *)virt_to_phys(&port->out_descr[i+1]);
+ }
+
+ /* Create a ring from the list. */
+ port->out_descr[NBR_OUT_DESCR-1].next =
+ (dma_descr_data *)virt_to_phys(&port->out_descr[0]);
+
+ /* Setup context for traversing the ring. */
+ port->active_tr_descr = &port->out_descr[0];
+ port->prev_tr_descr = &port->out_descr[NBR_OUT_DESCR-1];
+ port->catch_tr_descr = &port->out_descr[0];
+#endif
}
static inline int sync_data_avail(struct sync_port *port)
@@ -311,7 +399,7 @@ static inline int sync_data_avail(struct sync_port *port)
* ^rp ^wp ^wp ^rp
*/
- if (end >= start)
+ if (end >= start)
avail = end - start;
else
avail = port->in_buffer_size - (start - end);
@@ -331,7 +419,7 @@ static inline int sync_data_avail_to_end(struct sync_port *port)
* ^rp ^wp ^wp ^rp
*/
- if (end >= start)
+ if (end >= start)
avail = end - start;
else
avail = port->flip + port->in_buffer_size - start;
@@ -341,66 +429,69 @@ static inline int sync_data_avail_to_end(struct sync_port *port)
static int sync_serial_open(struct inode *inode, struct file *file)
{
int dev = iminor(inode);
- sync_port* port;
+ sync_port *port;
reg_dma_rw_cfg cfg = {.en = regk_dma_yes};
reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes};
- DEBUG(printk("Open sync serial port %d\n", dev));
+ DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));
- if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
+ if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled)
{
- DEBUG(printk("Invalid minor %d\n", dev));
+ DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev));
return -ENODEV;
}
port = &ports[dev];
/* Allow open this device twice (assuming one reader and one writer) */
if (port->busy == 2)
{
- DEBUG(printk("Device is busy.. \n"));
+ DEBUG(printk(KERN_DEBUG "Device is busy.. \n"));
return -EBUSY;
}
+
+
if (port->init_irqs) {
if (port->use_dma) {
- if (port == &ports[0]){
+ if (port == &ports[0]) {
#ifdef SYNC_SER_DMA
- if(request_irq(DMA4_INTR_VECT,
- tr_interrupt,
- 0,
- "synchronous serial 0 dma tr",
- &ports[0])) {
+ if (request_irq(DMA_OUT_INTR_VECT,
+ tr_interrupt,
+ 0,
+ "synchronous serial 0 dma tr",
+ &ports[0])) {
printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ");
return -EBUSY;
- } else if(request_irq(DMA5_INTR_VECT,
- rx_interrupt,
- 0,
- "synchronous serial 1 dma rx",
- &ports[0])) {
- free_irq(DMA4_INTR_VECT, &port[0]);
+ } else if (request_irq(DMA_IN_INTR_VECT,
+ rx_interrupt,
+ 0,
+ "synchronous serial 1 dma rx",
+ &ports[0])) {
+ free_irq(DMA_OUT_INTR_VECT, &port[0]);
printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ");
return -EBUSY;
- } else if (crisv32_request_dma(SYNC_SER0_TX_DMA_NBR,
- "synchronous serial 0 dma tr",
- DMA_VERBOSE_ON_ERROR,
- 0,
- dma_sser0)) {
- free_irq(DMA4_INTR_VECT, &port[0]);
- free_irq(DMA5_INTR_VECT, &port[0]);
+ } else if (crisv32_request_dma(OUT_DMA_NBR,
+ "synchronous serial 0 dma tr",
+ DMA_VERBOSE_ON_ERROR,
+ 0,
+ REQ_DMA_SYNCSER)) {
+ free_irq(DMA_OUT_INTR_VECT, &port[0]);
+ free_irq(DMA_IN_INTR_VECT, &port[0]);
printk(KERN_CRIT "Can't allocate sync serial port 0 TX DMA channel");
return -EBUSY;
- } else if (crisv32_request_dma(SYNC_SER0_RX_DMA_NBR,
- "synchronous serial 0 dma rec",
- DMA_VERBOSE_ON_ERROR,
- 0,
- dma_sser0)) {
- crisv32_free_dma(SYNC_SER0_TX_DMA_NBR);
- free_irq(DMA4_INTR_VECT, &port[0]);
- free_irq(DMA5_INTR_VECT, &port[0]);
+ } else if (crisv32_request_dma(IN_DMA_NBR,
+ "synchronous serial 0 dma rec",
+ DMA_VERBOSE_ON_ERROR,
+ 0,
+ REQ_DMA_SYNCSER)) {
+ crisv32_free_dma(OUT_DMA_NBR);
+ free_irq(DMA_OUT_INTR_VECT, &port[0]);
+ free_irq(DMA_IN_INTR_VECT, &port[0]);
printk(KERN_CRIT "Can't allocate sync serial port 1 RX DMA channel");
return -EBUSY;
}
#endif
}
- else if (port == &ports[1]){
+#ifdef CONFIG_ETRAXFS
+ else if (port == &ports[1]) {
#ifdef SYNC_SER_DMA
if (request_irq(DMA6_INTR_VECT,
tr_interrupt,
@@ -417,20 +508,22 @@ static int sync_serial_open(struct inode *inode, struct file *file)
free_irq(DMA6_INTR_VECT, &ports[1]);
printk(KERN_CRIT "Can't allocate sync serial port 3 IRQ");
return -EBUSY;
- } else if (crisv32_request_dma(SYNC_SER1_TX_DMA_NBR,
- "synchronous serial 1 dma tr",
- DMA_VERBOSE_ON_ERROR,
- 0,
- dma_sser1)) {
- free_irq(21, &ports[1]);
- free_irq(20, &ports[1]);
+ } else if (crisv32_request_dma(
+ SYNC_SER1_TX_DMA_NBR,
+ "synchronous serial 1 dma tr",
+ DMA_VERBOSE_ON_ERROR,
+ 0,
+ dma_sser1)) {
+ free_irq(DMA6_INTR_VECT, &ports[1]);
+ free_irq(DMA7_INTR_VECT, &ports[1]);
printk(KERN_CRIT "Can't allocate sync serial port 3 TX DMA channel");
return -EBUSY;
- } else if (crisv32_request_dma(SYNC_SER1_RX_DMA_NBR,
- "synchronous serial 3 dma rec",
- DMA_VERBOSE_ON_ERROR,
- 0,
- dma_sser1)) {
+ } else if (crisv32_request_dma(
+ SYNC_SER1_RX_DMA_NBR,
+ "synchronous serial 3 dma rec",
+ DMA_VERBOSE_ON_ERROR,
+ 0,
+ dma_sser1)) {
crisv32_free_dma(SYNC_SER1_TX_DMA_NBR);
free_irq(DMA6_INTR_VECT, &ports[1]);
free_irq(DMA7_INTR_VECT, &ports[1]);
@@ -439,14 +532,14 @@ static int sync_serial_open(struct inode *inode, struct file *file)
}
#endif
}
-
+#endif
/* Enable DMAs */
REG_WR(dma, port->regi_dmain, rw_cfg, cfg);
REG_WR(dma, port->regi_dmaout, rw_cfg, cfg);
/* Enable DMA IRQs */
REG_WR(dma, port->regi_dmain, rw_intr_mask, intr_mask);
REG_WR(dma, port->regi_dmaout, rw_intr_mask, intr_mask);
- /* Set up wordsize = 2 for DMAs. */
+ /* Set up wordsize = 1 for DMAs. */
DMA_WR_CMD (port->regi_dmain, regk_dma_set_w_size1);
DMA_WR_CMD (port->regi_dmaout, regk_dma_set_w_size1);
@@ -455,7 +548,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
} else { /* !port->use_dma */
#ifdef SYNC_SER_MANUAL
if (port == &ports[0]) {
- if (request_irq(SSER0_INTR_VECT,
+ if (request_irq(SYNCSER_INTR_VECT,
manual_interrupt,
0,
"synchronous serial manual irq",
@@ -463,7 +556,9 @@ static int sync_serial_open(struct inode *inode, struct file *file)
printk("Can't allocate sync serial manual irq");
return -EBUSY;
}
- } else if (port == &ports[1]) {
+ }
+#ifdef CONFIG_ETRAXFS
+ else if (port == &ports[1]) {
if (request_irq(SSER1_INTR_VECT,
manual_interrupt,
0,
@@ -473,11 +568,13 @@ static int sync_serial_open(struct inode *inode, struct file *file)
return -EBUSY;
}
}
+#endif
port->init_irqs = 0;
#else
panic("sync_serial: Manual mode not supported.\n");
#endif /* SYNC_SER_MANUAL */
}
+
} /* port->init_irqs */
port->busy++;
@@ -487,9 +584,9 @@ static int sync_serial_open(struct inode *inode, struct file *file)
static int sync_serial_release(struct inode *inode, struct file *file)
{
int dev = iminor(inode);
- sync_port* port;
+ sync_port *port;
- if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
+ if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled)
{
DEBUG(printk("Invalid minor %d\n", dev));
return -ENODEV;
@@ -506,17 +603,37 @@ static unsigned int sync_serial_poll(struct file *file, poll_table *wait)
{
int dev = iminor(file->f_path.dentry->d_inode);
unsigned int mask = 0;
- sync_port* port;
+ sync_port *port;
DEBUGPOLL( static unsigned int prev_mask = 0; );
port = &ports[dev];
+
+ if (!port->started) {
+ reg_sser_rw_cfg cfg = REG_RD(sser, port->regi_sser, rw_cfg);
+ reg_sser_rw_rec_cfg rec_cfg =
+ REG_RD(sser, port->regi_sser, rw_rec_cfg);
+ cfg.en = regk_sser_yes;
+ rec_cfg.rec_en = port->input;
+ REG_WR(sser, port->regi_sser, rw_cfg, cfg);
+ REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg);
+ port->started = 1;
+ }
+
poll_wait(file, &port->out_wait_q, wait);
poll_wait(file, &port->in_wait_q, wait);
- /* Some room to write */
- if (port->out_count < OUT_BUFFER_SIZE)
+
+ /* No active transfer, descriptors are available */
+ if (port->output && !port->tr_running)
+ mask |= POLLOUT | POLLWRNORM;
+
+ /* Descriptor and buffer space available. */
+ if (port->output &&
+ port->active_tr_descr != port->catch_tr_descr &&
+ port->out_buf_count < OUT_BUFFER_SIZE)
mask |= POLLOUT | POLLWRNORM;
+
/* At least an inbufchunk of data */
- if (sync_data_avail(port) >= port->inbufchunk)
+ if (port->input && sync_data_avail(port) >= port->inbufchunk)
mask |= POLLIN | POLLRDNORM;
DEBUGPOLL(if (mask != prev_mask)
@@ -531,15 +648,16 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int return_val = 0;
+ int dma_w_size = regk_dma_set_w_size1;
int dev = iminor(file->f_path.dentry->d_inode);
- sync_port* port;
+ sync_port *port;
reg_sser_rw_tr_cfg tr_cfg;
reg_sser_rw_rec_cfg rec_cfg;
reg_sser_rw_frm_cfg frm_cfg;
reg_sser_rw_cfg gen_cfg;
reg_sser_rw_intr_mask intr_mask;
- if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
+ if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled)
{
DEBUG(printk("Invalid minor %d\n", dev));
return -1;
@@ -558,61 +676,81 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
case SSP_SPEED:
if (GET_SPEED(arg) == CODEC)
{
+ unsigned int freq;
+
gen_cfg.base_freq = regk_sser_f32;
- /* FREQ = 0 => 4 MHz => clk_div = 7*/
- gen_cfg.clk_div = 6 + (1 << GET_FREQ(arg));
- }
- else
- {
+
+ /* Clock divider will internally be
+ * gen_cfg.clk_div + 1.
+ */
+
+ freq = GET_FREQ(arg);
+ switch (freq) {
+ case FREQ_32kHz:
+ case FREQ_64kHz:
+ case FREQ_128kHz:
+ case FREQ_256kHz:
+ gen_cfg.clk_div = 125 *
+ (1 << (freq - FREQ_256kHz)) - 1;
+ break;
+ case FREQ_512kHz:
+ gen_cfg.clk_div = 62;
+ break;
+ case FREQ_1MHz:
+ case FREQ_2MHz:
+ case FREQ_4MHz:
+ gen_cfg.clk_div = 8 * (1 << freq) - 1;
+ break;
+ }
+ } else {
gen_cfg.base_freq = regk_sser_f29_493;
- switch (GET_SPEED(arg))
- {
- case SSP150:
- gen_cfg.clk_div = 29493000 / (150 * 8) - 1;
- break;
- case SSP300:
- gen_cfg.clk_div = 29493000 / (300 * 8) - 1;
- break;
- case SSP600:
- gen_cfg.clk_div = 29493000 / (600 * 8) - 1;
- break;
- case SSP1200:
- gen_cfg.clk_div = 29493000 / (1200 * 8) - 1;
- break;
- case SSP2400:
- gen_cfg.clk_div = 29493000 / (2400 * 8) - 1;
- break;
- case SSP4800:
- gen_cfg.clk_div = 29493000 / (4800 * 8) - 1;
- break;
- case SSP9600:
- gen_cfg.clk_div = 29493000 / (9600 * 8) - 1;
- break;
- case SSP19200:
- gen_cfg.clk_div = 29493000 / (19200 * 8) - 1;
- break;
- case SSP28800:
- gen_cfg.clk_div = 29493000 / (28800 * 8) - 1;
- break;
- case SSP57600:
- gen_cfg.clk_div = 29493000 / (57600 * 8) - 1;
- break;
- case SSP115200:
- gen_cfg.clk_div = 29493000 / (115200 * 8) - 1;
- break;
- case SSP230400:
- gen_cfg.clk_div = 29493000 / (230400 * 8) - 1;
- break;
- case SSP460800:
- gen_cfg.clk_div = 29493000 / (460800 * 8) - 1;
- break;
- case SSP921600:
- gen_cfg.clk_div = 29493000 / (921600 * 8) - 1;
- break;
- case SSP3125000:
- gen_cfg.base_freq = regk_sser_f100;
- gen_cfg.clk_div = 100000000 / (3125000 * 8) - 1;
- break;
+ switch (GET_SPEED(arg)) {
+ case SSP150:
+ gen_cfg.clk_div = 29493000 / (150 * 8) - 1;
+ break;
+ case SSP300:
+ gen_cfg.clk_div = 29493000 / (300 * 8) - 1;
+ break;
+ case SSP600:
+ gen_cfg.clk_div = 29493000 / (600 * 8) - 1;
+ break;
+ case SSP1200:
+ gen_cfg.clk_div = 29493000 / (1200 * 8) - 1;
+ break;
+ case SSP2400:
+ gen_cfg.clk_div = 29493000 / (2400 * 8) - 1;
+ break;
+ case SSP4800:
+ gen_cfg.clk_div = 29493000 / (4800 * 8) - 1;
+ break;
+ case SSP9600:
+ gen_cfg.clk_div = 29493000 / (9600 * 8) - 1;
+ break;
+ case SSP19200:
+ gen_cfg.clk_div = 29493000 / (19200 * 8) - 1;
+ break;
+ case SSP28800:
+ gen_cfg.clk_div = 29493000 / (28800 * 8) - 1;
+ break;
+ case SSP57600:
+ gen_cfg.clk_div = 29493000 / (57600 * 8) - 1;
+ break;
+ case SSP115200:
+ gen_cfg.clk_div = 29493000 / (115200 * 8) - 1;
+ break;
+ case SSP230400:
+ gen_cfg.clk_div = 29493000 / (230400 * 8) - 1;
+ break;
+ case SSP460800:
+ gen_cfg.clk_div = 29493000 / (460800 * 8) - 1;
+ break;
+ case SSP921600:
+ gen_cfg.clk_div = 29493000 / (921600 * 8) - 1;
+ break;
+ case SSP3125000:
+ gen_cfg.base_freq = regk_sser_f100;
+ gen_cfg.clk_div = 100000000 / (3125000 * 8) - 1;
+ break;
}
}
@@ -625,46 +763,60 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
case MASTER_OUTPUT:
port->output = 1;
port->input = 0;
+ frm_cfg.out_on = regk_sser_tr;
+ frm_cfg.frame_pin_dir = regk_sser_out;
gen_cfg.clk_dir = regk_sser_out;
break;
case SLAVE_OUTPUT:
port->output = 1;
port->input = 0;
+ frm_cfg.frame_pin_dir = regk_sser_in;
gen_cfg.clk_dir = regk_sser_in;
break;
case MASTER_INPUT:
port->output = 0;
port->input = 1;
+ frm_cfg.frame_pin_dir = regk_sser_out;
+ frm_cfg.out_on = regk_sser_intern_tb;
gen_cfg.clk_dir = regk_sser_out;
break;
case SLAVE_INPUT:
port->output = 0;
port->input = 1;
+ frm_cfg.frame_pin_dir = regk_sser_in;
gen_cfg.clk_dir = regk_sser_in;
break;
case MASTER_BIDIR:
port->output = 1;
port->input = 1;
+ frm_cfg.frame_pin_dir = regk_sser_out;
+ frm_cfg.out_on = regk_sser_intern_tb;
gen_cfg.clk_dir = regk_sser_out;
break;
case SLAVE_BIDIR:
port->output = 1;
port->input = 1;
+ frm_cfg.frame_pin_dir = regk_sser_in;
gen_cfg.clk_dir = regk_sser_in;
break;
default:
spin_unlock_irq(&port->lock);
return -EINVAL;
-
}
if (!port->use_dma || (arg == MASTER_OUTPUT || arg == SLAVE_OUTPUT))
intr_mask.rdav = regk_sser_yes;
break;
case SSP_FRAME_SYNC:
- if (arg & NORMAL_SYNC)
+ if (arg & NORMAL_SYNC) {
+ frm_cfg.rec_delay = 1;
frm_cfg.tr_delay = 1;
+ }
else if (arg & EARLY_SYNC)
- frm_cfg.tr_delay = 0;
+ frm_cfg.rec_delay = frm_cfg.tr_delay = 0;
+ else if (arg & SECOND_WORD_SYNC) {
+ frm_cfg.rec_delay = 7;
+ frm_cfg.tr_delay = 1;
+ }
tr_cfg.bulk_wspace = frm_cfg.tr_delay;
frm_cfg.early_wend = regk_sser_yes;
@@ -680,9 +832,11 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
else if (arg & SYNC_OFF)
frm_cfg.frame_pin_use = regk_sser_gio0;
- if (arg & WORD_SIZE_8)
+ dma_w_size = regk_dma_set_w_size2;
+ if (arg & WORD_SIZE_8) {
rec_cfg.sample_size = tr_cfg.sample_size = 7;
- else if (arg & WORD_SIZE_12)
+ dma_w_size = regk_dma_set_w_size1;
+ } else if (arg & WORD_SIZE_12)
rec_cfg.sample_size = tr_cfg.sample_size = 11;
else if (arg & WORD_SIZE_16)
rec_cfg.sample_size = tr_cfg.sample_size = 15;
@@ -696,10 +850,13 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
else if (arg & BIT_ORDER_LSB)
rec_cfg.sh_dir = tr_cfg.sh_dir = regk_sser_lsbfirst;
- if (arg & FLOW_CONTROL_ENABLE)
+ if (arg & FLOW_CONTROL_ENABLE) {
+ frm_cfg.status_pin_use = regk_sser_frm;
rec_cfg.fifo_thr = regk_sser_thr16;
- else if (arg & FLOW_CONTROL_DISABLE)
+ } else if (arg & FLOW_CONTROL_DISABLE) {
+ frm_cfg.status_pin_use = regk_sser_gio0;
rec_cfg.fifo_thr = regk_sser_inf;
+ }
if (arg & CLOCK_NOT_GATED)
gen_cfg.gate_clk = regk_sser_no;
@@ -726,9 +883,9 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
break;
case SSP_OPOLARITY:
if (arg & CLOCK_NORMAL)
- gen_cfg.out_clk_pol = regk_sser_neg;
- else if (arg & CLOCK_INVERT)
gen_cfg.out_clk_pol = regk_sser_pos;
+ else if (arg & CLOCK_INVERT)
+ gen_cfg.out_clk_pol = regk_sser_neg;
if (arg & FRAME_NORMAL)
frm_cfg.level = regk_sser_pos_hi;
@@ -770,10 +927,9 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
}
- if (port->started)
- {
- tr_cfg.tr_en = port->output;
+ if (port->started) {
rec_cfg.rec_en = port->input;
+ gen_cfg.en = (port->output | port->input);
}
REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg);
@@ -782,138 +938,145 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask);
REG_WR(sser, port->regi_sser, rw_cfg, gen_cfg);
+
+ if (cmd == SSP_FRAME_SYNC && (arg & (WORD_SIZE_8 | WORD_SIZE_12 |
+ WORD_SIZE_16 | WORD_SIZE_24 | WORD_SIZE_32))) {
+ int en = gen_cfg.en;
+ gen_cfg.en = 0;
+ REG_WR(sser, port->regi_sser, rw_cfg, gen_cfg);
+ /* ##### Should DMA be stoped before we change dma size? */
+ DMA_WR_CMD(port->regi_dmain, dma_w_size);
+ DMA_WR_CMD(port->regi_dmaout, dma_w_size);
+ gen_cfg.en = en;
+ REG_WR(sser, port->regi_sser, rw_cfg, gen_cfg);
+ }
+
spin_unlock_irq(&port->lock);
return return_val;
}
-static ssize_t sync_serial_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos)
+/* NOTE: sync_serial_write does not support concurrency */
+static ssize_t sync_serial_write(struct file *file, const char *buf,
+ size_t count, loff_t *ppos)
{
int dev = iminor(file->f_path.dentry->d_inode);
DECLARE_WAITQUEUE(wait, current);
- sync_port *port;
- unsigned long c, c1;
- unsigned long free_outp;
- unsigned long outp;
- unsigned long out_buffer;
+ struct sync_port *port;
+ int trunc_count;
unsigned long flags;
+ int bytes_free;
+ int out_buf_count;
- if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
- {
+ unsigned char *rd_ptr; /* First allocated byte in the buffer */
+ unsigned char *wr_ptr; /* First free byte in the buffer */
+ unsigned char *buf_stop_ptr; /* Last byte + 1 */
+
+ if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled) {
DEBUG(printk("Invalid minor %d\n", dev));
return -ENODEV;
}
port = &ports[dev];
- DEBUGWRITE(printk("W d%d c %lu (%d/%d)\n", port->port_nbr, count, port->out_count, OUT_BUFFER_SIZE));
- /* Space to end of buffer */
- /*
- * out_buffer <c1>012345<- c ->OUT_BUFFER_SIZE
- * outp^ +out_count
- ^free_outp
- * out_buffer 45<- c ->0123OUT_BUFFER_SIZE
- * +out_count outp^
- * free_outp
- *
+ /* |<- OUT_BUFFER_SIZE ->|
+ * |<- out_buf_count ->|
+ * |<- trunc_count ->| ...->|
+ * ______________________________________________________
+ * | free | data | free |
+ * |_________|___________________|________________________|
+ * ^ rd_ptr ^ wr_ptr
*/
+ DEBUGWRITE(printk(KERN_DEBUG "W d%d c %lu a: %p c: %p\n",
+ port->port_nbr, count, port->active_tr_descr,
+ port->catch_tr_descr));
/* Read variables that may be updated by interrupts */
spin_lock_irqsave(&port->lock, flags);
- count = count > OUT_BUFFER_SIZE - port->out_count ? OUT_BUFFER_SIZE - port->out_count : count;
- outp = (unsigned long)port->outp;
- free_outp = outp + port->out_count;
+ rd_ptr = port->out_rd_ptr;
+ out_buf_count = port->out_buf_count;
spin_unlock_irqrestore(&port->lock, flags);
- out_buffer = (unsigned long)port->out_buffer;
- /* Find out where and how much to write */
- if (free_outp >= out_buffer + OUT_BUFFER_SIZE)
- free_outp -= OUT_BUFFER_SIZE;
- if (free_outp >= outp)
- c = out_buffer + OUT_BUFFER_SIZE - free_outp;
- else
- c = outp - free_outp;
- if (c > count)
- c = count;
+ /* Check if resources are available */
+ if (port->tr_running &&
+ ((port->use_dma && port->active_tr_descr == port->catch_tr_descr) ||
+ out_buf_count >= OUT_BUFFER_SIZE)) {
+ DEBUGWRITE(printk(KERN_DEBUG "sser%d full\n", dev));
+ return -EAGAIN;
+ }
+
+ buf_stop_ptr = port->out_buffer + OUT_BUFFER_SIZE;
+
+ /* Determine pointer to the first free byte, before copying. */
+ wr_ptr = rd_ptr + out_buf_count;
+ if (wr_ptr >= buf_stop_ptr)
+ wr_ptr -= OUT_BUFFER_SIZE;
-// DEBUGWRITE(printk("w op %08lX fop %08lX c %lu\n", outp, free_outp, c));
- if (copy_from_user((void*)free_outp, buf, c))
+ /* If we wrap the ring buffer, let the user space program handle it by
+ * truncating the data. This could be more elegant, small buffer
+ * fragments may occur.
+ */
+ bytes_free = OUT_BUFFER_SIZE - out_buf_count;
+ if (wr_ptr + bytes_free > buf_stop_ptr)
+ bytes_free = buf_stop_ptr - wr_ptr;
+ trunc_count = (count < bytes_free) ? count : bytes_free;
+
+ if (copy_from_user(wr_ptr, buf, trunc_count))
return -EFAULT;
- if (c != count) {
- buf += c;
- c1 = count - c;
- DEBUGWRITE(printk("w2 fi %lu c %lu c1 %lu\n", free_outp-out_buffer, c, c1));
- if (copy_from_user((void*)out_buffer, buf, c1))
- return -EFAULT;
- }
- spin_lock_irqsave(&port->lock, flags);
- port->out_count += count;
- spin_unlock_irqrestore(&port->lock, flags);
+ DEBUGOUTBUF(printk(KERN_DEBUG "%-4d + %-4d = %-4d %p %p %p\n",
+ out_buf_count, trunc_count,
+ port->out_buf_count, port->out_buffer,
+ wr_ptr, buf_stop_ptr));
/* Make sure transmitter/receiver is running */
- if (!port->started)
- {
+ if (!port->started) {
reg_sser_rw_cfg cfg = REG_RD(sser, port->regi_sser, rw_cfg);
- reg_sser_rw_tr_cfg tr_cfg = REG_RD(sser, port->regi_sser, rw_tr_cfg);
reg_sser_rw_rec_cfg rec_cfg = REG_RD(sser, port->regi_sser, rw_rec_cfg);
cfg.en = regk_sser_yes;
- tr_cfg.tr_en = port->output;
rec_cfg.rec_en = port->input;
REG_WR(sser, port->regi_sser, rw_cfg, cfg);
- REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg);
REG_WR(sser, port->regi_sser, rw_rec_cfg, rec_cfg);
port->started = 1;
}
- if (file->f_flags & O_NONBLOCK) {
- spin_lock_irqsave(&port->lock, flags);
- if (!port->tr_running) {
- if (!port->use_dma) {
- reg_sser_rw_intr_mask intr_mask;
- intr_mask = REG_RD(sser, port->regi_sser, rw_intr_mask);
- /* Start sender by writing data */
- send_word(port);
- /* and enable transmitter ready IRQ */
- intr_mask.trdy = 1;
- REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask);
- } else {
- start_dma(port, (unsigned char* volatile )port->outp, c);
- }
- }
- spin_unlock_irqrestore(&port->lock, flags);
- DEBUGWRITE(printk("w d%d c %lu NB\n",
- port->port_nbr, count));
- return count;
+ /* Setup wait if blocking */
+ if (!(file->f_flags & O_NONBLOCK)) {
+ add_wait_queue(&port->out_wait_q, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
}
- /* Sleep until all sent */
-
- add_wait_queue(&port->out_wait_q, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&port->lock, flags);
- if (!port->tr_running) {
- if (!port->use_dma) {
- reg_sser_rw_intr_mask intr_mask;
- intr_mask = REG_RD(sser, port->regi_sser, rw_intr_mask);
- /* Start sender by writing data */
- send_word(port);
- /* and enable transmitter ready IRQ */
- intr_mask.trdy = 1;
- REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask);
- } else {
- start_dma(port, port->outp, c);
- }
+ port->out_buf_count += trunc_count;
+ if (port->use_dma) {
+ start_dma_out(port, wr_ptr, trunc_count);
+ } else if (!port->tr_running) {
+ reg_sser_rw_intr_mask intr_mask;
+ intr_mask = REG_RD(sser, port->regi_sser, rw_intr_mask);
+ /* Start sender by writing data */
+ send_word(port);
+ /* and enable transmitter ready IRQ */
+ intr_mask.trdy = 1;
+ REG_WR(sser, port->regi_sser, rw_intr_mask, intr_mask);
}
spin_unlock_irqrestore(&port->lock, flags);
+
+ /* Exit if non blocking */
+ if (file->f_flags & O_NONBLOCK) {
+ DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu %08x\n",
+ port->port_nbr, trunc_count,
+ REG_RD_INT(dma, port->regi_dmaout, r_intr)));
+ return trunc_count;
+ }
+
schedule();
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->out_wait_q, &wait);
+
if (signal_pending(current))
- {
return -EINTR;
- }
- DEBUGWRITE(printk("w d%d c %lu\n", port->port_nbr, count));
- return count;
+
+ DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu\n",
+ port->port_nbr, trunc_count));
+ return trunc_count;
}
static ssize_t sync_serial_read(struct file * file, char * buf,
@@ -926,7 +1089,7 @@ static ssize_t sync_serial_read(struct file * file, char * buf,
unsigned char* end;
unsigned long flags;
- if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled)
+ if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled)
{
DEBUG(printk("Invalid minor %d\n", dev));
return -ENODEV;
@@ -949,7 +1112,6 @@ static ssize_t sync_serial_read(struct file * file, char * buf,
port->started = 1;
}
-
/* Calculate number of available bytes */
/* Save pointers to avoid that they are modified by interrupt */
spin_lock_irqsave(&port->lock, flags);
@@ -958,16 +1120,14 @@ static ssize_t sync_serial_read(struct file * file, char * buf,
spin_unlock_irqrestore(&port->lock, flags);
while ((start == end) && !port->full) /* No data */
{
+ DEBUGREAD(printk(KERN_DEBUG "&"));
if (file->f_flags & O_NONBLOCK)
- {
return -EAGAIN;
- }
interruptible_sleep_on(&port->in_wait_q);
if (signal_pending(current))
- {
return -EINTR;
- }
+
spin_lock_irqsave(&port->lock, flags);
start = (unsigned char*)port->readp; /* cast away volatile */
end = (unsigned char*)port->writep; /* cast away volatile */
@@ -1004,83 +1164,105 @@ static void send_word(sync_port* port)
switch(tr_cfg.sample_size)
{
case 8:
- port->out_count--;
- tr_data.data = *port->outp++;
+ port->out_buf_count--;
+ tr_data.data = *port->out_rd_ptr++;
REG_WR(sser, port->regi_sser, rw_tr_data, tr_data);
- if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
- port->outp = port->out_buffer;
+ if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE)
+ port->out_rd_ptr = port->out_buffer;
break;
case 12:
{
- int data = (*port->outp++) << 8;
- data |= *port->outp++;
- port->out_count-=2;
+ int data = (*port->out_rd_ptr++) << 8;
+ data |= *port->out_rd_ptr++;
+ port->out_buf_count -= 2;
tr_data.data = data;
REG_WR(sser, port->regi_sser, rw_tr_data, tr_data);
- if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
- port->outp = port->out_buffer;
+ if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE)
+ port->out_rd_ptr = port->out_buffer;
}
break;
case 16:
- port->out_count-=2;
- tr_data.data = *(unsigned short *)port->outp;
+ port->out_buf_count -= 2;
+ tr_data.data = *(unsigned short *)port->out_rd_ptr;
REG_WR(sser, port->regi_sser, rw_tr_data, tr_data);
- port->outp+=2;
- if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
- port->outp = port->out_buffer;
+ port->out_rd_ptr += 2;
+ if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE)
+ port->out_rd_ptr = port->out_buffer;
break;
case 24:
- port->out_count-=3;
- tr_data.data = *(unsigned short *)port->outp;
+ port->out_buf_count -= 3;
+ tr_data.data = *(unsigned short *)port->out_rd_ptr;
REG_WR(sser, port->regi_sser, rw_tr_data, tr_data);
- port->outp+=2;
- tr_data.data = *port->outp++;
+ port->out_rd_ptr += 2;
+ tr_data.data = *port->out_rd_ptr++;
REG_WR(sser, port->regi_sser, rw_tr_data, tr_data);
- if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
- port->outp = port->out_buffer;
+ if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE)
+ port->out_rd_ptr = port->out_buffer;
break;
case 32:
- port->out_count-=4;
- tr_data.data = *(unsigned short *)port->outp;
+ port->out_buf_count -= 4;
+ tr_data.data = *(unsigned short *)port->out_rd_ptr;
REG_WR(sser, port->regi_sser, rw_tr_data, tr_data);
- port->outp+=2;
- tr_data.data = *(unsigned short *)port->outp;
+ port->out_rd_ptr += 2;
+ tr_data.data = *(unsigned short *)port->out_rd_ptr;
REG_WR(sser, port->regi_sser, rw_tr_data, tr_data);
- port->outp+=2;
- if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
- port->outp = port->out_buffer;
+ port->out_rd_ptr += 2;
+ if (port->out_rd_ptr >= port->out_buffer + OUT_BUFFER_SIZE)
+ port->out_rd_ptr = port->out_buffer;
break;
}
}
-
-static void start_dma(struct sync_port* port, const char* data, int count)
+static void start_dma_out(struct sync_port *port,
+ const char *data, int count)
{
- port->tr_running = 1;
- port->out_descr.buf = (char*)virt_to_phys((char*)data);
- port->out_descr.after = port->out_descr.buf + count;
- port->out_descr.eol = port->out_descr.intr = 1;
+ port->active_tr_descr->buf = (char *) virt_to_phys((char *) data);
+ port->active_tr_descr->after = port->active_tr_descr->buf + count;
+ port->active_tr_descr->intr = 1;
+
+ port->active_tr_descr->eol = 1;
+ port->prev_tr_descr->eol = 0;
+
+ DEBUGTRDMA(printk(KERN_DEBUG "Inserting eolr:%p eol@:%p\n",
+ port->prev_tr_descr, port->active_tr_descr));
+ port->prev_tr_descr = port->active_tr_descr;
+ port->active_tr_descr = phys_to_virt((int) port->active_tr_descr->next);
+
+ if (!port->tr_running) {
+ reg_sser_rw_tr_cfg tr_cfg = REG_RD(sser, port->regi_sser,
+ rw_tr_cfg);
- port->out_context.saved_data = (dma_descr_data*)virt_to_phys(&port->out_descr);
- port->out_context.saved_data_buf = port->out_descr.buf;
+ port->out_context.next = 0;
+ port->out_context.saved_data =
+ (dma_descr_data *)virt_to_phys(port->prev_tr_descr);
+ port->out_context.saved_data_buf = port->prev_tr_descr->buf;
+
+ DMA_START_CONTEXT(port->regi_dmaout,
+ virt_to_phys((char *)&port->out_context));
+
+ tr_cfg.tr_en = regk_sser_yes;
+ REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg);
+ DEBUGTRDMA(printk(KERN_DEBUG "dma s\n"););
+ } else {
+ DMA_CONTINUE_DATA(port->regi_dmaout);
+ DEBUGTRDMA(printk(KERN_DEBUG "dma c\n"););
+ }
- DMA_START_CONTEXT(port->regi_dmaout, virt_to_phys((char*)&port->out_context));
- DEBUGTXINT(printk("dma %08lX c %d\n", (unsigned long)data, count));
+ port->tr_running = 1;
}
-static void start_dma_in(sync_port* port)
+static void start_dma_in(sync_port *port)
{
int i;
- char* buf;
+ char *buf;
port->writep = port->flip;
- if (port->writep > port->flip + port->in_buffer_size)
- {
+ if (port->writep > port->flip + port->in_buffer_size) {
panic("Offset too large in sync serial driver\n");
return;
}
buf = (char*)virt_to_phys(port->in_buffer);
- for (i = 0; i < NUM_IN_DESCR; i++) {
+ for (i = 0; i < NBR_IN_DESCR; i++) {
port->in_descr[i].buf = buf;
port->in_descr[i].after = buf + port->inbufchunk;
port->in_descr[i].intr = 1;
@@ -1092,59 +1274,126 @@ static void start_dma_in(sync_port* port)
port->in_descr[i-1].next = (dma_descr_data*)virt_to_phys(&port->in_descr[0]);
port->in_descr[i-1].eol = regk_sser_yes;
port->next_rx_desc = &port->in_descr[0];
- port->prev_rx_desc = &port->in_descr[NUM_IN_DESCR - 1];
+ port->prev_rx_desc = &port->in_descr[NBR_IN_DESCR - 1];
port->in_context.saved_data = (dma_descr_data*)virt_to_phys(&port->in_descr[0]);
port->in_context.saved_data_buf = port->in_descr[0].buf;
DMA_START_CONTEXT(port->regi_dmain, virt_to_phys(&port->in_context));
}
#ifdef SYNC_SER_DMA
-static irqreturn_t tr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t tr_interrupt(int irq, void *dev_id)
{
reg_dma_r_masked_intr masked;
reg_dma_rw_ack_intr ack_intr = {.data = regk_dma_yes};
+ reg_dma_rw_stat stat;
int i;
- struct dma_descr_data *descr;
- unsigned int sentl;
int found = 0;
+ int stop_sser = 0;
- for (i = 0; i < NUMBER_OF_PORTS; i++)
- {
+ for (i = 0; i < NBR_PORTS; i++) {
sync_port *port = &ports[i];
- if (!port->enabled || !port->use_dma )
+ if (!port->enabled || !port->use_dma)
continue;
+ /* IRQ active for the port? */
masked = REG_RD(dma, port->regi_dmaout, r_masked_intr);
+ if (!masked.data)
+ continue;
- if (masked.data) /* IRQ active for the port? */
- {
- found = 1;
- /* Clear IRQ */
- REG_WR(dma, port->regi_dmaout, rw_ack_intr, ack_intr);
- descr = &port->out_descr;
- sentl = descr->after - descr->buf;
- port->out_count -= sentl;
- port->outp += sentl;
- if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE)
- port->outp = port->out_buffer;
- if (port->out_count) {
- int c;
- c = port->out_buffer + OUT_BUFFER_SIZE - port->outp;
- if (c > port->out_count)
- c = port->out_count;
- DEBUGTXINT(printk("tx_int DMAWRITE %i %i\n", sentl, c));
- start_dma(port, port->outp, c);
- } else {
- DEBUGTXINT(printk("tx_int DMA stop %i\n", sentl));
- port->tr_running = 0;
+ found = 1;
+
+ /* Check if we should stop the DMA transfer */
+ stat = REG_RD(dma, port->regi_dmaout, rw_stat);
+ if (stat.list_state == regk_dma_data_at_eol)
+ stop_sser = 1;
+
+ /* Clear IRQ */
+ REG_WR(dma, port->regi_dmaout, rw_ack_intr, ack_intr);
+
+ if (!stop_sser) {
+ /* The DMA has completed a descriptor, EOL was not
+ * encountered, so step relevant descriptor and
+ * datapointers forward. */
+ int sent;
+ sent = port->catch_tr_descr->after -
+ port->catch_tr_descr->buf;
+ DEBUGTXINT(printk(KERN_DEBUG "%-4d - %-4d = %-4d\t"
+ "in descr %p (ac: %p)\n",
+ port->out_buf_count, sent,
+ port->out_buf_count - sent,
+ port->catch_tr_descr,
+ port->active_tr_descr););
+ port->out_buf_count -= sent;
+ port->catch_tr_descr =
+ phys_to_virt((int) port->catch_tr_descr->next);
+ port->out_rd_ptr =
+ phys_to_virt((int) port->catch_tr_descr->buf);
+ } else {
+ int i, sent;
+ /* EOL handler.
+ * Note that if an EOL was encountered during the irq
+ * locked section of sync_ser_write the DMA will be
+ * restarted and the eol flag will be cleared.
+ * The remaining descriptors will be traversed by
+ * the descriptor interrupts as usual.
+ */
+ i = 0;
+ while (!port->catch_tr_descr->eol) {
+ sent = port->catch_tr_descr->after -
+ port->catch_tr_descr->buf;
+ DEBUGOUTBUF(printk(KERN_DEBUG
+ "traversing descr %p -%d (%d)\n",
+ port->catch_tr_descr,
+ sent,
+ port->out_buf_count));
+ port->out_buf_count -= sent;
+ port->catch_tr_descr = phys_to_virt(
+ (int)port->catch_tr_descr->next);
+ i++;
+ if (i >= NBR_OUT_DESCR) {
+ /* TODO: Reset and recover */
+ panic("sync_serial: missing eol");
+ }
}
- wake_up_interruptible(&port->out_wait_q); /* wake up the waiting process */
+ sent = port->catch_tr_descr->after -
+ port->catch_tr_descr->buf;
+ DEBUGOUTBUF(printk(KERN_DEBUG
+ "eol at descr %p -%d (%d)\n",
+ port->catch_tr_descr,
+ sent,
+ port->out_buf_count));
+
+ port->out_buf_count -= sent;
+
+ /* Update read pointer to first free byte, we
+ * may already be writing data there. */
+ port->out_rd_ptr =
+ phys_to_virt((int) port->catch_tr_descr->after);
+ if (port->out_rd_ptr > port->out_buffer +
+ OUT_BUFFER_SIZE)
+ port->out_rd_ptr = port->out_buffer;
+
+ reg_sser_rw_tr_cfg tr_cfg =
+ REG_RD(sser, port->regi_sser, rw_tr_cfg);
+ DEBUGTXINT(printk(KERN_DEBUG
+ "tr_int DMA stop %d, set catch @ %p\n",
+ port->out_buf_count,
+ port->active_tr_descr));
+ if (port->out_buf_count != 0)
+ printk(KERN_CRIT "sync_ser: buffer not "
+ "empty after eol.\n");
+ port->catch_tr_descr = port->active_tr_descr;
+ port->tr_running = 0;
+ tr_cfg.tr_en = regk_sser_no;
+ REG_WR(sser, port->regi_sser, rw_tr_cfg, tr_cfg);
}
+ /* wake up the waiting process */
+ wake_up_interruptible(&port->out_wait_q);
}
return IRQ_RETVAL(found);
} /* tr_interrupt */
-static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t rx_interrupt(int irq, void *dev_id)
{
reg_dma_r_masked_intr masked;
reg_dma_rw_ack_intr ack_intr = {.data = regk_dma_yes};
@@ -1152,7 +1401,7 @@ static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
int i;
int found = 0;
- for (i = 0; i < NUMBER_OF_PORTS; i++)
+ for (i = 0; i < NBR_PORTS; i++)
{
sync_port *port = &ports[i];
@@ -1166,7 +1415,7 @@ static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
found = 1;
while (REG_RD(dma, port->regi_dmain, rw_data) !=
virt_to_phys(port->next_rx_desc)) {
-
+ DEBUGRXINT(printk(KERN_DEBUG "!"));
if (port->writep + port->inbufchunk > port->flip + port->in_buffer_size) {
int first_size = port->flip + port->in_buffer_size - port->writep;
memcpy((char*)port->writep, phys_to_virt((unsigned)port->next_rx_desc->buf), first_size);
@@ -1185,11 +1434,16 @@ static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
port->full = 1;
}
- port->next_rx_desc->eol = 0;
- port->prev_rx_desc->eol = 1;
- port->prev_rx_desc = phys_to_virt((unsigned)port->next_rx_desc);
+ port->next_rx_desc->eol = 1;
+ port->prev_rx_desc->eol = 0;
+ /* Cache bug workaround */
+ flush_dma_descr(port->prev_rx_desc, 0);
+ port->prev_rx_desc = port->next_rx_desc;
port->next_rx_desc = phys_to_virt((unsigned)port->next_rx_desc->next);
- wake_up_interruptible(&port->in_wait_q); /* wake up the waiting process */
+ /* Cache bug workaround */
+ flush_dma_descr(port->prev_rx_desc, 1);
+ /* wake up the waiting process */
+ wake_up_interruptible(&port->in_wait_q);
DMA_CONTINUE(port->regi_dmain);
REG_WR(dma, port->regi_dmain, rw_ack_intr, ack_intr);
@@ -1201,15 +1455,15 @@ static irqreturn_t rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
#endif /* SYNC_SER_DMA */
#ifdef SYNC_SER_MANUAL
-static irqreturn_t manual_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t manual_interrupt(int irq, void *dev_id)
{
int i;
int found = 0;
reg_sser_r_masked_intr masked;
- for (i = 0; i < NUMBER_OF_PORTS; i++)
+ for (i = 0; i < NBR_PORTS; i++)
{
- sync_port* port = &ports[i];
+ sync_port *port = &ports[i];
if (!port->enabled || port->use_dma)
{
@@ -1263,7 +1517,7 @@ static irqreturn_t manual_interrupt(int irq, void *dev_id, struct pt_regs * regs
if (masked.trdy) /* Transmitter ready? */
{
found = 1;
- if (port->out_count > 0) /* More data to send */
+ if (port->out_buf_count > 0) /* More data to send */
send_word(port);
else /* transmission finished */
{
diff --git a/arch/cris/arch-v32/kernel/Makefile b/arch/cris/arch-v32/kernel/Makefile
index 5d5b613cde8..993d987b007 100644
--- a/arch/cris/arch-v32/kernel/Makefile
+++ b/arch/cris/arch-v32/kernel/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.11 2004/12/17 10:16:13 starvik Exp $
#
# Makefile for the linux kernel.
#
@@ -6,9 +5,9 @@
extra-y := head.o
-obj-y := entry.o traps.o irq.o debugport.o dma.o pinmux.o \
+obj-y := entry.o traps.o irq.o debugport.o \
process.o ptrace.o setup.o signal.o traps.o time.o \
- arbiter.o io.o
+ cache.o cacheflush.o
obj-$(CONFIG_ETRAXFS_SIM) += vcs_hook.o
diff --git a/arch/cris/arch-v32/kernel/arbiter.c b/arch/cris/arch-v32/kernel/arbiter.c
deleted file mode 100644
index 420a5312ed0..00000000000
--- a/arch/cris/arch-v32/kernel/arbiter.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Memory arbiter functions. Allocates bandwidth through the
- * arbiter and sets up arbiter breakpoints.
- *
- * The algorithm first assigns slots to the clients that has specified
- * bandwidth (e.g. ethernet) and then the remaining slots are divided
- * on all the active clients.
- *
- * Copyright (c) 2004, 2005 Axis Communications AB.
- */
-
-#include <asm/arch/hwregs/reg_map.h>
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/marb_defs.h>
-#include <asm/arch/arbiter.h>
-#include <asm/arch/hwregs/intr_vect.h>
-#include <linux/interrupt.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <asm/io.h>
-
-struct crisv32_watch_entry
-{
- unsigned long instance;
- watch_callback* cb;
- unsigned long start;
- unsigned long end;
- int used;
-};
-
-#define NUMBER_OF_BP 4
-#define NBR_OF_CLIENTS 14
-#define NBR_OF_SLOTS 64
-#define SDRAM_BANDWIDTH 100000000 /* Some kind of expected value */
-#define INTMEM_BANDWIDTH 400000000
-#define NBR_OF_REGIONS 2
-
-static struct crisv32_watch_entry watches[NUMBER_OF_BP] =
-{
- {regi_marb_bp0},
- {regi_marb_bp1},
- {regi_marb_bp2},
- {regi_marb_bp3}
-};
-
-static int requested_slots[NBR_OF_REGIONS][NBR_OF_CLIENTS];
-static int active_clients[NBR_OF_REGIONS][NBR_OF_CLIENTS];
-static int max_bandwidth[NBR_OF_REGIONS] = {SDRAM_BANDWIDTH, INTMEM_BANDWIDTH};
-
-DEFINE_SPINLOCK(arbiter_lock);
-
-static irqreturn_t
-crisv32_arbiter_irq(int irq, void* dev_id, struct pt_regs* regs);
-
-static void crisv32_arbiter_config(int region)
-{
- int slot;
- int client;
- int interval = 0;
- int val[NBR_OF_SLOTS];
-
- for (slot = 0; slot < NBR_OF_SLOTS; slot++)
- val[slot] = NBR_OF_CLIENTS + 1;
-
- for (client = 0; client < NBR_OF_CLIENTS; client++)
- {
- int pos;
- if (!requested_slots[region][client])
- continue;
- interval = NBR_OF_SLOTS / requested_slots[region][client];
- pos = 0;
- while (pos < NBR_OF_SLOTS)
- {
- if (val[pos] != NBR_OF_CLIENTS + 1)
- pos++;
- else
- {
- val[pos] = client;
- pos += interval;
- }
- }
- }
-
- client = 0;
- for (slot = 0; slot < NBR_OF_SLOTS; slot++)
- {
- if (val[slot] == NBR_OF_CLIENTS + 1)
- {
- int first = client;
- while(!active_clients[region][client]) {
- client = (client + 1) % NBR_OF_CLIENTS;
- if (client == first)
- break;
- }
- val[slot] = client;
- client = (client + 1) % NBR_OF_CLIENTS;
- }
- if (region == EXT_REGION)
- REG_WR_INT_VECT(marb, regi_marb, rw_ext_slots, slot, val[slot]);
- else if (region == INT_REGION)
- REG_WR_INT_VECT(marb, regi_marb, rw_int_slots, slot, val[slot]);
- }
-}
-
-extern char _stext, _etext;
-
-static void crisv32_arbiter_init(void)
-{
- static int initialized = 0;
-
- if (initialized)
- return;
-
- initialized = 1;
-
- /* CPU caches are active. */
- active_clients[EXT_REGION][10] = active_clients[EXT_REGION][11] = 1;
- crisv32_arbiter_config(EXT_REGION);
- crisv32_arbiter_config(INT_REGION);
-
- if (request_irq(MEMARB_INTR_VECT, crisv32_arbiter_irq, IRQF_DISABLED,
- "arbiter", NULL))
- printk(KERN_ERR "Couldn't allocate arbiter IRQ\n");
-
-#ifndef CONFIG_ETRAX_KGDB
- /* Global watch for writes to kernel text segment. */
- crisv32_arbiter_watch(virt_to_phys(&_stext), &_etext - &_stext,
- arbiter_all_clients, arbiter_all_write, NULL);
-#endif
-}
-
-
-
-int crisv32_arbiter_allocate_bandwidth(int client, int region,
- unsigned long bandwidth)
-{
- int i;
- int total_assigned = 0;
- int total_clients = 0;
- int req;
-
- crisv32_arbiter_init();
-
- for (i = 0; i < NBR_OF_CLIENTS; i++)
- {
- total_assigned += requested_slots[region][i];
- total_clients += active_clients[region][i];
- }
- req = NBR_OF_SLOTS / (max_bandwidth[region] / bandwidth);
-
- if (total_assigned + total_clients + req + 1 > NBR_OF_SLOTS)
- return -ENOMEM;
-
- active_clients[region][client] = 1;
- requested_slots[region][client] = req;
- crisv32_arbiter_config(region);
-
- return 0;
-}
-
-int crisv32_arbiter_watch(unsigned long start, unsigned long size,
- unsigned long clients, unsigned long accesses,
- watch_callback* cb)
-{
- int i;
-
- crisv32_arbiter_init();
-
- if (start > 0x80000000) {
- printk("Arbiter: %lX doesn't look like a physical address", start);
- return -EFAULT;
- }
-
- spin_lock(&arbiter_lock);
-
- for (i = 0; i < NUMBER_OF_BP; i++) {
- if (!watches[i].used) {
- reg_marb_rw_intr_mask intr_mask = REG_RD(marb, regi_marb, rw_intr_mask);
-
- watches[i].used = 1;
- watches[i].start = start;
- watches[i].end = start + size;
- watches[i].cb = cb;
-
- REG_WR_INT(marb_bp, watches[i].instance, rw_first_addr, watches[i].start);
- REG_WR_INT(marb_bp, watches[i].instance, rw_last_addr, watches[i].end);
- REG_WR_INT(marb_bp, watches[i].instance, rw_op, accesses);
- REG_WR_INT(marb_bp, watches[i].instance, rw_clients, clients);
-
- if (i == 0)
- intr_mask.bp0 = regk_marb_yes;
- else if (i == 1)
- intr_mask.bp1 = regk_marb_yes;
- else if (i == 2)
- intr_mask.bp2 = regk_marb_yes;
- else if (i == 3)
- intr_mask.bp3 = regk_marb_yes;
-
- REG_WR(marb, regi_marb, rw_intr_mask, intr_mask);
- spin_unlock(&arbiter_lock);
-
- return i;
- }
- }
- spin_unlock(&arbiter_lock);
- return -ENOMEM;
-}
-
-int crisv32_arbiter_unwatch(int id)
-{
- reg_marb_rw_intr_mask intr_mask = REG_RD(marb, regi_marb, rw_intr_mask);
-
- crisv32_arbiter_init();
-
- spin_lock(&arbiter_lock);
-
- if ((id < 0) || (id >= NUMBER_OF_BP) || (!watches[id].used)) {
- spin_unlock(&arbiter_lock);
- return -EINVAL;
- }
-
- memset(&watches[id], 0, sizeof(struct crisv32_watch_entry));
-
- if (id == 0)
- intr_mask.bp0 = regk_marb_no;
- else if (id == 1)
- intr_mask.bp2 = regk_marb_no;
- else if (id == 2)
- intr_mask.bp2 = regk_marb_no;
- else if (id == 3)
- intr_mask.bp3 = regk_marb_no;
-
- REG_WR(marb, regi_marb, rw_intr_mask, intr_mask);
-
- spin_unlock(&arbiter_lock);
- return 0;
-}
-
-extern void show_registers(struct pt_regs *regs);
-
-static irqreturn_t
-crisv32_arbiter_irq(int irq, void* dev_id, struct pt_regs* regs)
-{
- reg_marb_r_masked_intr masked_intr = REG_RD(marb, regi_marb, r_masked_intr);
- reg_marb_bp_r_brk_clients r_clients;
- reg_marb_bp_r_brk_addr r_addr;
- reg_marb_bp_r_brk_op r_op;
- reg_marb_bp_r_brk_first_client r_first;
- reg_marb_bp_r_brk_size r_size;
- reg_marb_bp_rw_ack ack = {0};
- reg_marb_rw_ack_intr ack_intr = {.bp0=1,.bp1=1,.bp2=1,.bp3=1};
- struct crisv32_watch_entry* watch;
-
- if (masked_intr.bp0) {
- watch = &watches[0];
- ack_intr.bp0 = regk_marb_yes;
- } else if (masked_intr.bp1) {
- watch = &watches[1];
- ack_intr.bp1 = regk_marb_yes;
- } else if (masked_intr.bp2) {
- watch = &watches[2];
- ack_intr.bp2 = regk_marb_yes;
- } else if (masked_intr.bp3) {
- watch = &watches[3];
- ack_intr.bp3 = regk_marb_yes;
- } else {
- return IRQ_NONE;
- }
-
- /* Retrieve all useful information and print it. */
- r_clients = REG_RD(marb_bp, watch->instance, r_brk_clients);
- r_addr = REG_RD(marb_bp, watch->instance, r_brk_addr);
- r_op = REG_RD(marb_bp, watch->instance, r_brk_op);
- r_first = REG_RD(marb_bp, watch->instance, r_brk_first_client);
- r_size = REG_RD(marb_bp, watch->instance, r_brk_size);
-
- printk("Arbiter IRQ\n");
- printk("Clients %X addr %X op %X first %X size %X\n",
- REG_TYPE_CONV(int, reg_marb_bp_r_brk_clients, r_clients),
- REG_TYPE_CONV(int, reg_marb_bp_r_brk_addr, r_addr),
- REG_TYPE_CONV(int, reg_marb_bp_r_brk_op, r_op),
- REG_TYPE_CONV(int, reg_marb_bp_r_brk_first_client, r_first),
- REG_TYPE_CONV(int, reg_marb_bp_r_brk_size, r_size));
-
- REG_WR(marb_bp, watch->instance, rw_ack, ack);
- REG_WR(marb, regi_marb, rw_ack_intr, ack_intr);
-
- printk("IRQ occured at %lX\n", regs->erp);
-
- if (watch->cb)
- watch->cb();
-
-
- return IRQ_HANDLED;
-}
diff --git a/arch/cris/arch-v32/kernel/crisksyms.c b/arch/cris/arch-v32/kernel/crisksyms.c
index e513da71124..77d02c15a7f 100644
--- a/arch/cris/arch-v32/kernel/crisksyms.c
+++ b/arch/cris/arch-v32/kernel/crisksyms.c
@@ -2,7 +2,8 @@
#include <linux/irq.h>
#include <asm/arch/dma.h>
#include <asm/arch/intmem.h>
-#include <asm/arch/pinmux.h>
+#include <asm/arch/mach/pinmux.h>
+#include <asm/arch/io.h>
/* Functions for allocating DMA channels */
EXPORT_SYMBOL(crisv32_request_dma);
@@ -16,7 +17,11 @@ EXPORT_SYMBOL(crisv32_intmem_virt_to_phys);
/* Functions for handling pinmux */
EXPORT_SYMBOL(crisv32_pinmux_alloc);
+EXPORT_SYMBOL(crisv32_pinmux_alloc_fixed);
EXPORT_SYMBOL(crisv32_pinmux_dealloc);
+EXPORT_SYMBOL(crisv32_pinmux_dealloc_fixed);
+EXPORT_SYMBOL(crisv32_io_get_name);
+EXPORT_SYMBOL(crisv32_io_get);
/* Functions masking/unmasking interrupts */
EXPORT_SYMBOL(mask_irq);
diff --git a/arch/cris/arch-v32/kernel/debugport.c b/arch/cris/arch-v32/kernel/debugport.c
index d1272ad9215..15af4c29315 100644
--- a/arch/cris/arch-v32/kernel/debugport.c
+++ b/arch/cris/arch-v32/kernel/debugport.c
@@ -4,17 +4,12 @@
#include <linux/console.h>
#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/tty.h>
#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/arch/hwregs/ser_defs.h>
-#include <asm/arch/hwregs/dma_defs.h>
-#include <asm/arch/pinmux.h>
-
-#include <asm/irq.h>
-#include <asm/arch/hwregs/intr_vect_defs.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/ser_defs.h>
+#include <hwregs/dma_defs.h>
+#include <asm/arch/mach/pinmux.h>
struct dbg_port
{
@@ -59,45 +54,50 @@ struct dbg_port ports[] =
115200,
'N',
8
- }
+ },
+#if CONFIG_ETRAX_SERIAL_PORTS == 5
+ {
+ 4,
+ regi_ser4,
+ 0,
+ 115200,
+ 'N',
+ 8
+ },
+#endif
};
static struct dbg_port *port =
#if defined(CONFIG_ETRAX_DEBUG_PORT0)
-&ports[0];
+ &ports[0];
#elif defined(CONFIG_ETRAX_DEBUG_PORT1)
-&ports[1];
+ &ports[1];
#elif defined(CONFIG_ETRAX_DEBUG_PORT2)
-&ports[2];
+ &ports[2];
#elif defined(CONFIG_ETRAX_DEBUG_PORT3)
-&ports[3];
+ &ports[3];
+#elif defined(CONFIG_ETRAX_DEBUG_PORT4)
+ &ports[4];
#else
-NULL;
+ NULL;
#endif
#ifdef CONFIG_ETRAX_KGDB
static struct dbg_port *kgdb_port =
#if defined(CONFIG_ETRAX_KGDB_PORT0)
-&ports[0];
+ &ports[0];
#elif defined(CONFIG_ETRAX_KGDB_PORT1)
-&ports[1];
+ &ports[1];
#elif defined(CONFIG_ETRAX_KGDB_PORT2)
-&ports[2];
+ &ports[2];
#elif defined(CONFIG_ETRAX_KGDB_PORT3)
-&ports[3];
+ &ports[3];
+#elif defined(CONFIG_ETRAX_KGDB_PORT4)
+ &ports[4];
#else
-NULL;
+ NULL;
#endif
#endif
-#ifdef CONFIG_ETRAXFS_SIM
-extern void print_str( const char *str );
-static char buffer[1024];
-static char msg[] = "Debug: ";
-static int buffer_pos = sizeof(msg) - 1;
-#endif
-
-extern struct tty_driver *serial_driver;
-
static void
start_port(struct dbg_port* p)
{
@@ -114,6 +114,10 @@ start_port(struct dbg_port* p)
crisv32_pinmux_alloc_fixed(pinmux_ser2);
else if (p->nbr == 3)
crisv32_pinmux_alloc_fixed(pinmux_ser3);
+#if CONFIG_ETRAX_SERIAL_PORTS == 5
+ else if (p->nbr == 4)
+ crisv32_pinmux_alloc_fixed(pinmux_ser4);
+#endif
/* Set up serial port registers */
reg_ser_rw_tr_ctrl tr_ctrl = {0};
@@ -156,124 +160,21 @@ start_port(struct dbg_port* p)
REG_WR (ser, p->instance, rw_rec_ctrl, rec_ctrl);
}
-/* No debug */
-#ifdef CONFIG_ETRAX_DEBUG_PORT_NULL
-
-static void
-console_write(struct console *co, const char *buf, unsigned int len)
-{
- return;
-}
-
-/* Target debug */
-#elif !defined(CONFIG_ETRAXFS_SIM)
-
-static void
-console_write_direct(struct console *co, const char *buf, unsigned int len)
-{
- int i;
- reg_ser_r_stat_din stat;
- reg_ser_rw_tr_dma_en tr_dma_en, old;
-
- /* Switch to manual mode */
- tr_dma_en = old = REG_RD (ser, port->instance, rw_tr_dma_en);
- if (tr_dma_en.en == regk_ser_yes) {
- tr_dma_en.en = regk_ser_no;
- REG_WR(ser, port->instance, rw_tr_dma_en, tr_dma_en);
- }
-
- /* Send data */
- for (i = 0; i < len; i++) {
- /* LF -> CRLF */
- if (buf[i] == '\n') {
- do {
- stat = REG_RD (ser, port->instance, r_stat_din);
- } while (!stat.tr_rdy);
- REG_WR_INT (ser, port->instance, rw_dout, '\r');
- }
- /* Wait until transmitter is ready and send.*/
- do {
- stat = REG_RD (ser, port->instance, r_stat_din);
- } while (!stat.tr_rdy);
- REG_WR_INT (ser, port->instance, rw_dout, buf[i]);
- }
-
- /* Restore mode */
- if (tr_dma_en.en != old.en)
- REG_WR(ser, port->instance, rw_tr_dma_en, old);
-}
-
-static void
-console_write(struct console *co, const char *buf, unsigned int len)
-{
- if (!port)
- return;
- console_write_direct(co, buf, len);
-}
-
-
-
-#else
-
-/* VCS debug */
-
-static void
-console_write(struct console *co, const char *buf, unsigned int len)
-{
- char* pos;
- pos = memchr(buf, '\n', len);
- if (pos) {
- int l = ++pos - buf;
- memcpy(buffer + buffer_pos, buf, l);
- memcpy(buffer, msg, sizeof(msg) - 1);
- buffer[buffer_pos + l] = '\0';
- print_str(buffer);
- buffer_pos = sizeof(msg) - 1;
- if (pos - buf != len) {
- memcpy(buffer + buffer_pos, pos, len - l);
- buffer_pos += len - l;
- }
- } else {
- memcpy(buffer + buffer_pos, buf, len);
- buffer_pos += len;
- }
-}
-
-#endif
-
-int raw_printk(const char *fmt, ...)
-{
- static char buf[1024];
- int printed_len;
- va_list args;
- va_start(args, fmt);
- printed_len = vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- console_write(NULL, buf, strlen(buf));
- return printed_len;
-}
-
-void
-stupid_debug(char* buf)
-{
- console_write(NULL, buf, strlen(buf));
-}
-
#ifdef CONFIG_ETRAX_KGDB
/* Use polling to get a single character from the kernel debug port */
int
getDebugChar(void)
{
- reg_ser_rs_status_data stat;
+ reg_ser_rs_stat_din stat;
reg_ser_rw_ack_intr ack_intr = { 0 };
do {
- stat = REG_RD(ser, kgdb_instance, rs_status_data);
- } while (!stat.data_avail);
+ stat = REG_RD(ser, kgdb_port->instance, rs_stat_din);
+ } while (!stat.dav);
/* Ack the data_avail interrupt. */
- ack_intr.data_avail = 1;
- REG_WR(ser, kgdb_instance, rw_ack_intr, ack_intr);
+ ack_intr.dav = 1;
+ REG_WR(ser, kgdb_port->instance, rw_ack_intr, ack_intr);
return stat.data;
}
@@ -282,173 +183,18 @@ getDebugChar(void)
void
putDebugChar(int val)
{
- reg_ser_r_status_data stat;
+ reg_ser_r_stat_din stat;
do {
- stat = REG_RD (ser, kgdb_instance, r_status_data);
- } while (!stat.tr_ready);
- REG_WR (ser, kgdb_instance, rw_data_out, REG_TYPE_CONV(reg_ser_rw_data_out, int, val));
+ stat = REG_RD(ser, kgdb_port->instance, r_stat_din);
+ } while (!stat.tr_rdy);
+ REG_WR_INT(ser, kgdb_port->instance, rw_dout, val);
}
#endif /* CONFIG_ETRAX_KGDB */
-static int __init
-console_setup(struct console *co, char *options)
-{
- char* s;
-
- if (options) {
- port = &ports[co->index];
- port->baudrate = 115200;
- port->parity = 'N';
- port->bits = 8;
- port->baudrate = simple_strtoul(options, NULL, 10);
- s = options;
- while(*s >= '0' && *s <= '9')
- s++;
- if (*s) port->parity = *s++;
- if (*s) port->bits = *s++ - '0';
- port->started = 0;
- start_port(port);
- }
- return 0;
-}
-
-/* This is a dummy serial device that throws away anything written to it.
- * This is used when no debug output is wanted.
- */
-static struct tty_driver dummy_driver;
-
-static int dummy_open(struct tty_struct *tty, struct file * filp)
-{
- return 0;
-}
-
-static void dummy_close(struct tty_struct *tty, struct file * filp)
-{
-}
-
-static int dummy_write(struct tty_struct * tty,
- const unsigned char *buf, int count)
-{
- return count;
-}
-
-static int
-dummy_write_room(struct tty_struct *tty)
-{
- return 8192;
-}
-
-void __init
-init_dummy_console(void)
-{
- memset(&dummy_driver, 0, sizeof(struct tty_driver));
- dummy_driver.driver_name = "serial";
- dummy_driver.name = "ttyS";
- dummy_driver.major = TTY_MAJOR;
- dummy_driver.minor_start = 68;
- dummy_driver.num = 1; /* etrax100 has 4 serial ports */
- dummy_driver.type = TTY_DRIVER_TYPE_SERIAL;
- dummy_driver.subtype = SERIAL_TYPE_NORMAL;
- dummy_driver.init_termios = tty_std_termios;
- dummy_driver.init_termios.c_cflag =
- B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
- dummy_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-
- dummy_driver.open = dummy_open;
- dummy_driver.close = dummy_close;
- dummy_driver.write = dummy_write;
- dummy_driver.write_room = dummy_write_room;
- if (tty_register_driver(&dummy_driver))
- panic("Couldn't register dummy serial driver\n");
-}
-
-static struct tty_driver*
-crisv32_console_device(struct console* co, int *index)
-{
- if (port)
- *index = port->nbr;
- return port ? serial_driver : &dummy_driver;
-}
-
-static struct console sercons = {
- name : "ttyS",
- write: console_write,
- read : NULL,
- device : crisv32_console_device,
- unblank : NULL,
- setup : console_setup,
- flags : CON_PRINTBUFFER,
- index : -1,
- cflag : 0,
- next : NULL
-};
-static struct console sercons0 = {
- name : "ttyS",
- write: console_write,
- read : NULL,
- device : crisv32_console_device,
- unblank : NULL,
- setup : console_setup,
- flags : CON_PRINTBUFFER,
- index : 0,
- cflag : 0,
- next : NULL
-};
-
-static struct console sercons1 = {
- name : "ttyS",
- write: console_write,
- read : NULL,
- device : crisv32_console_device,
- unblank : NULL,
- setup : console_setup,
- flags : CON_PRINTBUFFER,
- index : 1,
- cflag : 0,
- next : NULL
-};
-static struct console sercons2 = {
- name : "ttyS",
- write: console_write,
- read : NULL,
- device : crisv32_console_device,
- unblank : NULL,
- setup : console_setup,
- flags : CON_PRINTBUFFER,
- index : 2,
- cflag : 0,
- next : NULL
-};
-static struct console sercons3 = {
- name : "ttyS",
- write: console_write,
- read : NULL,
- device : crisv32_console_device,
- unblank : NULL,
- setup : console_setup,
- flags : CON_PRINTBUFFER,
- index : 3,
- cflag : 0,
- next : NULL
-};
-
/* Register console for printk's, etc. */
int __init
init_etrax_debug(void)
{
- static int first = 1;
-
- if (!first) {
- unregister_console(&sercons);
- register_console(&sercons0);
- register_console(&sercons1);
- register_console(&sercons2);
- register_console(&sercons3);
- init_dummy_console();
- return 0;
- }
- first = 0;
- register_console(&sercons);
start_port(port);
#ifdef CONFIG_ETRAX_KGDB
@@ -456,5 +202,3 @@ init_etrax_debug(void)
#endif /* CONFIG_ETRAX_KGDB */
return 0;
}
-
-__initcall(init_etrax_debug);
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S
index f9d27807b91..eebbaba4543 100644
--- a/arch/cris/arch-v32/kernel/entry.S
+++ b/arch/cris/arch-v32/kernel/entry.S
@@ -10,7 +10,7 @@
* after a timer-interrupt and after each system call.
*
* Stack layout in 'ret_from_system_call':
- * ptrace needs to have all regs on the stack.
+ * ptrace needs to have all regs on the stack.
* if the order here is changed, it needs to be
* updated in fork.c:copy_process, signal.c:do_signal,
* ptrace.c and ptrace.h
@@ -281,12 +281,10 @@ _work_notifysig:
;; Deal with pending signals and notify-resume requests.
addoq +TI_flags, $r0, $acr
- move.d [$acr], $r13 ; The thread_info_flags parameter.
- move.d $r9, $r10 ; do_notify_resume syscall/irq param.
- moveq 0, $r11 ; oldset param - 0 in this case.
- move.d $sp, $r12 ; The regs param.
+ move.d [$acr], $r12 ; The thread_info_flags parameter.
+ move.d $sp, $r11 ; The regs param.
jsr do_notify_resume
- nop
+ move.d $r9, $r10 ; do_notify_resume syscall/irq param.
ba _Rexit
nop
@@ -396,7 +394,7 @@ nmi_interrupt:
btstq REG_BIT(intr_vect, r_nmi, watchdog), $r0
bpl 1f
nop
- jsr handle_watchdog_bite ; In time.c.
+ jsr handle_watchdog_bite ; In time.c.
move.d $sp, $r10 ; Pointer to registers
1: btstq REG_BIT(intr_vect, r_nmi, ext), $r0
bpl 1f
@@ -515,6 +513,13 @@ _ugdb_handle_exception:
ba do_sigtrap ; SIGTRAP the offending process.
move.d [$sp+], $r0 ; Restore R0 in delay slot.
+ .global kernel_execve
+kernel_execve:
+ move.d __NR_execve, $r9
+ break 13
+ ret
+ nop
+
.data
.section .rodata,"a"
@@ -778,21 +783,21 @@ sys_call_table:
.long sys_epoll_ctl /* 255 */
.long sys_epoll_wait
.long sys_remap_file_pages
- .long sys_set_tid_address
- .long sys_timer_create
- .long sys_timer_settime /* 260 */
- .long sys_timer_gettime
- .long sys_timer_getoverrun
- .long sys_timer_delete
- .long sys_clock_settime
- .long sys_clock_gettime /* 265 */
- .long sys_clock_getres
- .long sys_clock_nanosleep
+ .long sys_set_tid_address
+ .long sys_timer_create
+ .long sys_timer_settime /* 260 */
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun
+ .long sys_timer_delete
+ .long sys_clock_settime
+ .long sys_clock_gettime /* 265 */
+ .long sys_clock_getres
+ .long sys_clock_nanosleep
.long sys_statfs64
.long sys_fstatfs64
.long sys_tgkill /* 270 */
.long sys_utimes
- .long sys_fadvise64_64
+ .long sys_fadvise64_64
.long sys_ni_syscall /* sys_vserver */
.long sys_ni_syscall /* sys_mbind */
.long sys_ni_syscall /* 275 sys_get_mempolicy */
@@ -805,6 +810,48 @@ sys_call_table:
.long sys_mq_getsetattr
.long sys_ni_syscall /* reserved for kexec */
.long sys_waitid
+ .long sys_ni_syscall /* 285 */ /* available */
+ .long sys_add_key
+ .long sys_request_key
+ .long sys_keyctl
+ .long sys_ioprio_set
+ .long sys_ioprio_get /* 290 */
+ .long sys_inotify_init
+ .long sys_inotify_add_watch
+ .long sys_inotify_rm_watch
+ .long sys_migrate_pages
+ .long sys_openat /* 295 */
+ .long sys_mkdirat
+ .long sys_mknodat
+ .long sys_fchownat
+ .long sys_futimesat
+ .long sys_fstatat64 /* 300 */
+ .long sys_unlinkat
+ .long sys_renameat
+ .long sys_linkat
+ .long sys_symlinkat
+ .long sys_readlinkat /* 305 */
+ .long sys_fchmodat
+ .long sys_faccessat
+ .long sys_pselect6
+ .long sys_ppoll
+ .long sys_unshare /* 310 */
+ .long sys_set_robust_list
+ .long sys_get_robust_list
+ .long sys_splice
+ .long sys_sync_file_range
+ .long sys_tee /* 315 */
+ .long sys_vmsplice
+ .long sys_move_pages
+ .long sys_getcpu
+ .long sys_epoll_pwait
+ .long sys_utimensat /* 320 */
+ .long sys_signalfd
+ .long sys_timerfd_create
+ .long sys_eventfd
+ .long sys_fallocate
+ .long sys_timerfd_settime /* 325 */
+ .long sys_timerfd_gettime
/*
* NOTE!! This doesn't have to be exact - we just have
diff --git a/arch/cris/arch-v32/kernel/fasttimer.c b/arch/cris/arch-v32/kernel/fasttimer.c
index b40551f9f40..2de9d5849ef 100644
--- a/arch/cris/arch-v32/kernel/fasttimer.c
+++ b/arch/cris/arch-v32/kernel/fasttimer.c
@@ -1,110 +1,9 @@
-/* $Id: fasttimer.c,v 1.11 2005/01/04 11:15:46 starvik Exp $
+/*
* linux/arch/cris/kernel/fasttimer.c
*
* Fast timers for ETRAX FS
- * This may be useful in other OS than Linux so use 2 space indentation...
- *
- * $Log: fasttimer.c,v $
- * Revision 1.11 2005/01/04 11:15:46 starvik
- * Don't share timer IRQ.
- *
- * Revision 1.10 2004/12/07 09:19:38 starvik
- * Corrected includes.
- * Use correct interrupt macros.
- *
- * Revision 1.9 2004/05/14 10:18:58 starvik
- * Export fast_timer_list
- *
- * Revision 1.8 2004/05/14 07:58:03 starvik
- * Merge of changes from 2.4
- *
- * Revision 1.7 2003/07/10 12:06:14 starvik
- * Return IRQ_NONE if irq wasn't handled
- *
- * Revision 1.6 2003/07/04 08:27:49 starvik
- * Merge of Linux 2.5.74
- *
- * Revision 1.5 2003/06/05 10:16:22 johana
- * New INTR_VECT macros.
- *
- * Revision 1.4 2003/06/03 08:49:45 johana
- * Fixed typo.
- *
- * Revision 1.3 2003/06/02 12:51:27 johana
- * Now compiles.
- * Commented some include files that probably can be removed.
- *
- * Revision 1.2 2003/06/02 12:09:41 johana
- * Ported to ETRAX FS using the trig interrupt instead of timer1.
- *
- * Revision 1.3 2002/12/12 08:26:32 starvik
- * Don't use C-comments inside CVS comments
- *
- * Revision 1.2 2002/12/11 15:42:02 starvik
- * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/
- *
- * Revision 1.1 2002/11/18 07:58:06 starvik
- * Fast timers (from Linux 2.4)
- *
- * Revision 1.5 2002/10/15 06:21:39 starvik
- * Added call to init_waitqueue_head
*
- * Revision 1.4 2002/05/28 17:47:59 johana
- * Added del_fast_timer()
- *
- * Revision 1.3 2002/05/28 16:16:07 johana
- * Handle empty fast_timer_list
- *
- * Revision 1.2 2002/05/27 15:38:42 johana
- * Made it compile without warnings on Linux 2.4.
- * (includes, wait_queue, PROC_FS and snprintf)
- *
- * Revision 1.1 2002/05/27 15:32:25 johana
- * arch/etrax100/kernel/fasttimer.c v1.8 from the elinux tree.
- *
- * Revision 1.8 2001/11/27 13:50:40 pkj
- * Disable interrupts while stopping the timer and while modifying the
- * list of active timers in timer1_handler() as it may be interrupted
- * by other interrupts (e.g., the serial interrupt) which may add fast
- * timers.
- *
- * Revision 1.7 2001/11/22 11:50:32 pkj
- * * Only store information about the last 16 timers.
- * * proc_fasttimer_read() now uses an allocated buffer, since it
- * requires more space than just a page even for only writing the
- * last 16 timers. The buffer is only allocated on request, so
- * unless /proc/fasttimer is read, it is never allocated.
- * * Renamed fast_timer_started to fast_timers_started to match
- * fast_timers_added and fast_timers_expired.
- * * Some clean-up.
- *
- * Revision 1.6 2000/12/13 14:02:08 johana
- * Removed volatile for fast_timer_list
- *
- * Revision 1.5 2000/12/13 13:55:35 johana
- * Added DEBUG_LOG, added som cli() and cleanup
- *
- * Revision 1.4 2000/12/05 13:48:50 johana
- * Added range check when writing proc file, modified timer int handling
- *
- * Revision 1.3 2000/11/23 10:10:20 johana
- * More debug/logging possibilities.
- * Moved GET_JIFFIES_USEC() to timex.h and time.c
- *
- * Revision 1.2 2000/11/01 13:41:04 johana
- * Clean up and bugfixes.
- * Created new do_gettimeofday_fast() that gets a timeval struct
- * with time based on jiffies and *R_TIMER0_DATA, uses a table
- * for fast conversion of timer value to microseconds.
- * (Much faster the standard do_gettimeofday() and we don't really
- * want to use the true time - we want the "uptime" so timers don't screw up
- * when we change the time.
- * TODO: Add efficient support for continuous timers as well.
- *
- * Revision 1.1 2000/10/26 15:49:16 johana
- * Added fasttimer, highresolution timers.
- *
- * Copyright (C) 2000,2001 2002, 2003 Axis Communications AB, Lund, Sweden
+ * Copyright (C) 2000-2006 Axis Communications AB, Lund, Sweden
*/
#include <linux/errno.h>
@@ -122,9 +21,9 @@
#include <linux/version.h>
-#include <asm/arch/hwregs/reg_map.h>
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/timer_defs.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/timer_defs.h>
#include <asm/fasttimer.h>
#include <linux/proc_fs.h>
@@ -140,30 +39,25 @@
#define DEBUG_LOG_INCLUDED
#define FAST_TIMER_LOG
-//#define FAST_TIMER_TEST
+/* #define FAST_TIMER_TEST */
#define FAST_TIMER_SANITY_CHECKS
#ifdef FAST_TIMER_SANITY_CHECKS
-#define SANITYCHECK(x) x
-static int sanity_failed = 0;
-#else
-#define SANITYCHECK(x)
+static int sanity_failed;
#endif
#define D1(x)
#define D2(x)
#define DP(x)
-#define __INLINE__ inline
-
-static int fast_timer_running = 0;
-static int fast_timers_added = 0;
-static int fast_timers_started = 0;
-static int fast_timers_expired = 0;
-static int fast_timers_deleted = 0;
-static int fast_timer_is_init = 0;
-static int fast_timer_ints = 0;
+static unsigned int fast_timer_running;
+static unsigned int fast_timers_added;
+static unsigned int fast_timers_started;
+static unsigned int fast_timers_expired;
+static unsigned int fast_timers_deleted;
+static unsigned int fast_timer_is_init;
+static unsigned int fast_timer_ints;
struct fast_timer *fast_timer_list = NULL;
@@ -171,8 +65,8 @@ struct fast_timer *fast_timer_list = NULL;
#define DEBUG_LOG_MAX 128
static const char * debug_log_string[DEBUG_LOG_MAX];
static unsigned long debug_log_value[DEBUG_LOG_MAX];
-static int debug_log_cnt = 0;
-static int debug_log_cnt_wrapped = 0;
+static unsigned int debug_log_cnt;
+static unsigned int debug_log_cnt_wrapped;
#define DEBUG_LOG(string, value) \
{ \
@@ -202,103 +96,92 @@ struct fast_timer timer_expired_log[NUM_TIMER_STATS];
int timer_div_settings[NUM_TIMER_STATS];
int timer_delay_settings[NUM_TIMER_STATS];
+struct work_struct fast_work;
static void
-timer_trig_handler(void);
+timer_trig_handler(struct work_struct *work);
/* Not true gettimeofday, only checks the jiffies (uptime) + useconds */
-void __INLINE__ do_gettimeofday_fast(struct timeval *tv)
+inline void do_gettimeofday_fast(struct fasttime_t *tv)
{
- unsigned long sec = jiffies;
- unsigned long usec = GET_JIFFIES_USEC();
-
- usec += (sec % HZ) * (1000000 / HZ);
- sec = sec / HZ;
-
- if (usec > 1000000)
- {
- usec -= 1000000;
- sec++;
- }
- tv->tv_sec = sec;
- tv->tv_usec = usec;
+ tv->tv_jiff = jiffies;
+ tv->tv_usec = GET_JIFFIES_USEC();
}
-int __INLINE__ timeval_cmp(struct timeval *t0, struct timeval *t1)
+inline int fasttime_cmp(struct fasttime_t *t0, struct fasttime_t *t1)
{
- if (t0->tv_sec < t1->tv_sec)
- {
- return -1;
- }
- else if (t0->tv_sec > t1->tv_sec)
- {
- return 1;
- }
- if (t0->tv_usec < t1->tv_usec)
- {
- return -1;
- }
- else if (t0->tv_usec > t1->tv_usec)
- {
- return 1;
- }
- return 0;
+ /* Compare jiffies. Takes care of wrapping */
+ if (time_before(t0->tv_jiff, t1->tv_jiff))
+ return -1;
+ else if (time_after(t0->tv_jiff, t1->tv_jiff))
+ return 1;
+
+ /* Compare us */
+ if (t0->tv_usec < t1->tv_usec)
+ return -1;
+ else if (t0->tv_usec > t1->tv_usec)
+ return 1;
+ return 0;
}
/* Called with ints off */
-void __INLINE__ start_timer_trig(unsigned long delay_us)
+inline void start_timer_trig(unsigned long delay_us)
{
reg_timer_rw_ack_intr ack_intr = { 0 };
reg_timer_rw_intr_mask intr_mask;
reg_timer_rw_trig trig;
reg_timer_rw_trig_cfg trig_cfg = { 0 };
- reg_timer_r_time r_time;
+ reg_timer_r_time r_time0;
+ reg_timer_r_time r_time1;
+ unsigned char trig_wrap;
+ unsigned char time_wrap;
- r_time = REG_RD(timer, regi_timer, r_time);
+ r_time0 = REG_RD(timer, regi_timer0, r_time);
D1(printk("start_timer_trig : %d us freq: %i div: %i\n",
delay_us, freq_index, div));
/* Clear trig irq */
- intr_mask = REG_RD(timer, regi_timer, rw_intr_mask);
+ intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask);
intr_mask.trig = 0;
- REG_WR(timer, regi_timer, rw_intr_mask, intr_mask);
+ REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask);
- /* Set timer values */
- /* r_time is 100MHz (10 ns resolution) */
- trig = r_time + delay_us*(1000/10);
+ /* Set timer values and check if trigger wraps. */
+ /* r_time is 100MHz (10 ns resolution) */
+ trig_wrap = (trig = r_time0 + delay_us*(1000/10)) < r_time0;
timer_div_settings[fast_timers_started % NUM_TIMER_STATS] = trig;
timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us;
/* Ack interrupt */
ack_intr.trig = 1;
- REG_WR(timer, regi_timer, rw_ack_intr, ack_intr);
+ REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr);
/* Start timer */
- REG_WR(timer, regi_timer, rw_trig, trig);
+ REG_WR(timer, regi_timer0, rw_trig, trig);
trig_cfg.tmr = regk_timer_time;
- REG_WR(timer, regi_timer, rw_trig_cfg, trig_cfg);
+ REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg);
/* Check if we have already passed the trig time */
- r_time = REG_RD(timer, regi_timer, r_time);
- if (r_time < trig) {
+ r_time1 = REG_RD(timer, regi_timer0, r_time);
+ time_wrap = r_time1 < r_time0;
+
+ if ((trig_wrap && !time_wrap) || (r_time1 < trig)) {
/* No, Enable trig irq */
- intr_mask = REG_RD(timer, regi_timer, rw_intr_mask);
+ intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask);
intr_mask.trig = 1;
- REG_WR(timer, regi_timer, rw_intr_mask, intr_mask);
+ REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask);
fast_timers_started++;
fast_timer_running = 1;
- }
- else
- {
+ } else {
/* We have passed the time, disable trig point, ack intr */
trig_cfg.tmr = regk_timer_off;
- REG_WR(timer, regi_timer, rw_trig_cfg, trig_cfg);
- REG_WR(timer, regi_timer, rw_ack_intr, ack_intr);
- /* call the int routine directly */
- timer_trig_handler();
+ REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg);
+ REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr);
+ /* call the int routine */
+ INIT_WORK(&fast_work, timer_trig_handler);
+ schedule_work(&fast_work);
}
}
@@ -320,22 +203,20 @@ void start_one_shot_timer(struct fast_timer *t,
do_gettimeofday_fast(&t->tv_set);
tmp = fast_timer_list;
- SANITYCHECK({ /* Check so this is not in the list already... */
- while (tmp != NULL)
- {
- if (tmp == t)
- {
- printk("timer name: %s data: 0x%08lX already in list!\n", name, data);
- sanity_failed++;
- return;
- }
- else
- {
- tmp = tmp->next;
- }
- }
- tmp = fast_timer_list;
- });
+#ifdef FAST_TIMER_SANITY_CHECKS
+ /* Check so this is not in the list already... */
+ while (tmp != NULL) {
+ if (tmp == t) {
+ printk(KERN_DEBUG
+ "timer name: %s data: 0x%08lX already "
+ "in list!\n", name, data);
+ sanity_failed++;
+ goto done;
+ } else
+ tmp = tmp->next;
+ }
+ tmp = fast_timer_list;
+#endif
t->delay_us = delay_us;
t->function = function;
@@ -343,11 +224,10 @@ void start_one_shot_timer(struct fast_timer *t,
t->name = name;
t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000;
- t->tv_expires.tv_sec = t->tv_set.tv_sec + delay_us / 1000000;
- if (t->tv_expires.tv_usec > 1000000)
- {
+ t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ;
+ if (t->tv_expires.tv_usec > 1000000) {
t->tv_expires.tv_usec -= 1000000;
- t->tv_expires.tv_sec++;
+ t->tv_expires.tv_jiff += HZ;
}
#ifdef FAST_TIMER_LOG
timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t;
@@ -355,15 +235,12 @@ void start_one_shot_timer(struct fast_timer *t,
fast_timers_added++;
/* Check if this should timeout before anything else */
- if (tmp == NULL || timeval_cmp(&t->tv_expires, &tmp->tv_expires) < 0)
- {
+ if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0) {
/* Put first in list and modify the timer value */
t->prev = NULL;
t->next = fast_timer_list;
if (fast_timer_list)
- {
fast_timer_list->prev = t;
- }
fast_timer_list = t;
#ifdef FAST_TIMER_LOG
timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
@@ -372,10 +249,8 @@ void start_one_shot_timer(struct fast_timer *t,
} else {
/* Put in correct place in list */
while (tmp->next &&
- timeval_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0)
- {
+ fasttime_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0)
tmp = tmp->next;
- }
/* Insert t after tmp */
t->prev = tmp;
t->next = tmp->next;
@@ -388,6 +263,7 @@ void start_one_shot_timer(struct fast_timer *t,
D2(printk("start_one_shot_timer: %d us done\n", delay_us));
+done:
local_irq_restore(flags);
} /* start_one_shot_timer */
@@ -431,19 +307,18 @@ int del_fast_timer(struct fast_timer * t)
/* Timer interrupt handler for trig interrupts */
static irqreturn_t
-timer_trig_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+timer_trig_interrupt(int irq, void *dev_id)
{
reg_timer_r_masked_intr masked_intr;
-
/* Check if the timer interrupt is for us (a trig int) */
- masked_intr = REG_RD(timer, regi_timer, r_masked_intr);
+ masked_intr = REG_RD(timer, regi_timer0, r_masked_intr);
if (!masked_intr.trig)
return IRQ_NONE;
- timer_trig_handler();
+ timer_trig_handler(NULL);
return IRQ_HANDLED;
}
-static void timer_trig_handler(void)
+static void timer_trig_handler(struct work_struct *work)
{
reg_timer_rw_ack_intr ack_intr = { 0 };
reg_timer_rw_intr_mask intr_mask;
@@ -451,38 +326,45 @@ static void timer_trig_handler(void)
struct fast_timer *t;
unsigned long flags;
+ /* We keep interrupts disabled not only when we modify the
+ * fast timer list, but any time we hold a reference to a
+ * timer in the list, since del_fast_timer may be called
+ * from (another) interrupt context. Thus, the only time
+ * when interrupts are enabled is when calling the timer
+ * callback function.
+ */
local_irq_save(flags);
/* Clear timer trig interrupt */
- intr_mask = REG_RD(timer, regi_timer, rw_intr_mask);
+ intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask);
intr_mask.trig = 0;
- REG_WR(timer, regi_timer, rw_intr_mask, intr_mask);
+ REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask);
/* First stop timer, then ack interrupt */
/* Stop timer */
trig_cfg.tmr = regk_timer_off;
- REG_WR(timer, regi_timer, rw_trig_cfg, trig_cfg);
+ REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg);
/* Ack interrupt */
ack_intr.trig = 1;
- REG_WR(timer, regi_timer, rw_ack_intr, ack_intr);
+ REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr);
fast_timer_running = 0;
fast_timer_ints++;
- local_irq_restore(flags);
+ fast_timer_function_type *f;
+ unsigned long d;
t = fast_timer_list;
- while (t)
- {
- struct timeval tv;
+ while (t) {
+ struct fasttime_t tv;
/* Has it really expired? */
do_gettimeofday_fast(&tv);
- D1(printk("t: %is %06ius\n", tv.tv_sec, tv.tv_usec));
+ D1(printk(KERN_DEBUG
+ "t: %is %06ius\n", tv.tv_jiff, tv.tv_usec));
- if (timeval_cmp(&t->tv_expires, &tv) <= 0)
- {
+ if (fasttime_cmp(&t->tv_expires, &tv) <= 0) {
/* Yes it has expired */
#ifdef FAST_TIMER_LOG
timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
@@ -490,84 +372,77 @@ static void timer_trig_handler(void)
fast_timers_expired++;
/* Remove this timer before call, since it may reuse the timer */
- local_irq_save(flags);
if (t->prev)
- {
t->prev->next = t->next;
- }
else
- {
fast_timer_list = t->next;
- }
if (t->next)
- {
t->next->prev = t->prev;
- }
t->prev = NULL;
t->next = NULL;
- local_irq_restore(flags);
- if (t->function != NULL)
- {
- t->function(t->data);
- }
- else
- {
+ /* Save function callback data before enabling
+ * interrupts, since the timer may be removed and we
+ * don't know how it was allocated (e.g. ->function
+ * and ->data may become overwritten after deletion
+ * if the timer was stack-allocated).
+ */
+ f = t->function;
+ d = t->data;
+
+ if (f != NULL) {
+ /* Run the callback function with interrupts
+ * enabled. */
+ local_irq_restore(flags);
+ f(d);
+ local_irq_save(flags);
+ } else
DEBUG_LOG("!trimertrig %i function==NULL!\n", fast_timer_ints);
- }
- }
- else
- {
+ } else {
/* Timer is to early, let's set it again using the normal routines */
D1(printk(".\n"));
}
- local_irq_save(flags);
- if ((t = fast_timer_list) != NULL)
- {
+ t = fast_timer_list;
+ if (t != NULL) {
/* Start next timer.. */
- long us;
- struct timeval tv;
+ long us = 0;
+ struct fasttime_t tv;
do_gettimeofday_fast(&tv);
- us = ((t->tv_expires.tv_sec - tv.tv_sec) * 1000000 +
- t->tv_expires.tv_usec - tv.tv_usec);
- if (us > 0)
- {
- if (!fast_timer_running)
- {
+
+ /* time_after_eq takes care of wrapping */
+ if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
+ us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
+ 1000000 / HZ + t->tv_expires.tv_usec -
+ tv.tv_usec);
+
+ if (us > 0) {
+ if (!fast_timer_running) {
#ifdef FAST_TIMER_LOG
timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
#endif
start_timer_trig(us);
}
- local_irq_restore(flags);
break;
- }
- else
- {
+ } else {
/* Timer already expired, let's handle it better late than never.
* The normal loop handles it
*/
D1(printk("e! %d\n", us));
}
}
- local_irq_restore(flags);
}
- if (!t)
- {
+ local_irq_restore(flags);
+
+ if (!t)
D1(printk("ttrig stop!\n"));
- }
}
static void wake_up_func(unsigned long data)
{
-#ifdef DECLARE_WAITQUEUE
wait_queue_head_t *sleep_wait_p = (wait_queue_head_t*)data;
-#else
- struct wait_queue **sleep_wait_p = (struct wait_queue **)data;
-#endif
wake_up(sleep_wait_p);
}
@@ -577,28 +452,17 @@ static void wake_up_func(unsigned long data)
void schedule_usleep(unsigned long us)
{
struct fast_timer t;
-#ifdef DECLARE_WAITQUEUE
wait_queue_head_t sleep_wait;
init_waitqueue_head(&sleep_wait);
- {
- DECLARE_WAITQUEUE(wait, current);
-#else
- struct wait_queue *sleep_wait = NULL;
- struct wait_queue wait = { current, NULL };
-#endif
D1(printk("schedule_usleep(%d)\n", us));
- add_wait_queue(&sleep_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us,
"usleep");
- schedule();
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&sleep_wait, &wait);
+ /* Uninterruptible sleep on the fast timer. (The condition is
+ * somewhat redundant since the timer is what wakes us up.) */
+ wait_event(sleep_wait, !fast_timer_pending(&t));
+
D1(printk("done schedule_usleep(%d)\n", us));
-#ifdef DECLARE_WAITQUEUE
- }
-#endif
}
#ifdef CONFIG_PROC_FS
@@ -618,20 +482,22 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
unsigned long flags;
int i = 0;
int num_to_show;
- struct timeval tv;
+ struct fasttime_t tv;
struct fast_timer *t, *nextt;
static char *bigbuf = NULL;
static unsigned long used;
- if (!bigbuf && !(bigbuf = vmalloc(BIG_BUF_SIZE)))
- {
- used = 0;
- bigbuf[0] = '\0';
- return 0;
- }
-
- if (!offset || !used)
- {
+ if (!bigbuf) {
+ bigbuf = vmalloc(BIG_BUF_SIZE);
+ if (!bigbuf) {
+ used = 0;
+ if (buf)
+ buf[0] = '\0';
+ return 0;
+ }
+ }
+
+ if (!offset || !used) {
do_gettimeofday_fast(&tv);
used = 0;
@@ -648,7 +514,7 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
used += sprintf(bigbuf + used, "Fast timer running: %s\n",
fast_timer_running ? "yes" : "no");
used += sprintf(bigbuf + used, "Current time: %lu.%06lu\n",
- (unsigned long)tv.tv_sec,
+ (unsigned long)tv.tv_jiff,
(unsigned long)tv.tv_usec);
#ifdef FAST_TIMER_SANITY_CHECKS
used += sprintf(bigbuf + used, "Sanity failed: %i\n",
@@ -661,10 +527,8 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
int end_i = debug_log_cnt;
i = 0;
- if (debug_log_cnt_wrapped)
- {
+ if (debug_log_cnt_wrapped)
i = debug_log_cnt;
- }
while ((i != end_i || (debug_log_cnt_wrapped && !used)) &&
used+100 < BIG_BUF_SIZE)
@@ -697,9 +561,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
"d: %6li us data: 0x%08lX"
"\n",
t->name,
- (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_jiff,
(unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_jiff,
(unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
@@ -719,9 +583,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
"d: %6li us data: 0x%08lX"
"\n",
t->name,
- (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_jiff,
(unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_jiff,
(unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
@@ -739,9 +603,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
"d: %6li us data: 0x%08lX"
"\n",
t->name,
- (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_jiff,
(unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_jiff,
(unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
@@ -752,26 +616,25 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
used += sprintf(bigbuf + used, "Active timers:\n");
local_irq_save(flags);
- local_irq_save(flags);
t = fast_timer_list;
while (t != NULL && (used+100 < BIG_BUF_SIZE))
{
nextt = t->next;
local_irq_restore(flags);
used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
- "d: %6li us data: 0x%08lX"
-/* " func: 0x%08lX" */
- "\n",
- t->name,
- (unsigned long)t->tv_set.tv_sec,
- (unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
- (unsigned long)t->tv_expires.tv_usec,
+ "d: %6li us data: 0x%08lX"
+/* " func: 0x%08lX" */
+ "\n",
+ t->name,
+ (unsigned long)t->tv_set.tv_jiff,
+ (unsigned long)t->tv_set.tv_usec,
+ (unsigned long)t->tv_expires.tv_jiff,
+ (unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
/* , t->function */
);
- local_irq_disable();
+ local_irq_save(flags);
if (t->next != nextt)
{
printk("timer removed!\n");
@@ -800,7 +663,7 @@ static volatile int num_test_timeout = 0;
static struct fast_timer tr[10];
static int exp_num[10];
-static struct timeval tv_exp[100];
+static struct fasttime_t tv_exp[100];
static void test_timeout(unsigned long data)
{
@@ -838,7 +701,7 @@ static void fast_timer_test(void)
int prev_num;
int j;
- struct timeval tv, tv0, tv1, tv2;
+ struct fasttime_t tv, tv0, tv1, tv2;
printk("fast_timer_test() start\n");
do_gettimeofday_fast(&tv);
@@ -851,21 +714,22 @@ static void fast_timer_test(void)
{
do_gettimeofday_fast(&tv_exp[j]);
}
- printk("fast_timer_test() %is %06i\n", tv.tv_sec, tv.tv_usec);
+ printk(KERN_DEBUG "fast_timer_test() %is %06i\n", tv.tv_jiff, tv.tv_usec);
for (j = 0; j < 1000; j++)
{
- printk("%i %i %i %i %i\n",j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]);
+ printk(KERN_DEBUG "%i %i %i %i %i\n",
+ j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]);
j += 4;
}
for (j = 0; j < 100; j++)
{
- printk("%i.%i %i.%i %i.%i %i.%i %i.%i\n",
- tv_exp[j].tv_sec,tv_exp[j].tv_usec,
- tv_exp[j+1].tv_sec,tv_exp[j+1].tv_usec,
- tv_exp[j+2].tv_sec,tv_exp[j+2].tv_usec,
- tv_exp[j+3].tv_sec,tv_exp[j+3].tv_usec,
- tv_exp[j+4].tv_sec,tv_exp[j+4].tv_usec);
+ printk(KERN_DEBUG "%i.%i %i.%i %i.%i %i.%i %i.%i\n",
+ tv_exp[j].tv_jiff, tv_exp[j].tv_usec,
+ tv_exp[j+1].tv_jiff, tv_exp[j+1].tv_usec,
+ tv_exp[j+2].tv_jiff, tv_exp[j+2].tv_usec,
+ tv_exp[j+3].tv_jiff, tv_exp[j+3].tv_usec,
+ tv_exp[j+4].tv_jiff, tv_exp[j+4].tv_usec);
j += 4;
}
do_gettimeofday_fast(&tv0);
@@ -892,14 +756,15 @@ static void fast_timer_test(void)
while (num_test_timeout < i)
{
if (num_test_timeout != prev_num)
- {
prev_num = num_test_timeout;
- }
}
do_gettimeofday_fast(&tv2);
- printk("Timers started %is %06i\n", tv0.tv_sec, tv0.tv_usec);
- printk("Timers started at %is %06i\n", tv1.tv_sec, tv1.tv_usec);
- printk("Timers done %is %06i\n", tv2.tv_sec, tv2.tv_usec);
+ printk(KERN_INFO "Timers started %is %06i\n",
+ tv0.tv_jiff, tv0.tv_usec);
+ printk(KERN_INFO "Timers started at %is %06i\n",
+ tv1.tv_jiff, tv1.tv_usec);
+ printk(KERN_INFO "Timers done %is %06i\n",
+ tv2.tv_jiff, tv2.tv_usec);
DP(printk("buf0:\n");
printk(buf0);
printk("buf1:\n");
@@ -921,9 +786,9 @@ static void fast_timer_test(void)
printk("%-10s set: %6is %06ius exp: %6is %06ius "
"data: 0x%08X func: 0x%08X\n",
t->name,
- t->tv_set.tv_sec,
+ t->tv_set.tv_jiff,
t->tv_set.tv_usec,
- t->tv_expires.tv_sec,
+ t->tv_expires.tv_jiff,
t->tv_expires.tv_usec,
t->data,
t->function
@@ -931,10 +796,12 @@ static void fast_timer_test(void)
printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n",
t->delay_us,
- tv_exp[j].tv_sec,
+ tv_exp[j].tv_jiff,
tv_exp[j].tv_usec,
exp_num[j],
- (tv_exp[j].tv_sec - t->tv_expires.tv_sec)*1000000 + tv_exp[j].tv_usec - t->tv_expires.tv_usec);
+ (tv_exp[j].tv_jiff - t->tv_expires.tv_jiff) *
+ 1000000 + tv_exp[j].tv_usec -
+ t->tv_expires.tv_usec);
}
proc_fasttimer_read(buf5, NULL, 0, 0, 0);
printk("buf5 after all done:\n");
@@ -944,7 +811,7 @@ static void fast_timer_test(void)
#endif
-void fast_timer_init(void)
+int fast_timer_init(void)
{
/* For some reason, request_irq() hangs when called froom time_init() */
if (!fast_timer_is_init)
@@ -952,18 +819,20 @@ void fast_timer_init(void)
printk("fast_timer_init()\n");
#ifdef CONFIG_PROC_FS
- if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 )))
- fasttimer_proc_entry->read_proc = proc_fasttimer_read;
+ fasttimer_proc_entry = create_proc_entry("fasttimer", 0, 0);
+ if (fasttimer_proc_entry)
+ fasttimer_proc_entry->read_proc = proc_fasttimer_read;
#endif /* PROC_FS */
- if(request_irq(TIMER_INTR_VECT, timer_trig_interrupt, IRQF_DISABLED,
- "fast timer int", NULL))
- {
- printk("err: timer1 irq\n");
- }
+ if (request_irq(TIMER0_INTR_VECT, timer_trig_interrupt,
+ IRQF_SHARED | IRQF_DISABLED,
+ "fast timer int", &fast_timer_list))
+ printk(KERN_ERR "err: fasttimer irq\n");
fast_timer_is_init = 1;
#ifdef FAST_TIMER_TEST
printk("do test\n");
fast_timer_test();
#endif
}
+ return 0;
}
+__initcall(fast_timer_init);
diff --git a/arch/cris/arch-v32/kernel/head.S b/arch/cris/arch-v32/kernel/head.S
index 20bd80a84e4..2d66a7c320e 100644
--- a/arch/cris/arch-v32/kernel/head.S
+++ b/arch/cris/arch-v32/kernel/head.S
@@ -4,22 +4,25 @@
* Copyright (C) 2003, Axis Communications AB
*/
-
#define ASSEMBLER_MACROS_ONLY
/*
* The macros found in mmu_defs_asm.h uses the ## concatenation operator, so
* -traditional must not be used when assembling this file.
*/
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/asm/mmu_defs_asm.h>
-#include <asm/arch/hwregs/asm/reg_map_asm.h>
-#include <asm/arch/hwregs/asm/config_defs_asm.h>
-#include <asm/arch/hwregs/asm/bif_core_defs_asm.h>
+#include <hwregs/reg_rdwr.h>
+#include <asm/arch/memmap.h>
+#include <hwregs/intr_vect.h>
+#include <hwregs/asm/mmu_defs_asm.h>
+#include <hwregs/asm/reg_map_asm.h>
+#include <asm/arch/mach/startup.inc>
#define CRAMFS_MAGIC 0x28cd3d45
+#define JHEAD_MAGIC 0x1FF528A6
+#define JHEAD_SIZE 8
#define RAM_INIT_MAGIC 0x56902387
#define COMMAND_LINE_MAGIC 0x87109563
+#define NAND_BOOT_MAGIC 0x9a9db001
;; NOTE: R8 and R9 carry information from the decompressor (if the
;; kernel was compressed). They must not be used in the code below
@@ -30,12 +33,11 @@
.global romfs_start
.global romfs_length
.global romfs_in_flash
+ .global nand_boot
.global swapper_pg_dir
- .global crisv32_nand_boot
- .global crisv32_nand_cramfs_offset
;; Dummy section to make it bootable with current VCS simulator
-#ifdef CONFIG_ETRAXFS_SIM
+#ifdef CONFIG_ETRAX_VCS_SIM
.section ".boot", "ax"
ba tstart
nop
@@ -51,33 +53,15 @@ tstart:
;;
di
- ;; Start clocks for used blocks.
- move.d REG_ADDR(config, regi_config, rw_clk_ctrl), $r1
- move.d [$r1], $r0
- or.d REG_STATE(config, rw_clk_ctrl, cpu, yes) | \
- REG_STATE(config, rw_clk_ctrl, bif, yes) | \
- REG_STATE(config, rw_clk_ctrl, fix_io, yes), $r0
- move.d $r0, [$r1]
-
- ;; Set up waitstates etc
- move.d REG_ADDR(bif_core, regi_bif_core, rw_grp1_cfg), $r0
- move.d CONFIG_ETRAX_MEM_GRP1_CONFIG, $r1
- move.d $r1, [$r0]
- move.d REG_ADDR(bif_core, regi_bif_core, rw_grp2_cfg), $r0
- move.d CONFIG_ETRAX_MEM_GRP2_CONFIG, $r1
- move.d $r1, [$r0]
- move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r0
- move.d CONFIG_ETRAX_MEM_GRP3_CONFIG, $r1
- move.d $r1, [$r0]
- move.d REG_ADDR(bif_core, regi_bif_core, rw_grp4_cfg), $r0
- move.d CONFIG_ETRAX_MEM_GRP4_CONFIG, $r1
- move.d $r1, [$r0]
-
-#ifdef CONFIG_ETRAXFS_SIM
- ;; Set up minimal flash waitstates
- move.d 0, $r10
- move.d REG_ADDR(bif_core, regi_bif_core, rw_grp1_cfg), $r11
- move.d $r10, [$r11]
+ START_CLOCKS
+
+ SETUP_WAIT_STATES
+
+ GIO_INIT
+
+#ifdef CONFIG_SMP
+secondary_cpu_entry: /* Entry point for secondary CPUs */
+ di
#endif
;; Setup and enable the MMU. Use same configuration for both the data
@@ -85,7 +69,7 @@ tstart:
;;
;; Note; 3 cycles is needed for a bank-select to take effect. Further;
;; bank 1 is the instruction MMU, bank 2 is the data MMU.
-#ifndef CONFIG_ETRAXFS_SIM
+#ifndef CONFIG_ETRAX_VCS_SIM
move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \
| REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \
| REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
@@ -93,7 +77,7 @@ tstart:
;; Map the virtual DRAM to the RW eprom area at address 0.
;; Also map 0xa for the hook calls,
move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \
- | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 0) \
+ | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \
| REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb) \
| REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0xa), $r0
#endif
@@ -104,7 +88,7 @@ tstart:
;; Enable certain page protections and setup linear mapping
;; for f,e,c,b,4,0.
-#ifndef CONFIG_ETRAXFS_SIM
+#ifndef CONFIG_ETRAX_VCS_SIM
move.d REG_STATE(mmu, rw_mm_cfg, we, on) \
| REG_STATE(mmu, rw_mm_cfg, acc, on) \
| REG_STATE(mmu, rw_mm_cfg, ex, on) \
@@ -183,17 +167,11 @@ tstart:
nop
nop
nop
- move $s10, $r0
+ move $s12, $r0
cmpq 0, $r0
beq master_cpu
nop
slave_cpu:
- ; A slave waits for cpu_now_booting to be equal to CPU ID.
- move.d cpu_now_booting, $r1
-slave_wait:
- cmp.d [$r1], $r0
- bne slave_wait
- nop
; Time to boot-up. Get stack location provided by master CPU.
move.d smp_init_current_idle_thread, $r1
move.d [$r1], $sp
@@ -203,9 +181,16 @@ slave_wait:
jsr smp_callin
nop
master_cpu:
+ /* Set up entry point for secondary CPUs. The boot ROM has set up
+ * EBP at start of internal memory. The CPU will get there
+ * later when we issue an IPI to them... */
+ move.d MEM_INTMEM_START + IPI_INTR_VECT * 4, $r0
+ move.d secondary_cpu_entry, $r1
+ move.d $r1, [$r0]
#endif
-#ifndef CONFIG_ETRAXFS_SIM
- ;; Check if starting from DRAM or flash.
+#ifndef CONFIG_ETRAX_VCS_SIM
+ ; Check if starting from DRAM (network->RAM boot or unpacked
+ ; compressed kernel), or directly from flash.
lapcq ., $r0
and.d 0x7fffffff, $r0 ; Mask off the non-cache bit.
cmp.d 0x10000, $r0 ; Arbitrary, something above this code.
@@ -232,12 +217,13 @@ _inflash:
beq _dram_initialized
nop
-#include "../lib/dram_init.S"
+#include "../mach/dram_init.S"
_dram_initialized:
;; Copy the text and data section to DRAM. This depends on that the
;; variables used below are correctly set up by the linker script.
;; The calculated value stored in R4 is used below.
+ ;; Leave the cramfs file system (piggybacked after the kernel) in flash.
moveq 0, $r0 ; Source.
move.d text_start, $r1 ; Destination.
move.d __vmlinux_end, $r2
@@ -249,7 +235,7 @@ _dram_initialized:
blo 1b
nop
- ;; Keep CRAMFS in flash.
+ ;; Check for cramfs.
moveq 0, $r0
move.d romfs_length, $r1
move.d $r0, [$r1]
@@ -258,6 +244,7 @@ _dram_initialized:
bne 1f
nop
+ ;; Set length and start of cramfs, set romfs_in_flash flag
addoq +4, $r4, $acr
move.d [$acr], $r0
move.d romfs_length, $r1
@@ -273,35 +260,32 @@ _dram_initialized:
nop
_inram:
- ;; Check if booting from NAND flash (in that case we just remember the offset
- ;; into the flash where cramfs should be).
- move.d REG_ADDR(config, regi_config, r_bootsel), $r0
- move.d [$r0], $r0
- and.d REG_MASK(config, r_bootsel, boot_mode), $r0
- cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0
- bne move_cramfs
- moveq 1,$r0
- move.d crisv32_nand_boot, $r1
- move.d $r0, [$r1]
- move.d crisv32_nand_cramfs_offset, $r1
- move.d $r9, [$r1]
+ ;; Check if booting from NAND flash; if so, set appropriate flags
+ ;; and move on.
+ cmp.d NAND_BOOT_MAGIC, $r12
+ bne move_cramfs ; not nand, jump
moveq 1, $r0
- move.d romfs_in_flash, $r1
+ move.d nand_boot, $r1 ; tell axisflashmap we're booting from NAND
+ move.d $r0, [$r1]
+ moveq 0, $r0 ; tell axisflashmap romfs is not in
+ move.d romfs_in_flash, $r1 ; (directly accessed) flash
move.d $r0, [$r1]
- jump _start_it
+ jump _start_it ; continue with boot
nop
move_cramfs:
- ;; Move the cramfs after BSS.
+ ;; kernel is in DRAM.
+ ;; Must figure out if there is a piggybacked rootfs image or not.
+ ;; Set romfs_length to 0 => no rootfs image available by default.
moveq 0, $r0
move.d romfs_length, $r1
move.d $r0, [$r1]
-#ifndef CONFIG_ETRAXFS_SIM
+#ifndef CONFIG_ETRAX_VCS_SIM
;; The kernel could have been unpacked to DRAM by the loader, but
- ;; the cramfs image could still be inte the flash immediately
- ;; following the compressed kernel image. The loaded passes the address
- ;; of the bute succeeding the last compressed byte in the flash in
+ ;; the cramfs image could still be in the flash immediately
+ ;; following the compressed kernel image. The loader passes the address
+ ;; of the byte succeeding the last compressed byte in the flash in
;; register R9 when starting the kernel.
cmp.d 0x0ffffff8, $r9
bhs _no_romfs_in_flash ; R9 points outside the flash area.
@@ -310,11 +294,13 @@ move_cramfs:
ba _no_romfs_in_flash
nop
#endif
+ ;; cramfs rootfs might to be in flash. Check for it.
move.d [$r9], $r0 ; cramfs_super.magic
cmp.d CRAMFS_MAGIC, $r0
bne _no_romfs_in_flash
nop
+ ;; found cramfs in flash. set address and size, and romfs_in_flash flag.
addoq +4, $r9, $acr
move.d [$acr], $r0
move.d romfs_length, $r1
@@ -330,27 +316,43 @@ move_cramfs:
nop
_no_romfs_in_flash:
- ;; Look for cramfs.
+ ;; No romfs in flash, so look for cramfs, or jffs2 with jhead,
+ ;; after kernel in RAM, as is the case with network->RAM boot.
+ ;; For cramfs, partition starts with magic and length.
+ ;; For jffs2, a jhead is prepended which contains with magic and length.
+ ;; The jhead is not part of the jffs2 partition however.
#ifndef CONFIG_ETRAXFS_SIM
move.d __vmlinux_end, $r0
#else
move.d __end, $r0
#endif
move.d [$r0], $r1
- cmp.d CRAMFS_MAGIC, $r1
- bne 2f
+ cmp.d CRAMFS_MAGIC, $r1 ; cramfs magic?
+ beq 2f ; yes, jump
+ nop
+ cmp.d JHEAD_MAGIC, $r1 ; jffs2 (jhead) magic?
+ bne 4f ; no, skip copy
nop
+ addq 4, $r0 ; location of jffs2 size
+ move.d [$r0+], $r2 ; fetch jffs2 size -> r2
+ ; r0 now points to start of jffs2
+ ba 3f
+ nop
+2:
+ addoq +4, $r0, $acr ; location of cramfs size
+ move.d [$acr], $r2 ; fetch cramfs size -> r2
+ ; r0 still points to start of cramfs
+3:
+ ;; Now, move the root fs to after kernel's BSS
- addoq +4, $r0, $acr
- move.d [$acr], $r2
- move.d _end, $r1
+ move.d _end, $r1 ; start of cramfs -> r1
move.d romfs_start, $r3
- move.d $r1, [$r3]
+ move.d $r1, [$r3] ; store at romfs_start (for axisflashmap)
move.d romfs_length, $r3
- move.d $r2, [$r3]
+ move.d $r2, [$r3] ; store size at romfs_length
-#ifndef CONFIG_ETRAXFS_SIM
- add.d $r2, $r0
+#ifndef CONFIG_ETRAX_VCS_SIM
+ add.d $r2, $r0 ; copy from end and downwards
add.d $r2, $r1
lsrq 1, $r2 ; Size is in bytes, we copy words.
@@ -365,10 +367,17 @@ _no_romfs_in_flash:
nop
#endif
-2:
+4:
+ ;; BSS move done.
+ ;; Clear romfs_in_flash flag, as we now know romfs is in DRAM
+ ;; Also clear nand_boot flag; if we got here, we know we've not
+ ;; booted from NAND flash.
moveq 0, $r0
move.d romfs_in_flash, $r1
move.d $r0, [$r1]
+ moveq 0, $r0
+ move.d nand_boot, $r1
+ move.d $r0, [$r1]
jump _start_it ; Jump to cached code.
nop
@@ -384,8 +393,8 @@ _start_it:
move.d cris_command_line, $r10
or.d 0x80000000, $r11 ; Make it virtual
1:
- move.b [$r11+], $r12
- move.b $r12, [$r10+]
+ move.b [$r11+], $r1
+ move.b $r1, [$r10+]
subq 1, $r13
bne 1b
nop
@@ -401,7 +410,7 @@ no_command_line:
move.d etrax_irv, $r1 ; Set the exception base register and pointer.
move.d $r0, [$r1]
-#ifndef CONFIG_ETRAXFS_SIM
+#ifndef CONFIG_ETRAX_VCS_SIM
;; Clear the BSS region from _bss_start to _end.
move.d __bss_start, $r0
move.d _end, $r1
@@ -411,7 +420,7 @@ no_command_line:
nop
#endif
-#ifdef CONFIG_ETRAXFS_SIM
+#ifdef CONFIG_ETRAX_VCS_SIM
/* Set the watchdog timeout to something big. Will be removed when */
/* watchdog can be disabled with command line option */
move.d 0x7fffffff, $r10
@@ -423,25 +432,44 @@ no_command_line:
move.d __bss_start, $r0
movem [$r0], $r13
+#ifdef CONFIG_ETRAX_L2CACHE
+ jsr l2cache_init
+ nop
+#endif
+
jump start_kernel ; Jump to start_kernel() in init/main.c.
nop
.data
etrax_irv:
.dword 0
+
+; Variables for communication with the Axis flash map driver (axisflashmap),
+; and for setting up memory in arch/cris/kernel/setup.c .
+
+; romfs_start is set to the start of the root file system, if it exists
+; in directly accessible memory (i.e. NOR Flash when booting from Flash,
+; or RAM when booting directly from a network-downloaded RAM image)
romfs_start:
.dword 0
+
+; romfs_length is set to the size of the root file system image, if it exists
+; in directly accessible memory (see romfs_start). Otherwise it is set to 0.
romfs_length:
.dword 0
+
+; romfs_in_flash is set to 1 if the root file system resides in directly
+; accessible flash memory (i.e. NOR flash). It is set to 0 for RAM boot
+; or NAND flash boot.
romfs_in_flash:
.dword 0
-crisv32_nand_boot:
- .dword 0
-crisv32_nand_cramfs_offset:
+
+; nand_boot is set to 1 when the kernel has been booted from NAND flash
+nand_boot:
.dword 0
swapper_pg_dir = 0xc0002000
.section ".init.data", "aw"
-#include "../lib/hw_settings.S"
+#include "../mach/hw_settings.S"
diff --git a/arch/cris/arch-v32/kernel/io.c b/arch/cris/arch-v32/kernel/io.c
deleted file mode 100644
index a22a9e02e09..00000000000
--- a/arch/cris/arch-v32/kernel/io.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Helper functions for I/O pins.
- *
- * Copyright (c) 2004 Axis Communications AB.
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/io.h>
-#include <asm/arch/pinmux.h>
-#include <asm/arch/hwregs/gio_defs.h>
-
-struct crisv32_ioport crisv32_ioports[] =
-{
- {
- (unsigned long*)REG_ADDR(gio, regi_gio, rw_pa_oe),
- (unsigned long*)REG_ADDR(gio, regi_gio, rw_pa_dout),
- (unsigned long*)REG_ADDR(gio, regi_gio, r_pa_din),
- 8
- },
- {
- (unsigned long*)REG_ADDR(gio, regi_gio, rw_pb_oe),
- (unsigned long*)REG_ADDR(gio, regi_gio, rw_pb_dout),
- (unsigned long*)REG_ADDR(gio, regi_gio, r_pb_din),
- 18
- },
- {
- (unsigned long*)REG_ADDR(gio, regi_gio, rw_pc_oe),
- (unsigned long*)REG_ADDR(gio, regi_gio, rw_pc_dout),
- (unsigned long*)REG_ADDR(gio, regi_gio, r_pc_din),
- 18
- },
- {
- (unsigned long*)REG_ADDR(gio, regi_gio, rw_pd_oe),
- (unsigned long*)REG_ADDR(gio, regi_gio, rw_pd_dout),
- (unsigned long*)REG_ADDR(gio, regi_gio, r_pd_din),
- 18
- },
- {
- (unsigned long*)REG_ADDR(gio, regi_gio, rw_pe_oe),
- (unsigned long*)REG_ADDR(gio, regi_gio, rw_pe_dout),
- (unsigned long*)REG_ADDR(gio, regi_gio, r_pe_din),
- 18
- }
-};
-
-#define NBR_OF_PORTS ARRAY_SIZE(crisv32_ioports)
-
-struct crisv32_iopin crisv32_led1_green;
-struct crisv32_iopin crisv32_led1_red;
-struct crisv32_iopin crisv32_led2_green;
-struct crisv32_iopin crisv32_led2_red;
-struct crisv32_iopin crisv32_led3_green;
-struct crisv32_iopin crisv32_led3_red;
-
-/* Dummy port used when green LED and red LED is on the same bit */
-static unsigned long io_dummy;
-static struct crisv32_ioport dummy_port =
-{
- &io_dummy,
- &io_dummy,
- &io_dummy,
- 18
-};
-static struct crisv32_iopin dummy_led =
-{
- &dummy_port,
- 0
-};
-
-static int __init crisv32_io_init(void)
-{
- int ret = 0;
- /* Initialize LEDs */
- ret += crisv32_io_get_name(&crisv32_led1_green, CONFIG_ETRAX_LED1G);
- ret += crisv32_io_get_name(&crisv32_led1_red, CONFIG_ETRAX_LED1R);
- ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_LED2G);
- ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_LED2R);
- ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_LED3G);
- ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_LED3R);
- crisv32_io_set_dir(&crisv32_led1_green, crisv32_io_dir_out);
- crisv32_io_set_dir(&crisv32_led1_red, crisv32_io_dir_out);
- crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out);
- crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out);
- crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out);
- crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out);
-
- if (!strcmp(CONFIG_ETRAX_LED1G, CONFIG_ETRAX_LED1R))
- crisv32_led1_red = dummy_led;
- if (!strcmp(CONFIG_ETRAX_LED2G, CONFIG_ETRAX_LED2R))
- crisv32_led2_red = dummy_led;
-
- return ret;
-}
-
-__initcall(crisv32_io_init);
-
-int crisv32_io_get(struct crisv32_iopin* iopin,
- unsigned int port, unsigned int pin)
-{
- if (port > NBR_OF_PORTS)
- return -EINVAL;
- if (port > crisv32_ioports[port].pin_count)
- return -EINVAL;
-
- iopin->bit = 1 << pin;
- iopin->port = &crisv32_ioports[port];
-
- if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio))
- return -EIO;
-
- return 0;
-}
-
-int crisv32_io_get_name(struct crisv32_iopin* iopin,
- char* name)
-{
- int port;
- int pin;
-
- if (toupper(*name) == 'P')
- name++;
-
- if (toupper(*name) < 'A' || toupper(*name) > 'E')
- return -EINVAL;
-
- port = toupper(*name) - 'A';
- name++;
- pin = simple_strtoul(name, NULL, 10);
-
- if (pin < 0 || pin > crisv32_ioports[port].pin_count)
- return -EINVAL;
-
- iopin->bit = 1 << pin;
- iopin->port = &crisv32_ioports[port];
-
- if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio))
- return -EIO;
-
- return 0;
-}
-
-#ifdef CONFIG_PCI
-/* PCI I/O access stuff */
-struct cris_io_operations* cris_iops = NULL;
-EXPORT_SYMBOL(cris_iops);
-#endif
-
diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c
index a9acaa27024..173c141ac9b 100644
--- a/arch/cris/arch-v32/kernel/irq.c
+++ b/arch/cris/arch-v32/kernel/irq.c
@@ -15,15 +15,21 @@
#include <linux/threads.h>
#include <linux/spinlock.h>
#include <linux/kernel_stat.h>
-#include <asm/arch/hwregs/reg_map.h>
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/intr_vect.h>
-#include <asm/arch/hwregs/intr_vect_defs.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/intr_vect.h>
+#include <hwregs/intr_vect_defs.h>
#define CPU_FIXED -1
/* IRQ masks (refer to comment for crisv32_do_multiple) */
-#define TIMER_MASK (1 << (TIMER_INTR_VECT - FIRST_IRQ))
+#if TIMER0_INTR_VECT - FIRST_IRQ < 32
+#define TIMER_MASK (1 << (TIMER0_INTR_VECT - FIRST_IRQ))
+#undef TIMER_VECT1
+#else
+#define TIMER_MASK (1 << (TIMER0_INTR_VECT - FIRST_IRQ - 32))
+#define TIMER_VECT1
+#endif
#ifdef CONFIG_ETRAX_KGDB
#if defined(CONFIG_ETRAX_KGDB_PORT0)
#define IGNOREMASK (1 << (SER0_INTR_VECT - FIRST_IRQ))
@@ -44,8 +50,8 @@ struct cris_irq_allocation
cpumask_t mask; /* The CPUs to which the IRQ may be allocated. */
};
-struct cris_irq_allocation irq_allocations[NR_IRQS] =
- {[0 ... NR_IRQS - 1] = {0, CPU_MASK_ALL}};
+struct cris_irq_allocation irq_allocations[NR_REAL_IRQS] =
+ { [0 ... NR_REAL_IRQS - 1] = {0, CPU_MASK_ALL} };
static unsigned long irq_regs[NR_CPUS] =
{
@@ -55,6 +61,12 @@ static unsigned long irq_regs[NR_CPUS] =
#endif
};
+#if NR_REAL_IRQS > 32
+#define NBR_REGS 2
+#else
+#define NBR_REGS 1
+#endif
+
unsigned long cpu_irq_counters[NR_CPUS];
unsigned long irq_counters[NR_REAL_IRQS];
@@ -79,45 +91,81 @@ extern void d_mmu_write(void);
extern void kgdb_init(void);
extern void breakpoint(void);
+/* From traps.c. */
+extern void breakh_BUG(void);
+
/*
- * Build the IRQ handler stubs using macros from irq.h. First argument is the
- * IRQ number, the second argument is the corresponding bit in
- * intr_rw_vect_mask found in asm/arch/hwregs/intr_vect_defs.h.
+ * Build the IRQ handler stubs using macros from irq.h.
*/
-BUILD_IRQ(0x31, (1 << 0)) /* memarb */
-BUILD_IRQ(0x32, (1 << 1)) /* gen_io */
-BUILD_IRQ(0x33, (1 << 2)) /* iop0 */
-BUILD_IRQ(0x34, (1 << 3)) /* iop1 */
-BUILD_IRQ(0x35, (1 << 4)) /* iop2 */
-BUILD_IRQ(0x36, (1 << 5)) /* iop3 */
-BUILD_IRQ(0x37, (1 << 6)) /* dma0 */
-BUILD_IRQ(0x38, (1 << 7)) /* dma1 */
-BUILD_IRQ(0x39, (1 << 8)) /* dma2 */
-BUILD_IRQ(0x3a, (1 << 9)) /* dma3 */
-BUILD_IRQ(0x3b, (1 << 10)) /* dma4 */
-BUILD_IRQ(0x3c, (1 << 11)) /* dma5 */
-BUILD_IRQ(0x3d, (1 << 12)) /* dma6 */
-BUILD_IRQ(0x3e, (1 << 13)) /* dma7 */
-BUILD_IRQ(0x3f, (1 << 14)) /* dma8 */
-BUILD_IRQ(0x40, (1 << 15)) /* dma9 */
-BUILD_IRQ(0x41, (1 << 16)) /* ata */
-BUILD_IRQ(0x42, (1 << 17)) /* sser0 */
-BUILD_IRQ(0x43, (1 << 18)) /* sser1 */
-BUILD_IRQ(0x44, (1 << 19)) /* ser0 */
-BUILD_IRQ(0x45, (1 << 20)) /* ser1 */
-BUILD_IRQ(0x46, (1 << 21)) /* ser2 */
-BUILD_IRQ(0x47, (1 << 22)) /* ser3 */
-BUILD_IRQ(0x48, (1 << 23))
-BUILD_IRQ(0x49, (1 << 24)) /* eth0 */
-BUILD_IRQ(0x4a, (1 << 25)) /* eth1 */
-BUILD_TIMER_IRQ(0x4b, (1 << 26))/* timer */
-BUILD_IRQ(0x4c, (1 << 27)) /* bif_arb */
-BUILD_IRQ(0x4d, (1 << 28)) /* bif_dma */
-BUILD_IRQ(0x4e, (1 << 29)) /* ext */
-BUILD_IRQ(0x4f, (1 << 29)) /* ipi */
+BUILD_IRQ(0x31)
+BUILD_IRQ(0x32)
+BUILD_IRQ(0x33)
+BUILD_IRQ(0x34)
+BUILD_IRQ(0x35)
+BUILD_IRQ(0x36)
+BUILD_IRQ(0x37)
+BUILD_IRQ(0x38)
+BUILD_IRQ(0x39)
+BUILD_IRQ(0x3a)
+BUILD_IRQ(0x3b)
+BUILD_IRQ(0x3c)
+BUILD_IRQ(0x3d)
+BUILD_IRQ(0x3e)
+BUILD_IRQ(0x3f)
+BUILD_IRQ(0x40)
+BUILD_IRQ(0x41)
+BUILD_IRQ(0x42)
+BUILD_IRQ(0x43)
+BUILD_IRQ(0x44)
+BUILD_IRQ(0x45)
+BUILD_IRQ(0x46)
+BUILD_IRQ(0x47)
+BUILD_IRQ(0x48)
+BUILD_IRQ(0x49)
+BUILD_IRQ(0x4a)
+BUILD_IRQ(0x4b)
+BUILD_IRQ(0x4c)
+BUILD_IRQ(0x4d)
+BUILD_IRQ(0x4e)
+BUILD_IRQ(0x4f)
+BUILD_IRQ(0x50)
+#if MACH_IRQS > 32
+BUILD_IRQ(0x51)
+BUILD_IRQ(0x52)
+BUILD_IRQ(0x53)
+BUILD_IRQ(0x54)
+BUILD_IRQ(0x55)
+BUILD_IRQ(0x56)
+BUILD_IRQ(0x57)
+BUILD_IRQ(0x58)
+BUILD_IRQ(0x59)
+BUILD_IRQ(0x5a)
+BUILD_IRQ(0x5b)
+BUILD_IRQ(0x5c)
+BUILD_IRQ(0x5d)
+BUILD_IRQ(0x5e)
+BUILD_IRQ(0x5f)
+BUILD_IRQ(0x60)
+BUILD_IRQ(0x61)
+BUILD_IRQ(0x62)
+BUILD_IRQ(0x63)
+BUILD_IRQ(0x64)
+BUILD_IRQ(0x65)
+BUILD_IRQ(0x66)
+BUILD_IRQ(0x67)
+BUILD_IRQ(0x68)
+BUILD_IRQ(0x69)
+BUILD_IRQ(0x6a)
+BUILD_IRQ(0x6b)
+BUILD_IRQ(0x6c)
+BUILD_IRQ(0x6d)
+BUILD_IRQ(0x6e)
+BUILD_IRQ(0x6f)
+BUILD_IRQ(0x70)
+#endif
/* Pointers to the low-level handlers. */
-static void (*interrupt[NR_IRQS])(void) = {
+static void (*interrupt[MACH_IRQS])(void) = {
IRQ0x31_interrupt, IRQ0x32_interrupt, IRQ0x33_interrupt,
IRQ0x34_interrupt, IRQ0x35_interrupt, IRQ0x36_interrupt,
IRQ0x37_interrupt, IRQ0x38_interrupt, IRQ0x39_interrupt,
@@ -128,7 +176,20 @@ static void (*interrupt[NR_IRQS])(void) = {
IRQ0x46_interrupt, IRQ0x47_interrupt, IRQ0x48_interrupt,
IRQ0x49_interrupt, IRQ0x4a_interrupt, IRQ0x4b_interrupt,
IRQ0x4c_interrupt, IRQ0x4d_interrupt, IRQ0x4e_interrupt,
- IRQ0x4f_interrupt
+ IRQ0x4f_interrupt, IRQ0x50_interrupt,
+#if MACH_IRQS > 32
+ IRQ0x51_interrupt, IRQ0x52_interrupt, IRQ0x53_interrupt,
+ IRQ0x54_interrupt, IRQ0x55_interrupt, IRQ0x56_interrupt,
+ IRQ0x57_interrupt, IRQ0x58_interrupt, IRQ0x59_interrupt,
+ IRQ0x5a_interrupt, IRQ0x5b_interrupt, IRQ0x5c_interrupt,
+ IRQ0x5d_interrupt, IRQ0x5e_interrupt, IRQ0x5f_interrupt,
+ IRQ0x60_interrupt, IRQ0x61_interrupt, IRQ0x62_interrupt,
+ IRQ0x63_interrupt, IRQ0x64_interrupt, IRQ0x65_interrupt,
+ IRQ0x66_interrupt, IRQ0x67_interrupt, IRQ0x68_interrupt,
+ IRQ0x69_interrupt, IRQ0x6a_interrupt, IRQ0x6b_interrupt,
+ IRQ0x6c_interrupt, IRQ0x6d_interrupt, IRQ0x6e_interrupt,
+ IRQ0x6f_interrupt, IRQ0x70_interrupt,
+#endif
};
void
@@ -137,13 +198,26 @@ block_irq(int irq, int cpu)
int intr_mask;
unsigned long flags;
- spin_lock_irqsave(&irq_lock, flags);
- intr_mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask);
-
- /* Remember; 1 let through, 0 block. */
- intr_mask &= ~(1 << (irq - FIRST_IRQ));
-
- REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, intr_mask);
+ spin_lock_irqsave(&irq_lock, flags);
+ if (irq - FIRST_IRQ < 32)
+ intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu],
+ rw_mask, 0);
+ else
+ intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu],
+ rw_mask, 1);
+
+ /* Remember; 1 let thru, 0 block. */
+ if (irq - FIRST_IRQ < 32)
+ intr_mask &= ~(1 << (irq - FIRST_IRQ));
+ else
+ intr_mask &= ~(1 << (irq - FIRST_IRQ - 32));
+
+ if (irq - FIRST_IRQ < 32)
+ REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask,
+ 0, intr_mask);
+ else
+ REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask,
+ 1, intr_mask);
spin_unlock_irqrestore(&irq_lock, flags);
}
@@ -154,12 +228,26 @@ unblock_irq(int irq, int cpu)
unsigned long flags;
spin_lock_irqsave(&irq_lock, flags);
- intr_mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask);
-
- /* Remember; 1 let through, 0 block. */
- intr_mask |= (1 << (irq - FIRST_IRQ));
+ if (irq - FIRST_IRQ < 32)
+ intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu],
+ rw_mask, 0);
+ else
+ intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu],
+ rw_mask, 1);
+
+ /* Remember; 1 let thru, 0 block. */
+ if (irq - FIRST_IRQ < 32)
+ intr_mask |= (1 << (irq - FIRST_IRQ));
+ else
+ intr_mask |= (1 << (irq - FIRST_IRQ - 32));
+
+ if (irq - FIRST_IRQ < 32)
+ REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask,
+ 0, intr_mask);
+ else
+ REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask,
+ 1, intr_mask);
- REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, intr_mask);
spin_unlock_irqrestore(&irq_lock, flags);
}
@@ -298,8 +386,9 @@ crisv32_do_multiple(struct pt_regs* regs)
{
int cpu;
int mask;
- int masked;
+ int masked[NBR_REGS];
int bit;
+ int i;
cpu = smp_processor_id();
@@ -308,42 +397,59 @@ crisv32_do_multiple(struct pt_regs* regs)
*/
irq_enter();
- /* Get which IRQs that happened. */
- masked = REG_RD_INT(intr_vect, irq_regs[cpu], r_masked_vect);
+ for (i = 0; i < NBR_REGS; i++) {
+ /* Get which IRQs that happend. */
+ masked[i] = REG_RD_INT_VECT(intr_vect, irq_regs[cpu],
+ r_masked_vect, i);
- /* Calculate new IRQ mask with these IRQs disabled. */
- mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask);
- mask &= ~masked;
+ /* Calculate new IRQ mask with these IRQs disabled. */
+ mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i);
+ mask &= ~masked[i];
/* Timer IRQ is never masked */
- if (masked & TIMER_MASK)
- mask |= TIMER_MASK;
-
- /* Block all the IRQs */
- REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, mask);
+#ifdef TIMER_VECT1
+ if ((i == 1) && (masked[0] & TIMER_MASK))
+ mask |= TIMER_MASK;
+#else
+ if ((i == 0) && (masked[0] & TIMER_MASK))
+ mask |= TIMER_MASK;
+#endif
+ /* Block all the IRQs */
+ REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i, mask);
/* Check for timer IRQ and handle it special. */
- if (masked & TIMER_MASK) {
- masked &= ~TIMER_MASK;
- do_IRQ(TIMER_INTR_VECT, regs);
+#ifdef TIMER_VECT1
+ if ((i == 1) && (masked[i] & TIMER_MASK)) {
+ masked[i] &= ~TIMER_MASK;
+ do_IRQ(TIMER0_INTR_VECT, regs);
+ }
+#else
+ if ((i == 0) && (masked[i] & TIMER_MASK)) {
+ masked[i] &= ~TIMER_MASK;
+ do_IRQ(TIMER0_INTR_VECT, regs);
+ }
}
+#endif
#ifdef IGNORE_MASK
/* Remove IRQs that can't be handled as multiple. */
- masked &= ~IGNORE_MASK;
+ masked[0] &= ~IGNORE_MASK;
#endif
/* Handle the rest of the IRQs. */
- for (bit = 0; bit < 32; bit++)
- {
- if (masked & (1 << bit))
- do_IRQ(bit + FIRST_IRQ, regs);
+ for (i = 0; i < NBR_REGS; i++) {
+ for (bit = 0; bit < 32; bit++) {
+ if (masked[i] & (1 << bit))
+ do_IRQ(bit + FIRST_IRQ + i*32, regs);
+ }
}
/* Unblock all the IRQs. */
- mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask);
- mask |= masked;
- REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, mask);
+ for (i = 0; i < NBR_REGS; i++) {
+ mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i);
+ mask |= masked[i];
+ REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i, mask);
+ }
/* This irq_exit() will trigger the soft IRQs. */
irq_exit();
@@ -361,20 +467,21 @@ init_IRQ(void)
reg_intr_vect_rw_mask vect_mask = {0};
/* Clear all interrupts masks. */
- REG_WR(intr_vect, regi_irq, rw_mask, vect_mask);
+ for (i = 0; i < NBR_REGS; i++)
+ REG_WR_VECT(intr_vect, regi_irq, rw_mask, i, vect_mask);
for (i = 0; i < 256; i++)
etrax_irv->v[i] = weird_irq;
- /* Point all IRQs to bad handlers. */
+ /* Point all IRQ's to bad handlers. */
for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) {
irq_desc[j].chip = &crisv32_irq_type;
set_exception_vector(i, interrupt[j]);
}
/* Mark Timer and IPI IRQs as CPU local */
- irq_allocations[TIMER_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
- irq_desc[TIMER_INTR_VECT].status |= IRQ_PER_CPU;
+ irq_allocations[TIMER0_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
+ irq_desc[TIMER0_INTR_VECT].status |= IRQ_PER_CPU;
irq_allocations[IPI_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
irq_desc[IPI_INTR_VECT].status |= IRQ_PER_CPU;
@@ -391,6 +498,11 @@ init_IRQ(void)
set_exception_vector(0x0a, d_mmu_access);
set_exception_vector(0x0b, d_mmu_write);
+#ifdef CONFIG_BUG
+ /* Break 14 handler, used to implement cheap BUG(). */
+ set_exception_vector(0x1e, breakh_BUG);
+#endif
+
/* The system-call trap is reached by "break 13". */
set_exception_vector(0x1d, system_call);
diff --git a/arch/cris/arch-v32/kernel/kgdb.c b/arch/cris/arch-v32/kernel/kgdb.c
index 480e56348be..4e2e2e271ef 100644
--- a/arch/cris/arch-v32/kernel/kgdb.c
+++ b/arch/cris/arch-v32/kernel/kgdb.c
@@ -381,7 +381,7 @@ static int read_register(char regno, unsigned int *valptr);
/* Serial port, reads one character. ETRAX 100 specific. from debugport.c */
int getDebugChar(void);
-#ifdef CONFIG_ETRAXFS_SIM
+#ifdef CONFIG_ETRAX_VCS_SIM
int getDebugChar(void)
{
return socketread();
@@ -391,7 +391,7 @@ int getDebugChar(void)
/* Serial port, writes one character. ETRAX 100 specific. from debugport.c */
void putDebugChar(int val);
-#ifdef CONFIG_ETRAXFS_SIM
+#ifdef CONFIG_ETRAX_VCS_SIM
void putDebugChar(int val)
{
socketwrite((char *)&val, 1);
@@ -1599,7 +1599,7 @@ kgdb_init(void)
REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
ser_intr_mask = REG_RD(ser, regi_ser0, rw_intr_mask);
- ser_intr_mask.data_avail = regk_ser_yes;
+ ser_intr_mask.dav = regk_ser_yes;
REG_WR(ser, regi_ser0, rw_intr_mask, ser_intr_mask);
#elif defined(CONFIG_ETRAX_KGDB_PORT1)
/* Note: no shortcut registered (not handled by multiple_interrupt).
@@ -1611,7 +1611,7 @@ kgdb_init(void)
REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
ser_intr_mask = REG_RD(ser, regi_ser1, rw_intr_mask);
- ser_intr_mask.data_avail = regk_ser_yes;
+ ser_intr_mask.dav = regk_ser_yes;
REG_WR(ser, regi_ser1, rw_intr_mask, ser_intr_mask);
#elif defined(CONFIG_ETRAX_KGDB_PORT2)
/* Note: no shortcut registered (not handled by multiple_interrupt).
@@ -1623,7 +1623,7 @@ kgdb_init(void)
REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
ser_intr_mask = REG_RD(ser, regi_ser2, rw_intr_mask);
- ser_intr_mask.data_avail = regk_ser_yes;
+ ser_intr_mask.dav = regk_ser_yes;
REG_WR(ser, regi_ser2, rw_intr_mask, ser_intr_mask);
#elif defined(CONFIG_ETRAX_KGDB_PORT3)
/* Note: no shortcut registered (not handled by multiple_interrupt).
@@ -1635,7 +1635,7 @@ kgdb_init(void)
REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
ser_intr_mask = REG_RD(ser, regi_ser3, rw_intr_mask);
- ser_intr_mask.data_avail = regk_ser_yes;
+ ser_intr_mask.dav = regk_ser_yes;
REG_WR(ser, regi_ser3, rw_intr_mask, ser_intr_mask);
#endif
diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c
index b72a15580dc..ced5b725d9b 100644
--- a/arch/cris/arch-v32/kernel/process.c
+++ b/arch/cris/arch-v32/kernel/process.c
@@ -12,17 +12,13 @@
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/slab.h>
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/reg_map.h>
-#include <asm/arch/hwregs/timer_defs.h>
-#include <asm/arch/hwregs/intr_vect_defs.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/timer_defs.h>
+#include <hwregs/intr_vect_defs.h>
extern void stop_watchdog(void);
-#ifdef CONFIG_ETRAX_GPIO
-extern void etrax_gpio_wake_up_check(void); /* Defined in drivers/gpio.c. */
-#endif
-
extern int cris_hlt_counter;
/* We use this if we don't have any better idle routine. */
@@ -82,7 +78,7 @@ hard_reset_now(void)
wd_ctrl.cmd = regk_timer_start;
arch_enable_nmi();
- REG_WR(timer, regi_timer, rw_wd_ctrl, wd_ctrl);
+ REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl);
}
#endif
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index 2df60529a8a..e27f4670e88 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2003, Axis Communications AB.
+ * Copyright (C) 2000-2007, Axis Communications AB.
*/
#include <linux/kernel.h>
@@ -149,7 +149,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = generic_ptrace_pokedata(child, addr, data);
break;
- /* Write the word at location address in the USER area. */
+ /* Write the word at location address in the USER area. */
case PTRACE_POKEUSR:
ret = -EIO;
if ((addr & 3) || addr < 0 || addr > PT_MAX << 2)
@@ -201,7 +201,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
- /* Make the child exit by sending it a sigkill. */
+ /* Make the child exit by sending it a sigkill. */
case PTRACE_KILL:
ret = 0;
@@ -245,9 +245,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
+
/* Get all GP registers from the child. */
case PTRACE_GETREGS: {
- int i;
+ int i;
unsigned long tmp;
for (i = 0; i <= PT_MAX; i++) {
@@ -294,6 +295,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
+out_tsk:
return ret;
}
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c
index 024cc690197..58c1866804e 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -50,7 +50,7 @@ struct rt_signal_frame {
unsigned char retcode[8]; /* Trampoline code. */
};
-int do_signal(int restart, sigset_t *oldset, struct pt_regs *regs);
+void do_signal(int restart, struct pt_regs *regs);
void keep_debug_flags(unsigned long oldccs, unsigned long oldspc,
struct pt_regs *regs);
/*
@@ -61,74 +61,16 @@ int
sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
long srp, struct pt_regs *regs)
{
- sigset_t saveset;
-
mask &= _BLOCKABLE;
-
spin_lock_irq(&current->sighand->siglock);
-
- saveset = current->blocked;
-
+ current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
-
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- regs->r10 = -EINTR;
-
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
-
- if (do_signal(0, &saveset, regs)) {
- /*
- * This point is reached twice: once to call
- * the signal handler, then again to return
- * from the sigsuspend system call. When
- * calling the signal handler, R10 hold the
- * signal number as set by do_signal(). The
- * sigsuspend call will always return with
- * the restored value above; -EINTR.
- */
- return regs->r10;
- }
- }
-}
-
-/* Define some dummy arguments to be able to reach the regs argument. */
-int
-sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, long r12, long r13,
- long mof, long srp, struct pt_regs *regs)
-{
- sigset_t saveset;
- sigset_t newset;
-
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
-
- if (copy_from_user(&newset, unewset, sizeof(newset)))
- return -EFAULT;
-
- sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
-
- saveset = current->blocked;
- current->blocked = newset;
-
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
-
- regs->r10 = -EINTR;
-
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
-
- if (do_signal(0, &saveset, regs)) {
- /* See comment in function above. */
- return regs->r10;
- }
- }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
}
int
@@ -290,7 +232,7 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
goto badframe;
if (do_sigaltstack(&frame->uc.uc_stack, NULL, rdusp()) == -EFAULT)
- goto badframe;
+ goto badframe;
keep_debug_flags(oldccs, oldspc, regs);
@@ -347,11 +289,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
/* Grab and setup a signal frame.
*
* Basically a lot of state-info is stacked, and arranged for the
- * user-mode program to return to the kernel using either a trampoline
+ * user-mode program to return to the kernel using either a trampiline
* which performs the syscall sigreturn(), or a provided user-mode
* trampoline.
*/
-static void
+static int
setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
struct pt_regs * regs)
{
@@ -417,16 +359,17 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
/* Actually move the USP to reflect the stacked frame. */
wrusp((unsigned long)frame);
- return;
+ return 0;
give_sigsegv:
if (sig == SIGSEGV)
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
+ return -EFAULT;
}
-static void
+static int
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
@@ -503,21 +446,24 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Actually move the usp to reflect the stacked frame. */
wrusp((unsigned long)frame);
- return;
+ return 0;
give_sigsegv:
if (sig == SIGSEGV)
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
+ return -EFAULT;
}
/* Invoke a singal handler to, well, handle the signal. */
-static inline void
+static inline int
handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs * regs)
{
+ int ret;
+
/* Check if this got called from a system call. */
if (canrestart) {
/* If so, check system call restarting. */
@@ -561,19 +507,24 @@ handle_signal(int canrestart, unsigned long sig,
/* Set up the stack frame. */
if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
else
- setup_frame(sig, ka, oldset, regs);
+ ret = setup_frame(sig, ka, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ if (ret == 0) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked,
+ &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked, sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
+
+ return ret;
}
/*
@@ -587,12 +538,13 @@ handle_signal(int canrestart, unsigned long sig,
* we can use user_mode(regs) to see if we came directly from kernel or user
* mode below.
*/
-int
-do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
+void
+do_signal(int canrestart, struct pt_regs *regs)
{
int signr;
siginfo_t info;
struct k_sigaction ka;
+ sigset_t *oldset;
/*
* The common case should go fast, which is why this point is
@@ -600,17 +552,28 @@ do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
* without doing anything.
*/
if (!user_mode(regs))
- return 1;
+ return;
- if (!oldset)
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
- /* Deliver the signal. */
- handle_signal(canrestart, signr, &info, &ka, oldset, regs);
- return 1;
+ /* Whee! Actually deliver the signal. */
+ if (handle_signal(canrestart, signr, &info, &ka,
+ oldset, regs)) {
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+
+ return;
}
/* Got here from a system call? */
@@ -628,7 +591,12 @@ do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
}
}
- return 0;
+ /* if there's no signal to deliver, we just put the saved sigmask
+ * back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
}
asmlinkage void
@@ -641,7 +609,7 @@ ugdb_trap_user(struct thread_info *ti, int sig)
user_regs(ti)->spc = 0;
}
/* FIXME: Filter out false h/w breakpoint hits (i.e. EDA
- not within any configured h/w breakpoint range). Synchronize with
+ not withing any configured h/w breakpoint range). Synchronize with
what already exists for kernel debugging. */
if (((user_regs(ti)->exs & 0xff00) >> 8) == BREAK_8_INTR_VECT) {
/* Break 8: subtract 2 from ERP unless in a delay slot. */
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index 171c96e0a5d..a9c3334e46c 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -1,11 +1,12 @@
+#include <linux/types.h>
#include <asm/delay.h>
-#include <asm/arch/irq.h>
-#include <asm/arch/hwregs/intr_vect.h>
-#include <asm/arch/hwregs/intr_vect_defs.h>
+#include <irq.h>
+#include <hwregs/intr_vect.h>
+#include <hwregs/intr_vect_defs.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
-#include <asm/arch/hwregs/mmu_defs_asm.h>
-#include <asm/arch/hwregs/supp_reg.h>
+#include <hwregs/asm/mmu_defs_asm.h>
+#include <hwregs/supp_reg.h>
#include <asm/atomic.h>
#include <linux/err.h>
@@ -20,6 +21,7 @@
#define IPI_SCHEDULE 1
#define IPI_CALL 2
#define IPI_FLUSH_TLB 4
+#define IPI_BOOT 8
#define FLUSH_ALL (void*)0xffffffff
@@ -30,6 +32,8 @@ spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED};
cpumask_t cpu_online_map = CPU_MASK_NONE;
EXPORT_SYMBOL(cpu_online_map);
cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
+cpumask_t cpu_possible_map;
+EXPORT_SYMBOL(cpu_possible_map);
EXPORT_SYMBOL(phys_cpu_present_map);
/* Variables used during SMP boot */
@@ -55,13 +59,12 @@ static unsigned long flush_addr;
extern int setup_irq(int, struct irqaction *);
/* Mode registers */
-static unsigned long irq_regs[NR_CPUS] =
-{
+static unsigned long irq_regs[NR_CPUS] = {
regi_irq,
regi_irq2
};
-static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id);
static int send_ipi(int vector, int wait, cpumask_t cpu_mask);
static struct irqaction irq_ipi = {
.handler = crisv32_ipi_interrupt,
@@ -101,6 +104,7 @@ void __devinit smp_prepare_boot_cpu(void)
cpu_set(0, cpu_online_map);
cpu_set(0, phys_cpu_present_map);
+ cpu_set(0, cpu_possible_map);
}
void __init smp_cpus_done(unsigned int max_cpus)
@@ -113,6 +117,7 @@ smp_boot_one_cpu(int cpuid)
{
unsigned timeout;
struct task_struct *idle;
+ cpumask_t cpu_mask = CPU_MASK_NONE;
idle = fork_idle(cpuid);
if (IS_ERR(idle))
@@ -124,6 +129,12 @@ smp_boot_one_cpu(int cpuid)
smp_init_current_idle_thread = task_thread_info(idle);
cpu_now_booting = cpuid;
+ /* Kick it */
+ cpu_set(cpuid, cpu_online_map);
+ cpu_set(cpuid, cpu_mask);
+ send_ipi(IPI_BOOT, 0, cpu_mask);
+ cpu_clear(cpuid, cpu_online_map);
+
/* Wait for CPU to come online */
for (timeout = 0; timeout < 10000; timeout++) {
if(cpu_online(cpuid)) {
@@ -165,7 +176,7 @@ void __init smp_callin(void)
/* Enable IRQ and idle */
REG_WR(intr_vect, irq_regs[cpu], rw_mask, vect_mask);
unmask_irq(IPI_INTR_VECT);
- unmask_irq(TIMER_INTR_VECT);
+ unmask_irq(TIMER0_INTR_VECT);
preempt_disable();
local_irq_enable();
@@ -328,7 +339,7 @@ int smp_call_function(void (*func)(void *info), void *info,
return ret;
}
-irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id)
{
void (*func) (void *info) = call_data->func;
void *info = call_data->info;
diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c
index 2f7e8e200f2..3a13dd6e0a9 100644
--- a/arch/cris/arch-v32/kernel/time.c
+++ b/arch/cris/arch-v32/kernel/time.c
@@ -1,8 +1,7 @@
-/* $Id: time.c,v 1.19 2005/04/29 05:40:09 starvik Exp $
- *
+/*
* linux/arch/cris/arch-v32/kernel/time.c
*
- * Copyright (C) 2003 Axis Communications AB
+ * Copyright (C) 2003-2007 Axis Communications AB
*
*/
@@ -14,28 +13,34 @@
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/threads.h>
+#include <linux/cpufreq.h>
#include <asm/types.h>
#include <asm/signal.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/rtc.h>
#include <asm/irq.h>
-
-#include <asm/arch/hwregs/reg_map.h>
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/timer_defs.h>
-#include <asm/arch/hwregs/intr_vect_defs.h>
+#include <asm/irq_regs.h>
+
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/timer_defs.h>
+#include <hwregs/intr_vect_defs.h>
+#ifdef CONFIG_CRIS_MACH_ARTPEC3
+#include <hwregs/clkgen_defs.h>
+#endif
/* Watchdog defines */
-#define ETRAX_WD_KEY_MASK 0x7F /* key is 7 bit */
-#define ETRAX_WD_HZ 763 /* watchdog counts at 763 Hz */
-#define ETRAX_WD_CNT ((2*ETRAX_WD_HZ)/HZ + 1) /* Number of 763 counts before watchdog bites */
+#define ETRAX_WD_KEY_MASK 0x7F /* key is 7 bit */
+#define ETRAX_WD_HZ 763 /* watchdog counts at 763 Hz */
+/* Number of 763 counts before watchdog bites */
+#define ETRAX_WD_CNT ((2*ETRAX_WD_HZ)/HZ + 1)
unsigned long timer_regs[NR_CPUS] =
{
- regi_timer,
+ regi_timer0,
#ifdef CONFIG_SMP
- regi_timer2
+ regi_timer2
#endif
};
@@ -44,12 +49,22 @@ extern int set_rtc_mmss(unsigned long nowtime);
extern int setup_irq(int, struct irqaction *);
extern int have_rtc;
+#ifdef CONFIG_CPU_FREQ
+static int
+cris_time_freq_notifier(struct notifier_block *nb, unsigned long val,
+ void *data);
+
+static struct notifier_block cris_time_freq_notifier_block = {
+ .notifier_call = cris_time_freq_notifier,
+};
+#endif
+
unsigned long get_ns_in_jiffie(void)
{
reg_timer_r_tmr0_data data;
unsigned long ns;
- data = REG_RD(timer, regi_timer, r_tmr0_data);
+ data = REG_RD(timer, regi_timer0, r_tmr0_data);
ns = (TIMER0_DIV - data) * 10;
return ns;
}
@@ -59,31 +74,27 @@ unsigned long do_slow_gettimeoffset(void)
unsigned long count;
unsigned long usec_count = 0;
- static unsigned long count_p = TIMER0_DIV;/* for the first call after boot */
+ /* For the first call after boot */
+ static unsigned long count_p = TIMER0_DIV;
static unsigned long jiffies_p = 0;
- /*
- * cache volatile jiffies temporarily; we have IRQs turned off.
- */
+ /* Cache volatile jiffies temporarily; we have IRQs turned off. */
unsigned long jiffies_t;
/* The timer interrupt comes from Etrax timer 0. In order to get
* better precision, we check the current value. It might have
- * underflowed already though.
- */
+ * underflowed already though. */
+ count = REG_RD(timer, regi_timer0, r_tmr0_data);
+ jiffies_t = jiffies;
- count = REG_RD(timer, regi_timer, r_tmr0_data);
- jiffies_t = jiffies;
-
- /*
- * avoiding timer inconsistencies (they are rare, but they happen)...
- * there are one problem that must be avoided here:
- * 1. the timer counter underflows
+ /* Avoiding timer inconsistencies (they are rare, but they happen)
+ * There is one problem that must be avoided here:
+ * 1. the timer counter underflows
*/
if( jiffies_t == jiffies_p ) {
if( count > count_p ) {
- /* Timer wrapped, use new count and prescale
- * increase the time corresponding to one jiffie
+ /* Timer wrapped, use new count and prescale.
+ * Increase the time corresponding to one jiffy.
*/
usec_count = 1000000/HZ;
}
@@ -106,17 +117,15 @@ unsigned long do_slow_gettimeoffset(void)
*/
/* This gives us 1.3 ms to do something useful when the NMI comes */
-/* right now, starting the watchdog is the same as resetting it */
+/* Right now, starting the watchdog is the same as resetting it */
#define start_watchdog reset_watchdog
#if defined(CONFIG_ETRAX_WATCHDOG)
static short int watchdog_key = 42; /* arbitrary 7 bit number */
#endif
-/* number of pages to consider "out of memory". it is normal that the memory
- * is used though, so put this really low.
- */
-
+/* Number of pages to consider "out of memory". It is normal that the memory
+ * is used though, so set this really low. */
#define WATCHDOG_MIN_FREE_PAGES 8
void
@@ -125,14 +134,15 @@ reset_watchdog(void)
#if defined(CONFIG_ETRAX_WATCHDOG)
reg_timer_rw_wd_ctrl wd_ctrl = { 0 };
- /* only keep watchdog happy as long as we have memory left! */
+ /* Only keep watchdog happy as long as we have memory left! */
if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) {
- /* reset the watchdog with the inverse of the old key */
- watchdog_key ^= ETRAX_WD_KEY_MASK; /* invert key, which is 7 bits */
+ /* Reset the watchdog with the inverse of the old key */
+ /* Invert key, which is 7 bits */
+ watchdog_key ^= ETRAX_WD_KEY_MASK;
wd_ctrl.cnt = ETRAX_WD_CNT;
wd_ctrl.cmd = regk_timer_start;
wd_ctrl.key = watchdog_key;
- REG_WR(timer, regi_timer, rw_wd_ctrl, wd_ctrl);
+ REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl);
}
#endif
}
@@ -148,7 +158,7 @@ stop_watchdog(void)
wd_ctrl.cnt = ETRAX_WD_CNT;
wd_ctrl.cmd = regk_timer_stop;
wd_ctrl.key = watchdog_key;
- REG_WR(timer, regi_timer, rw_wd_ctrl, wd_ctrl);
+ REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl);
#endif
}
@@ -160,17 +170,28 @@ handle_watchdog_bite(struct pt_regs* regs)
#if defined(CONFIG_ETRAX_WATCHDOG)
extern int cause_of_death;
- raw_printk("Watchdog bite\n");
+ oops_in_progress = 1;
+ printk(KERN_WARNING "Watchdog bite\n");
/* Check if forced restart or unexpected watchdog */
if (cause_of_death == 0xbedead) {
+#ifdef CONFIG_CRIS_MACH_ARTPEC3
+ /* There is a bug in Artpec-3 (voodoo TR 78) that requires
+ * us to go to lower frequency for the reset to be reliable
+ */
+ reg_clkgen_rw_clk_ctrl ctrl =
+ REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
+ ctrl.pll = 0;
+ REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, ctrl);
+#endif
while(1);
}
- /* Unexpected watchdog, stop the watchdog and dump registers*/
+ /* Unexpected watchdog, stop the watchdog and dump registers. */
stop_watchdog();
- raw_printk("Oops: bitten by watchdog\n");
- show_registers(regs);
+ printk(KERN_WARNING "Oops: bitten by watchdog\n");
+ show_registers(regs);
+ oops_in_progress = 0;
#ifndef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
reset_watchdog();
#endif
@@ -178,21 +199,19 @@ handle_watchdog_bite(struct pt_regs* regs)
#endif
}
-/* last time the cmos clock got updated */
+/* Last time the cmos clock got updated. */
static long last_rtc_update = 0;
/*
* timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "do_timer()" routine every clocktick.
*/
-
-//static unsigned short myjiff; /* used by our debug routine print_timestamp */
-
extern void cris_do_profile(struct pt_regs *regs);
static inline irqreturn_t
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+timer_interrupt(int irq, void *dev_id)
{
+ struct pt_regs *regs = get_irq_regs();
int cpu = smp_processor_id();
reg_timer_r_masked_intr masked_intr;
reg_timer_rw_ack_intr ack_intr = { 0 };
@@ -202,11 +221,11 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (!masked_intr.tmr0)
return IRQ_NONE;
- /* acknowledge the timer irq */
+ /* Acknowledge the timer irq. */
ack_intr.tmr0 = 1;
REG_WR(timer, timer_regs[cpu], rw_ack_intr, ack_intr);
- /* reset watchdog otherwise it resets us! */
+ /* Reset watchdog otherwise it resets us! */
reset_watchdog();
/* Update statistics. */
@@ -218,7 +237,7 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (cpu != 0)
return IRQ_HANDLED;
- /* call the real timer interrupt handler */
+ /* Call the real timer interrupt handler */
do_timer(1);
/*
@@ -236,17 +255,17 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (set_rtc_mmss(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
- last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ /* Do it again in 60 s */
+ last_rtc_update = xtime.tv_sec - 600;
}
return IRQ_HANDLED;
}
-/* timer is IRQF_SHARED so drivers can add stuff to the timer irq chain
- * it needs to be IRQF_DISABLED to make the jiffies update work properly
+/* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain.
+ * It needs to be IRQF_DISABLED to make the jiffies update work properly.
*/
-
-static struct irqaction irq_timer = {
- .mask = timer_interrupt,
+static struct irqaction irq_timer = {
+ .handler = timer_interrupt,
.flags = IRQF_SHARED | IRQF_DISABLED,
.mask = CPU_MASK_NONE,
.name = "timer"
@@ -256,27 +275,27 @@ void __init
cris_timer_init(void)
{
int cpu = smp_processor_id();
- reg_timer_rw_tmr0_ctrl tmr0_ctrl = { 0 };
- reg_timer_rw_tmr0_div tmr0_div = TIMER0_DIV;
+ reg_timer_rw_tmr0_ctrl tmr0_ctrl = { 0 };
+ reg_timer_rw_tmr0_div tmr0_div = TIMER0_DIV;
reg_timer_rw_intr_mask timer_intr_mask;
- /* Setup the etrax timers
+ /* Setup the etrax timers.
* Base frequency is 100MHz, divider 1000000 -> 100 HZ
* We use timer0, so timer1 is free.
* The trig timer is used by the fasttimer API if enabled.
*/
- tmr0_ctrl.op = regk_timer_ld;
+ tmr0_ctrl.op = regk_timer_ld;
tmr0_ctrl.freq = regk_timer_f100;
- REG_WR(timer, timer_regs[cpu], rw_tmr0_div, tmr0_div);
- REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Load */
- tmr0_ctrl.op = regk_timer_run;
- REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Start */
-
- /* enable the timer irq */
- timer_intr_mask = REG_RD(timer, timer_regs[cpu], rw_intr_mask);
- timer_intr_mask.tmr0 = 1;
- REG_WR(timer, timer_regs[cpu], rw_intr_mask, timer_intr_mask);
+ REG_WR(timer, timer_regs[cpu], rw_tmr0_div, tmr0_div);
+ REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Load */
+ tmr0_ctrl.op = regk_timer_run;
+ REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Start */
+
+ /* Enable the timer irq. */
+ timer_intr_mask = REG_RD(timer, timer_regs[cpu], rw_intr_mask);
+ timer_intr_mask.tmr0 = 1;
+ REG_WR(timer, timer_regs[cpu], rw_intr_mask, timer_intr_mask);
}
void __init
@@ -284,7 +303,7 @@ time_init(void)
{
reg_intr_vect_rw_mask intr_mask;
- /* probe for the RTC and read it if it exists
+ /* Probe for the RTC and read it if it exists.
* Before the RTC can be probed the loops_per_usec variable needs
* to be initialized to make usleep work. A better value for
* loops_per_usec is calculated by the kernel later once the
@@ -293,52 +312,74 @@ time_init(void)
loops_per_usec = 50;
if(RTC_INIT() < 0) {
- /* no RTC, start at 1980 */
+ /* No RTC, start at 1980 */
xtime.tv_sec = 0;
xtime.tv_nsec = 0;
have_rtc = 0;
} else {
- /* get the current time */
+ /* Get the current time */
have_rtc = 1;
update_xtime_from_cmos();
}
/*
- * Initialize wall_to_monotonic such that adding it to xtime will yield zero, the
- * tv_nsec field must be normalized (i.e., 0 <= nsec < NSEC_PER_SEC).
+ * Initialize wall_to_monotonic such that adding it to
+ * xtime will yield zero, the tv_nsec field must be normalized
+ * (i.e., 0 <= nsec < NSEC_PER_SEC).
*/
set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
- /* Start CPU local timer */
+ /* Start CPU local timer. */
cris_timer_init();
- /* enable the timer irq in global config */
- intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);
- intr_mask.timer = 1;
- REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
-
- /* now actually register the timer irq handler that calls timer_interrupt() */
+ /* Enable the timer irq in global config. */
+ intr_mask = REG_RD_VECT(intr_vect, regi_irq, rw_mask, 1);
+ intr_mask.timer0 = 1;
+ REG_WR_VECT(intr_vect, regi_irq, rw_mask, 1, intr_mask);
- setup_irq(TIMER_INTR_VECT, &irq_timer);
+ /* Now actually register the timer irq handler that calls
+ * timer_interrupt(). */
+ setup_irq(TIMER0_INTR_VECT, &irq_timer);
- /* enable watchdog if we should use one */
+ /* Enable watchdog if we should use one. */
#if defined(CONFIG_ETRAX_WATCHDOG)
- printk("Enabling watchdog...\n");
+ printk(KERN_INFO "Enabling watchdog...\n");
start_watchdog();
/* If we use the hardware watchdog, we want to trap it as an NMI
- and dump registers before it resets us. For this to happen, we
- must set the "m" NMI enable flag (which once set, is unset only
- when an NMI is taken).
-
- The same goes for the external NMI, but that doesn't have any
- driver or infrastructure support yet. */
- {
- unsigned long flags;
- local_save_flags(flags);
- flags |= (1<<30); /* NMI M flag is at bit 30 */
- local_irq_restore(flags);
- }
+ * and dump registers before it resets us. For this to happen, we
+ * must set the "m" NMI enable flag (which once set, is unset only
+ * when an NMI is taken). */
+ {
+ unsigned long flags;
+ local_save_flags(flags);
+ flags |= (1<<30); /* NMI M flag is at bit 30 */
+ local_irq_restore(flags);
+ }
+#endif
+
+#ifdef CONFIG_CPU_FREQ
+ cpufreq_register_notifier(&cris_time_freq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
#endif
}
+
+#ifdef CONFIG_CPU_FREQ
+static int
+cris_time_freq_notifier(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ struct cpufreq_freqs *freqs = data;
+ if (val == CPUFREQ_POSTCHANGE) {
+ reg_timer_r_tmr0_data data;
+ reg_timer_rw_tmr0_div div = (freqs->new * 500) / HZ;
+ do {
+ data = REG_RD(timer, timer_regs[freqs->cpu],
+ r_tmr0_data);
+ } while (data > 20);
+ REG_WR(timer, timer_regs[freqs->cpu], rw_tmr0_div, div);
+ }
+ return 0;
+}
+#endif
diff --git a/arch/cris/arch-v32/kernel/traps.c b/arch/cris/arch-v32/kernel/traps.c
index 17fd3dbd1c8..9003e382cad 100644
--- a/arch/cris/arch-v32/kernel/traps.c
+++ b/arch/cris/arch-v32/kernel/traps.c
@@ -1,50 +1,45 @@
/*
- * Copyright (C) 2003, Axis Communications AB.
+ * Copyright (C) 2003-2006, Axis Communications AB.
*/
#include <linux/ptrace.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
-
-#include <asm/arch/hwregs/supp_reg.h>
-
-extern void reset_watchdog(void);
-extern void stop_watchdog(void);
-
-extern int raw_printk(const char *fmt, ...);
+#include <hwregs/supp_reg.h>
+#include <hwregs/intr_vect_defs.h>
+#include <asm/irq.h>
void
show_registers(struct pt_regs *regs)
{
/*
* It's possible to use either the USP register or current->thread.usp.
- * USP might not correspond to the current proccess for all cases this
+ * USP might not correspond to the current process for all cases this
* function is called, and current->thread.usp isn't up to date for the
- * current proccess. Experience shows that using USP is the way to go.
+ * current process. Experience shows that using USP is the way to go.
*/
- unsigned long usp;
+ unsigned long usp = rdusp();
unsigned long d_mmu_cause;
unsigned long i_mmu_cause;
- usp = rdusp();
+ printk("CPU: %d\n", smp_processor_id());
- raw_printk("CPU: %d\n", smp_processor_id());
+ printk("ERP: %08lx SRP: %08lx CCS: %08lx USP: %08lx MOF: %08lx\n",
+ regs->erp, regs->srp, regs->ccs, usp, regs->mof);
- raw_printk("ERP: %08lx SRP: %08lx CCS: %08lx USP: %08lx MOF: %08lx\n",
- regs->erp, regs->srp, regs->ccs, usp, regs->mof);
+ printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
+ regs->r0, regs->r1, regs->r2, regs->r3);
- raw_printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
- regs->r0, regs->r1, regs->r2, regs->r3);
+ printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
+ regs->r4, regs->r5, regs->r6, regs->r7);
- raw_printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
- regs->r4, regs->r5, regs->r6, regs->r7);
+ printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
+ regs->r8, regs->r9, regs->r10, regs->r11);
- raw_printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
- regs->r8, regs->r9, regs->r10, regs->r11);
+ printk("r12: %08lx r13: %08lx oR10: %08lx acr: %08lx\n",
+ regs->r12, regs->r13, regs->orig_r10, regs->acr);
- raw_printk("r12: %08lx r13: %08lx oR10: %08lx acr: %08lx\n",
- regs->r12, regs->r13, regs->orig_r10, regs->acr);
-
- raw_printk("sp: %08lx\n", regs);
+ printk(" sp: %08lx\n", (unsigned long)regs);
SUPP_BANK_SEL(BANK_IM);
SUPP_REG_RD(RW_MM_CAUSE, i_mmu_cause);
@@ -52,18 +47,20 @@ show_registers(struct pt_regs *regs)
SUPP_BANK_SEL(BANK_DM);
SUPP_REG_RD(RW_MM_CAUSE, d_mmu_cause);
- raw_printk(" Data MMU Cause: %08lx\n", d_mmu_cause);
- raw_printk("Instruction MMU Cause: %08lx\n", i_mmu_cause);
+ printk(" Data MMU Cause: %08lx\n", d_mmu_cause);
+ printk("Instruction MMU Cause: %08lx\n", i_mmu_cause);
- raw_printk("Process %s (pid: %d, stackpage: %08lx)\n",
- current->comm, current->pid, (unsigned long) current);
+ printk("Process %s (pid: %d, stackpage=%08lx)\n",
+ current->comm, current->pid, (unsigned long)current);
- /* Show additional info if in kernel-mode. */
+ /*
+ * When in-kernel, we also print out the stack and code at the
+ * time of the fault..
+ */
if (!user_mode(regs)) {
int i;
- unsigned char c;
- show_stack(NULL, (unsigned long *) usp);
+ show_stack(NULL, (unsigned long *)usp);
/*
* If the previous stack-dump wasn't a kernel one, dump the
@@ -72,7 +69,7 @@ show_registers(struct pt_regs *regs)
if (usp != 0)
show_stack(NULL, NULL);
- raw_printk("\nCode: ");
+ printk("\nCode: ");
if (regs->erp < PAGE_OFFSET)
goto bad_value;
@@ -84,76 +81,115 @@ show_registers(struct pt_regs *regs)
* instruction decoding should be in sync at the interesting
* point, but small enough to fit on a row. The regs->erp
* location is pointed out in a ksymoops-friendly way by
- * wrapping the byte for that address in parenthesis.
+ * wrapping the byte for that address in parenthesises.
*/
for (i = -12; i < 12; i++) {
- if (__get_user(c, &((unsigned char *) regs->erp)[i])) {
+ unsigned char c;
+
+ if (__get_user(c, &((unsigned char *)regs->erp)[i])) {
bad_value:
- raw_printk(" Bad IP value.");
+ printk(" Bad IP value.");
break;
}
if (i == 0)
- raw_printk("(%02x) ", c);
+ printk("(%02x) ", c);
else
- raw_printk("%02x ", c);
+ printk("%02x ", c);
}
-
- raw_printk("\n");
+ printk("\n");
}
}
-/*
- * This gets called from entry.S when the watchdog has bitten. Show something
- * similar to an Oops dump, and if the kernel is configured to be a nice doggy;
- * halt instead of reboot.
- */
void
-watchdog_bite_hook(struct pt_regs *regs)
+arch_enable_nmi(void)
{
-#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
- local_irq_disable();
- stop_watchdog();
- show_registers(regs);
+ unsigned long flags;
- while (1)
- ; /* Do nothing. */
-#else
- show_registers(regs);
-#endif
+ local_save_flags(flags);
+ flags |= (1 << 30); /* NMI M flag is at bit 30 */
+ local_irq_restore(flags);
}
-/* This is normally the Oops function. */
-void
-die_if_kernel(const char *str, struct pt_regs *regs, long err)
+extern void (*nmi_handler)(struct pt_regs *);
+void handle_nmi(struct pt_regs *regs)
{
- if (user_mode(regs))
- return;
+#ifdef CONFIG_ETRAXFS
+ reg_intr_vect_r_nmi r;
+#endif
-#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
- /*
- * This printout might take too long and could trigger
- * the watchdog normally. If NICE_DOGGY is set, simply
- * stop the watchdog during the printout.
- */
- stop_watchdog();
+ if (nmi_handler)
+ nmi_handler(regs);
+
+#ifdef CONFIG_ETRAXFS
+ /* Wait until nmi is no longer active. */
+ do {
+ r = REG_RD(intr_vect, regi_irq, r_nmi);
+ } while (r.ext == regk_intr_vect_on);
#endif
+}
- raw_printk("%s: %04lx\n", str, err & 0xffff);
- show_registers(regs);
+#ifdef CONFIG_BUG
+extern void die_if_kernel(const char *str, struct pt_regs *regs, long err);
-#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
- reset_watchdog();
-#endif
+/* Copy of the regs at BUG() time. */
+struct pt_regs BUG_regs;
- do_exit(SIGSEGV);
+void do_BUG(char *file, unsigned int line)
+{
+ printk("kernel BUG at %s:%d!\n", file, line);
+ die_if_kernel("Oops", &BUG_regs, 0);
}
+EXPORT_SYMBOL(do_BUG);
-void arch_enable_nmi(void)
+void fixup_BUG(struct pt_regs *regs)
{
- unsigned long flags;
- local_save_flags(flags);
- flags |= (1<<30); /* NMI M flag is at bit 30 */
- local_irq_restore(flags);
+ BUG_regs = *regs;
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+ /*
+ * Fixup the BUG arguments through exception handlers.
+ */
+ {
+ const struct exception_table_entry *fixup;
+
+ /*
+ * ERP points at the "break 14" + 2, compensate for the 2
+ * bytes.
+ */
+ fixup = search_exception_tables(instruction_pointer(regs) - 2);
+ if (fixup) {
+ /* Adjust the instruction pointer in the stackframe. */
+ instruction_pointer(regs) = fixup->fixup;
+ arch_fixup(regs);
+ }
+ }
+#else
+ /* Dont try to lookup the filename + line, just dump regs. */
+ do_BUG("unknown", 0);
+#endif
}
+
+/*
+ * Break 14 handler. Save regs and jump into the fixup_BUG.
+ */
+__asm__ ( ".text\n\t"
+ ".global breakh_BUG\n\t"
+ "breakh_BUG:\n\t"
+ SAVE_ALL
+ KGDB_FIXUP
+ "move.d $sp, $r10\n\t"
+ "jsr fixup_BUG\n\t"
+ "nop\n\t"
+ "jump ret_from_intr\n\t"
+ "nop\n\t");
+
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+void
+handle_BUG(struct pt_regs *regs)
+{
+}
+#endif
+#endif
diff --git a/arch/cris/arch-v32/kernel/vcs_hook.c b/arch/cris/arch-v32/kernel/vcs_hook.c
deleted file mode 100644
index 64d71c54c22..00000000000
--- a/arch/cris/arch-v32/kernel/vcs_hook.c
+++ /dev/null
@@ -1,96 +0,0 @@
-// $Id: vcs_hook.c,v 1.2 2003/08/12 12:01:06 starvik Exp $
-//
-// Call simulator hook. This is the part running in the
-// simulated program.
-//
-
-#include "vcs_hook.h"
-#include <stdarg.h>
-#include <asm/arch-v32/hwregs/reg_map.h>
-#include <asm/arch-v32/hwregs/intr_vect_defs.h>
-
-#define HOOK_TRIG_ADDR 0xb7000000 /* hook cvlog model reg address */
-#define HOOK_MEM_BASE_ADDR 0xa0000000 /* csp4 (shared mem) base addr */
-
-#define HOOK_DATA(offset) ((unsigned*) HOOK_MEM_BASE_ADDR)[offset]
-#define VHOOK_DATA(offset) ((volatile unsigned*) HOOK_MEM_BASE_ADDR)[offset]
-#define HOOK_TRIG(funcid) do { *((unsigned *) HOOK_TRIG_ADDR) = funcid; } while(0)
-#define HOOK_DATA_BYTE(offset) ((unsigned char*) HOOK_MEM_BASE_ADDR)[offset]
-
-
-// ------------------------------------------------------------------ hook_call
-int hook_call( unsigned id, unsigned pcnt, ...) {
- va_list ap;
- unsigned i;
- unsigned ret;
-#ifdef USING_SOS
- PREEMPT_OFF_SAVE();
-#endif
-
- // pass parameters
- HOOK_DATA(0) = id;
-
- /* Have to make hook_print_str a special case since we call with a
- parameter of byte type. Should perhaps be a separate
- hook_call. */
-
- if (id == hook_print_str) {
- int i;
- char *str;
-
- HOOK_DATA(1) = pcnt;
-
- va_start(ap, pcnt);
- str = (char*)va_arg(ap,unsigned);
-
- for (i=0; i!=pcnt; i++) {
- HOOK_DATA_BYTE(8+i) = str[i];
- }
- HOOK_DATA_BYTE(8+i) = 0; /* null byte */
- }
- else {
- va_start(ap, pcnt);
- for( i = 1; i <= pcnt; i++ ) HOOK_DATA(i) = va_arg(ap,unsigned);
- va_end(ap);
- }
-
- // read from mem to make sure data has propagated to memory before trigging
- *((volatile unsigned*) HOOK_MEM_BASE_ADDR);
-
- // trigger hook
- HOOK_TRIG(id);
-
- // wait for call to finish
- while( VHOOK_DATA(0) > 0 ) {}
-
- // extract return value
-
- ret = VHOOK_DATA(1);
-
-#ifdef USING_SOS
- PREEMPT_RESTORE();
-#endif
- return ret;
-}
-
-unsigned
-hook_buf(unsigned i)
-{
- return (HOOK_DATA(i));
-}
-
-void print_str( const char *str ) {
- int i;
- for (i=1; str[i]; i++); /* find null at end of string */
- hook_call(hook_print_str, i, str);
-}
-
-// --------------------------------------------------------------- CPU_KICK_DOG
-void CPU_KICK_DOG(void) {
- (void) hook_call( hook_kick_dog, 0 );
-}
-
-// ------------------------------------------------------- CPU_WATCHDOG_TIMEOUT
-void CPU_WATCHDOG_TIMEOUT( unsigned t ) {
- (void) hook_call( hook_dog_timeout, 1, t );
-}
diff --git a/arch/cris/arch-v32/lib/Makefile b/arch/cris/arch-v32/lib/Makefile
index 05b3ec6978d..eb4aad1f115 100644
--- a/arch/cris/arch-v32/lib/Makefile
+++ b/arch/cris/arch-v32/lib/Makefile
@@ -2,5 +2,6 @@
# Makefile for Etrax-specific library files..
#
-lib-y = checksum.o checksumcopy.o string.o usercopy.o memset.o csumcpfruser.o spinlock.o
+lib-y = checksum.o checksumcopy.o string.o usercopy.o memset.o \
+ csumcpfruser.o spinlock.o delay.o
diff --git a/arch/cris/arch-v32/lib/checksum.S b/arch/cris/arch-v32/lib/checksum.S
index 32e66181b82..87f3fd71ab1 100644
--- a/arch/cris/arch-v32/lib/checksum.S
+++ b/arch/cris/arch-v32/lib/checksum.S
@@ -1,6 +1,6 @@
/*
* A fast checksum routine using movem
- * Copyright (c) 1998-2001, 2003 Axis Communications AB
+ * Copyright (c) 1998-2007 Axis Communications AB
*
* csum_partial(const unsigned char * buff, int len, unsigned int sum)
*/
@@ -12,30 +12,23 @@ csum_partial:
;; r11 - length
;; r12 - checksum
- ;; check for breakeven length between movem and normal word looping versions
- ;; we also do _NOT_ want to compute a checksum over more than the
- ;; actual length when length < 40
-
- cmpu.w 80,$r11
- blo _word_loop
- nop
-
- ;; need to save the registers we use below in the movem loop
- ;; this overhead is why we have a check above for breakeven length
- ;; only r0 - r8 have to be saved, the other ones are clobber-able
- ;; according to the ABI
+ ;; Optimized for large packets
+ subq 10*4, $r11
+ blt _word_loop
+ move.d $r11, $acr
subq 9*4,$sp
- subq 10*4,$r11 ; update length for the first loop
+ clearf c
movem $r8,[$sp]
;; do a movem checksum
_mloop: movem [$r10+],$r9 ; read 10 longwords
-
+ ;; Loop count without touching the c flag.
+ addoq -10*4, $acr, $acr
;; perform dword checksumming on the 10 longwords
- add.d $r0,$r12
+ addc $r0,$r12
addc $r1,$r12
addc $r2,$r12
addc $r3,$r12
@@ -46,60 +39,41 @@ _mloop: movem [$r10+],$r9 ; read 10 longwords
addc $r8,$r12
addc $r9,$r12
- ;; fold the carry into the checksum, to avoid having to loop the carry
- ;; back into the top
-
- addc 0,$r12
- addc 0,$r12 ; do it again, since we might have generated a carry
-
- subq 10*4,$r11
- bge _mloop
- nop
-
- addq 10*4,$r11 ; compensate for last loop underflowing length
+ ;; test $acr without trashing carry.
+ move.d $acr, $acr
+ bpl _mloop
+ ;; r11 <= acr is not really needed in the mloop, just using the dslot
+ ;; to prepare for what is needed after mloop.
+ move.d $acr, $r11
+ ;; fold the last carry into r13
+ addc 0, $r12
movem [$sp+],$r8 ; restore regs
_word_loop:
- ;; only fold if there is anything to fold.
-
- cmpq 0,$r12
- beq _no_fold
-
- ;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below.
- ;; r9 and r13 can be used as temporaries.
+ addq 10*4,$r11 ; compensate for last loop underflowing length
moveq -1,$r9 ; put 0xffff in r9, faster than move.d 0xffff,r9
lsrq 16,$r9
move.d $r12,$r13
lsrq 16,$r13 ; r13 = checksum >> 16
- and.d $r9,$r12 ; checksum = checksum & 0xffff
- add.d $r13,$r12 ; checksum += r13
- move.d $r12,$r13 ; do the same again, maybe we got a carry last add
- lsrq 16,$r13
- and.d $r9,$r12
- add.d $r13,$r12
+ and.d $r9,$r12 ; checksum = checksum & 0xffff
_no_fold:
- cmpq 2,$r11
+ subq 2,$r11
blt _no_words
- nop
+ add.d $r13,$r12 ; checksum += r13
;; checksum the rest of the words
-
- subq 2,$r11
-
_wloop: subq 2,$r11
bge _wloop
addu.w [$r10+],$r12
- addq 2,$r11
-
_no_words:
+ addq 2,$r11
;; see if we have one odd byte more
- cmpq 1,$r11
- beq _do_byte
+ bne _do_byte
nop
ret
move.d $r12,$r10
diff --git a/arch/cris/arch-v32/lib/checksumcopy.S b/arch/cris/arch-v32/lib/checksumcopy.S
index 9303ccbadc6..21aabe91489 100644
--- a/arch/cris/arch-v32/lib/checksumcopy.S
+++ b/arch/cris/arch-v32/lib/checksumcopy.S
@@ -1,6 +1,6 @@
/*
* A fast checksum+copy routine using movem
- * Copyright (c) 1998, 2001, 2003 Axis Communications AB
+ * Copyright (c) 1998-2007 Axis Communications AB
*
* Authors: Bjorn Wesen
*
@@ -16,32 +16,23 @@ csum_partial_copy_nocheck:
;; r12 - length
;; r13 - checksum
- ;; check for breakeven length between movem and normal word looping versions
- ;; we also do _NOT_ want to compute a checksum over more than the
- ;; actual length when length < 40
-
- cmpu.w 80,$r12
- blo _word_loop
- nop
-
- ;; need to save the registers we use below in the movem loop
- ;; this overhead is why we have a check above for breakeven length
- ;; only r0 - r8 have to be saved, the other ones are clobber-able
- ;; according to the ABI
+ ;; Optimized for large packets
+ subq 10*4, $r12
+ blt _word_loop
+ move.d $r12, $acr
subq 9*4,$sp
- subq 10*4,$r12 ; update length for the first loop
+ clearf c
movem $r8,[$sp]
;; do a movem copy and checksum
-
1: ;; A failing userspace access (the read) will have this as PC.
_mloop: movem [$r10+],$r9 ; read 10 longwords
+ addoq -10*4, $acr, $acr ; loop counter in latency cycle
movem $r9,[$r11+] ; write 10 longwords
;; perform dword checksumming on the 10 longwords
-
- add.d $r0,$r13
+ addc $r0,$r13
addc $r1,$r13
addc $r2,$r13
addc $r3,$r13
@@ -52,47 +43,30 @@ _mloop: movem [$r10+],$r9 ; read 10 longwords
addc $r8,$r13
addc $r9,$r13
- ;; fold the carry into the checksum, to avoid having to loop the carry
- ;; back into the top
-
- addc 0,$r13
- addc 0,$r13 ; do it again, since we might have generated a carry
-
- subq 10*4,$r12
- bge _mloop
- nop
-
- addq 10*4,$r12 ; compensate for last loop underflowing length
+ ;; test $acr, without trashing carry.
+ move.d $acr, $acr
+ bpl _mloop
+ ;; r12 <= acr is needed after mloop and in the exception handlers.
+ move.d $acr, $r12
+ ;; fold the last carry into r13
+ addc 0, $r13
movem [$sp+],$r8 ; restore regs
_word_loop:
- ;; only fold if there is anything to fold.
-
- cmpq 0,$r13
- beq _no_fold
+ addq 10*4,$r12 ; compensate for last loop underflowing length
;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below
;; r9 can be used as temporary.
-
move.d $r13,$r9
lsrq 16,$r9 ; r0 = checksum >> 16
and.d 0xffff,$r13 ; checksum = checksum & 0xffff
- add.d $r9,$r13 ; checksum += r0
- move.d $r13,$r9 ; do the same again, maybe we got a carry last add
- lsrq 16,$r9
- and.d 0xffff,$r13
- add.d $r9,$r13
-_no_fold:
- cmpq 2,$r12
+ subq 2, $r12
blt _no_words
- nop
+ add.d $r9,$r13 ; checksum += r0
;; copy and checksum the rest of the words
-
- subq 2,$r12
-
2: ;; A failing userspace access for the read below will have this as PC.
_wloop: move.w [$r10+],$r9
addu.w $r9,$r13
@@ -100,12 +74,9 @@ _wloop: move.w [$r10+],$r9
bge _wloop
move.w $r9,[$r11+]
- addq 2,$r12
-
_no_words:
- ;; see if we have one odd byte more
- cmpq 1,$r12
- beq _do_byte
+ addq 2,$r12
+ bne _do_byte
nop
ret
move.d $r13,$r10
diff --git a/arch/cris/arch-v32/lib/delay.c b/arch/cris/arch-v32/lib/delay.c
new file mode 100644
index 00000000000..39f1ac9995b
--- /dev/null
+++ b/arch/cris/arch-v32/lib/delay.c
@@ -0,0 +1,28 @@
+/*
+ * Precise Delay Loops for ETRAX FS
+ *
+ * Copyright (C) 2006 Axis Communications AB.
+ *
+ */
+
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/timer_defs.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+/*
+ * On ETRAX FS, we can check the free-running read-only 100MHz timer
+ * getting 32-bit 10ns precision, theoretically good for 42.94967295
+ * seconds. Unsigned arithmetic and careful expression handles
+ * wrapping.
+ */
+
+void cris_delay10ns(u32 n10ns)
+{
+ u32 t0 = REG_RD(timer, regi_timer0, r_time);
+ while (REG_RD(timer, regi_timer0, r_time) - t0 < n10ns)
+ ;
+}
+EXPORT_SYMBOL(cris_delay10ns);
diff --git a/arch/cris/arch-v32/lib/memset.c b/arch/cris/arch-v32/lib/memset.c
index ffca1214674..c94ea9b3ec2 100644
--- a/arch/cris/arch-v32/lib/memset.c
+++ b/arch/cris/arch-v32/lib/memset.c
@@ -1,253 +1,259 @@
-/*#************************************************************************#*/
-/*#-------------------------------------------------------------------------*/
-/*# */
-/*# FUNCTION NAME: memset() */
-/*# */
-/*# PARAMETERS: void* dst; Destination address. */
-/*# int c; Value of byte to write. */
-/*# int len; Number of bytes to write. */
-/*# */
-/*# RETURNS: dst. */
-/*# */
-/*# DESCRIPTION: Sets the memory dst of length len bytes to c, as standard. */
-/*# Framework taken from memcpy. This routine is */
-/*# very sensitive to compiler changes in register allocation. */
-/*# Should really be rewritten to avoid this problem. */
-/*# */
-/*#-------------------------------------------------------------------------*/
-/*# */
-/*# HISTORY */
-/*# */
-/*# DATE NAME CHANGES */
-/*# ---- ---- ------- */
-/*# 990713 HP Tired of watching this function (or */
-/*# really, the nonoptimized generic */
-/*# implementation) take up 90% of simulator */
-/*# output. Measurements needed. */
-/*# */
-/*#-------------------------------------------------------------------------*/
-
-#include <linux/types.h>
-
-/* No, there's no macro saying 12*4, since it is "hard" to get it into
- the asm in a good way. Thus better to expose the problem everywhere.
- */
-
-/* Assuming 1 cycle per dword written or read (ok, not really true), and
- one per instruction, then 43+3*(n/48-1) <= 24+24*(n/48-1)
- so n >= 45.7; n >= 0.9; we win on the first full 48-byte block to set. */
-
-#define ZERO_BLOCK_SIZE (1*12*4)
-
-void *memset(void *pdst,
- int c,
- size_t plen)
+/* A memset for CRIS.
+ Copyright (C) 1999-2005 Axis Communications.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Neither the name of Axis Communications nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS
+ COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE. */
+
+/* FIXME: This file should really only be used for reference, as the
+ result is somewhat depending on gcc generating what we expect rather
+ than what we describe. An assembly file should be used instead. */
+
+/* Note the multiple occurrence of the expression "12*4", including the
+ asm. It is hard to get it into the asm in a good way. Thus better to
+ expose the problem everywhere: no macro. */
+
+/* Assuming one cycle per dword written or read (ok, not really true; the
+ world is not ideal), and one cycle per instruction, then 43+3*(n/48-1)
+ <= 24+24*(n/48-1) so n >= 45.7; n >= 0.9; we win on the first full
+ 48-byte block to set. */
+
+#define MEMSET_BY_BLOCK_THRESHOLD (1 * 48)
+
+/* No name ambiguities in this file. */
+__asm__ (".syntax no_register_prefix");
+
+void *memset(void *pdst, int c, unsigned int plen)
{
- /* Ok. Now we want the parameters put in special registers.
- Make sure the compiler is able to make something useful of this. */
+ /* Now we want the parameters in special registers. Make sure the
+ compiler does something usable with this. */
register char *return_dst __asm__ ("r10") = pdst;
register int n __asm__ ("r12") = plen;
register int lc __asm__ ("r11") = c;
- /* Most apps use memset sanely. Only those memsetting about 3..4
- bytes or less get penalized compared to the generic implementation
- - and that's not really sane use. */
+ /* Most apps use memset sanely. Memsetting about 3..4 bytes or less get
+ penalized here compared to the generic implementation. */
- /* Ugh. This is fragile at best. Check with newer GCC releases, if
- they compile cascaded "x |= x << 8" sanely! */
- __asm__("movu.b %0,$r13 \n\
- lslq 8,$r13 \n\
- move.b %0,$r13 \n\
- move.d $r13,%0 \n\
- lslq 16,$r13 \n\
- or.d $r13,%0"
- : "=r" (lc) : "0" (lc) : "r13");
+ /* This is fragile performancewise at best. Check with newer GCC
+ releases, if they compile cascaded "x |= x << 8" to sane code. */
+ __asm__("movu.b %0,r13 \n\
+ lslq 8,r13 \n\
+ move.b %0,r13 \n\
+ move.d r13,%0 \n\
+ lslq 16,r13 \n\
+ or.d r13,%0"
+ : "=r" (lc) /* Inputs. */
+ : "0" (lc) /* Outputs. */
+ : "r13"); /* Trash. */
{
register char *dst __asm__ ("r13") = pdst;
- /* This is NONPORTABLE, but since this whole routine is */
- /* grossly nonportable that doesn't matter. */
+ if (((unsigned long) pdst & 3) != 0
+ /* Oops! n = 0 must be a valid call, regardless of alignment. */
+ && n >= 3)
+ {
+ if ((unsigned long) dst & 1)
+ {
+ *dst = (char) lc;
+ n--;
+ dst++;
+ }
- if (((unsigned long) pdst & 3) != 0
- /* Oops! n=0 must be a legal call, regardless of alignment. */
- && n >= 3)
- {
- if ((unsigned long)dst & 1)
- {
- *dst = (char) lc;
- n--;
- dst++;
- }
-
- if ((unsigned long)dst & 2)
- {
- *(short *)dst = lc;
- n -= 2;
- dst += 2;
- }
- }
+ if ((unsigned long) dst & 2)
+ {
+ *(short *) dst = lc;
+ n -= 2;
+ dst += 2;
+ }
+ }
- /* Now the fun part. For the threshold value of this, check the equation
- above. */
- /* Decide which copying method to use. */
- if (n >= ZERO_BLOCK_SIZE)
- {
- /* For large copies we use 'movem' */
-
- /* It is not optimal to tell the compiler about clobbering any
- registers; that will move the saving/restoring of those registers
- to the function prologue/epilogue, and make non-movem sizes
- suboptimal.
-
- This method is not foolproof; it assumes that the "asm reg"
- declarations at the beginning of the function really are used
- here (beware: they may be moved to temporary registers).
- This way, we do not have to save/move the registers around into
- temporaries; we can safely use them straight away.
-
- If you want to check that the allocation was right; then
- check the equalities in the first comment. It should say
- "r13=r13, r12=r12, r11=r11" */
- __asm__ volatile (" \n\
- ;; Check that the register asm declaration got right. \n\
- ;; The GCC manual says it will work, but there *has* been bugs. \n\
- .ifnc %0-%1-%4,$r13-$r12-$r11 \n\
- .err \n\
- .endif \n\
+ /* Decide which setting method to use. */
+ if (n >= MEMSET_BY_BLOCK_THRESHOLD)
+ {
+ /* It is not optimal to tell the compiler about clobbering any
+ registers; that will move the saving/restoring of those registers
+ to the function prologue/epilogue, and make non-block sizes
+ suboptimal. */
+ __asm__ volatile
+ ("\
+ ;; GCC does promise correct register allocations, but let's \n\
+ ;; make sure it keeps its promises. \n\
+ .ifnc %0-%1-%4,$r13-$r12-$r11 \n\
+ .error \"GCC reg alloc bug: %0-%1-%4 != $r13-$r12-$r11\" \n\
+ .endif \n\
\n\
- ;; Save the registers we'll clobber in the movem process \n\
- ;; on the stack. Don't mention them to gcc, it will only be \n\
- ;; upset. \n\
- subq 11*4,$sp \n\
- movem $r10,[$sp] \n\
+ ;; Save the registers we'll clobber in the movem process \n\
+ ;; on the stack. Don't mention them to gcc, it will only be \n\
+ ;; upset. \n\
+ subq 11*4,sp \n\
+ movem r10,[sp] \n\
\n\
- move.d $r11,$r0 \n\
- move.d $r11,$r1 \n\
- move.d $r11,$r2 \n\
- move.d $r11,$r3 \n\
- move.d $r11,$r4 \n\
- move.d $r11,$r5 \n\
- move.d $r11,$r6 \n\
- move.d $r11,$r7 \n\
- move.d $r11,$r8 \n\
- move.d $r11,$r9 \n\
- move.d $r11,$r10 \n\
+ move.d r11,r0 \n\
+ move.d r11,r1 \n\
+ move.d r11,r2 \n\
+ move.d r11,r3 \n\
+ move.d r11,r4 \n\
+ move.d r11,r5 \n\
+ move.d r11,r6 \n\
+ move.d r11,r7 \n\
+ move.d r11,r8 \n\
+ move.d r11,r9 \n\
+ move.d r11,r10 \n\
\n\
- ;; Now we've got this: \n\
- ;; r13 - dst \n\
- ;; r12 - n \n\
+ ;; Now we've got this: \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
\n\
- ;; Update n for the first loop \n\
- subq 12*4,$r12 \n\
+ ;; Update n for the first loop \n\
+ subq 12*4,r12 \n\
0: \n\
- subq 12*4,$r12 \n\
- bge 0b \n\
- movem $r11,[$r13+] \n\
+"
+#ifdef __arch_common_v10_v32
+ /* Cater to branch offset difference between v32 and v10. We
+ assume the branch below has an 8-bit offset. */
+" setf\n"
+#endif
+" subq 12*4,r12 \n\
+ bge 0b \n\
+ movem r11,[r13+] \n\
\n\
- addq 12*4,$r12 ;; compensate for last loop underflowing n \n\
+ ;; Compensate for last loop underflowing n. \n\
+ addq 12*4,r12 \n\
\n\
- ;; Restore registers from stack \n\
- movem [$sp+],$r10"
+ ;; Restore registers from stack. \n\
+ movem [sp+],r10"
- /* Outputs */ : "=r" (dst), "=r" (n)
- /* Inputs */ : "0" (dst), "1" (n), "r" (lc));
- }
+ /* Outputs. */
+ : "=r" (dst), "=r" (n)
+
+ /* Inputs. */
+ : "0" (dst), "1" (n), "r" (lc));
+ }
+
+ /* An ad-hoc unroll, used for 4*12-1..16 bytes. */
+ while (n >= 16)
+ {
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ n -= 16;
+ }
- /* Either we directly starts copying, using dword copying
- in a loop, or we copy as much as possible with 'movem'
- and then the last block (<44 bytes) is copied here.
- This will work since 'movem' will have updated src,dst,n. */
-
- while ( n >= 16 )
- {
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- n -= 16;
- }
-
- /* A switch() is definitely the fastest although it takes a LOT of code.
- * Particularly if you inline code this.
- */
switch (n)
- {
+ {
case 0:
break;
+
case 1:
- *(char*)dst = (char) lc;
+ *dst = (char) lc;
break;
+
case 2:
- *(short*)dst = (short) lc;
+ *(short *) dst = (short) lc;
break;
+
case 3:
- *((short*)dst)++ = (short) lc;
- *(char*)dst = (char) lc;
+ *(short *) dst = (short) lc; dst += 2;
+ *dst = (char) lc;
break;
+
case 4:
- *((long*)dst)++ = lc;
+ *(long *) dst = lc;
break;
+
case 5:
- *((long*)dst)++ = lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *dst = (char) lc;
break;
+
case 6:
- *((long*)dst)++ = lc;
- *(short*)dst = (short) lc;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc;
break;
+
case 7:
- *((long*)dst)++ = lc;
- *((short*)dst)++ = (short) lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc; dst += 2;
+ *dst = (char) lc;
break;
+
case 8:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc;
break;
+
case 9:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *dst = (char) lc;
break;
+
case 10:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *(short*)dst = (short) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc;
break;
+
case 11:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((short*)dst)++ = (short) lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc; dst += 2;
+ *dst = (char) lc;
break;
+
case 12:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc;
break;
+
case 13:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *dst = (char) lc;
break;
+
case 14:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *(short*)dst = (short) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc;
break;
+
case 15:
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((long*)dst)++ = lc;
- *((short*)dst)++ = (short) lc;
- *(char*)dst = (char) lc;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(long *) dst = lc; dst += 4;
+ *(short *) dst = (short) lc; dst += 2;
+ *dst = (char) lc;
break;
- }
+ }
}
- return return_dst; /* destination pointer. */
-} /* memset() */
+ return return_dst;
+}
diff --git a/arch/cris/arch-v32/lib/spinlock.S b/arch/cris/arch-v32/lib/spinlock.S
index 2437ae7f6ed..79087ef59a1 100644
--- a/arch/cris/arch-v32/lib/spinlock.S
+++ b/arch/cris/arch-v32/lib/spinlock.S
@@ -12,11 +12,11 @@
cris_spin_lock:
clearf p
-1: test.d [$r10]
+1: test.b [$r10]
beq 1b
clearf p
ax
- clear.d [$r10]
+ clear.b [$r10]
bcs 1b
clearf p
ret
@@ -24,10 +24,10 @@ cris_spin_lock:
cris_spin_trylock:
clearf p
-1: move.d [$r10], $r11
+1: move.b [$r10], $r11
ax
- clear.d [$r10]
+ clear.b [$r10]
bcs 1b
clearf p
ret
- move.d $r11,$r10
+ movu.b $r11,$r10
diff --git a/arch/cris/arch-v32/mach-a3/Kconfig b/arch/cris/arch-v32/mach-a3/Kconfig
new file mode 100644
index 00000000000..a4df06d5997
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/Kconfig
@@ -0,0 +1,110 @@
+if CRIS_MACH_ARTPEC3
+
+menu "Artpec-3 options"
+ depends on CRIS_MACH_ARTPEC3
+
+config ETRAX_DRAM_VIRTUAL_BASE
+ hex
+ default "c0000000"
+
+config ETRAX_L2CACHE
+ bool
+ default y
+
+config ETRAX_SERIAL_PORTS
+ int
+ default 5
+
+config ETRAX_DDR
+ bool
+ default y
+
+config ETRAX_DDR2_MRS
+ hex "DDR2 MRS"
+ default "0"
+
+config ETRAX_DDR2_TIMING
+ hex "DDR2 SDRAM timing"
+ default "0"
+ help
+ SDRAM timing parameters.
+
+config ETRAX_DDR2_CONFIG
+ hex "DDR2 config"
+ default "0"
+
+config ETRAX_PIO_CE0_CFG
+ hex "PIO CE0 configuration"
+ default "0"
+
+config ETRAX_PIO_CE1_CFG
+ hex "PIO CE1 configuration"
+ default "0"
+
+config ETRAX_PIO_CE2_CFG
+ hex "PIO CE2 configuration"
+ default "0"
+
+config ETRAX_DEF_GIO_PA_OE
+ hex "GIO_PA_OE"
+ default "00000000"
+ help
+ Configures the direction of general port A bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used.
+ There are some guidelines though - if you know that only LED's are
+ connected to port PA, then they are usually connected to bits 2-4
+ and you can therefore use 1c. On other boards which don't have the
+ LED's at the general ports, these bits are used for all kinds of
+ stuff. If you don't know what to use, it is always safe to put all
+ as inputs, although floating inputs isn't good.
+
+config ETRAX_DEF_GIO_PA_OUT
+ hex "GIO_PA_OUT"
+ default "00000000"
+ help
+ Configures the initial data for the general port A bits. Most
+ products should use 00 here.
+
+config ETRAX_DEF_GIO_PB_OE
+ hex "GIO_PB_OE"
+ default "000000000"
+ help
+ Configures the direction of general port B bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used.
+ There are some guidelines though - if you know that only LED's are
+ connected to port PA, then they are usually connected to bits 2-4
+ and you can therefore use 1c. On other boards which don't have the
+ LED's at the general ports, these bits are used for all kinds of
+ stuff. If you don't know what to use, it is always safe to put all
+ as inputs, although floating inputs isn't good.
+
+config ETRAX_DEF_GIO_PB_OUT
+ hex "GIO_PB_OUT"
+ default "000000000"
+ help
+ Configures the initial data for the general port B bits. Most
+ products should use 00000 here.
+
+config ETRAX_DEF_GIO_PC_OE
+ hex "GIO_PC_OE"
+ default "00000"
+ help
+ Configures the direction of general port C bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used.
+ There are some guidelines though - if you know that only LED's are
+ connected to port PA, then they are usually connected to bits 2-4
+ and you can therefore use 1c. On other boards which don't have the
+ LED's at the general ports, these bits are used for all kinds of
+ stuff. If you don't know what to use, it is always safe to put all
+ as inputs, although floating inputs isn't good.
+
+config ETRAX_DEF_GIO_PC_OUT
+ hex "GIO_PC_OUT"
+ default "00000"
+ help
+ Configures the initial data for the general port C bits. Most
+ products should use 00000 here.
+
+endmenu
+
+endif
diff --git a/arch/cris/arch-v32/mach-a3/Makefile b/arch/cris/arch-v32/mach-a3/Makefile
new file mode 100644
index 00000000000..41fa6a6893a
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/Makefile
@@ -0,0 +1,11 @@
+# $Id: Makefile,v 1.3 2007/03/13 11:57:46 starvik Exp $
+#
+# Makefile for the linux kernel.
+#
+
+obj-y := dma.o pinmux.o io.o arbiter.o
+obj-$(CONFIG_ETRAX_VCS_SIM) += vcs_hook.o
+obj-$(CONFIG_CPU_FREQ) += cpufreq.o
+
+clean:
+
diff --git a/arch/cris/arch-v32/mach-a3/arbiter.c b/arch/cris/arch-v32/mach-a3/arbiter.c
new file mode 100644
index 00000000000..8b924db71c9
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/arbiter.c
@@ -0,0 +1,634 @@
+/*
+ * Memory arbiter functions. Allocates bandwidth through the
+ * arbiter and sets up arbiter breakpoints.
+ *
+ * The algorithm first assigns slots to the clients that has specified
+ * bandwidth (e.g. ethernet) and then the remaining slots are divided
+ * on all the active clients.
+ *
+ * Copyright (c) 2004-2007 Axis Communications AB.
+ *
+ * The artpec-3 has two arbiters. The memory hierarchy looks like this:
+ *
+ *
+ * CPU DMAs
+ * | |
+ * | |
+ * -------------- ------------------
+ * | foo arbiter|----| Internal memory|
+ * -------------- ------------------
+ * |
+ * --------------
+ * | L2 cache |
+ * --------------
+ * |
+ * h264 etc |
+ * | |
+ * | |
+ * --------------
+ * | bar arbiter|
+ * --------------
+ * |
+ * ---------
+ * | SDRAM |
+ * ---------
+ *
+ */
+
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/marb_foo_defs.h>
+#include <hwregs/marb_bar_defs.h>
+#include <arbiter.h>
+#include <hwregs/intr_vect.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/irq_regs.h>
+
+#define D(x)
+
+struct crisv32_watch_entry {
+ unsigned long instance;
+ watch_callback *cb;
+ unsigned long start;
+ unsigned long end;
+ int used;
+};
+
+#define NUMBER_OF_BP 4
+#define SDRAM_BANDWIDTH 400000000
+#define INTMEM_BANDWIDTH 400000000
+#define NBR_OF_SLOTS 64
+#define NBR_OF_REGIONS 2
+#define NBR_OF_CLIENTS 15
+#define ARBITERS 2
+#define UNASSIGNED 100
+
+struct arbiter {
+ unsigned long instance;
+ int nbr_regions;
+ int nbr_clients;
+ int requested_slots[NBR_OF_REGIONS][NBR_OF_CLIENTS];
+ int active_clients[NBR_OF_REGIONS][NBR_OF_CLIENTS];
+};
+
+static struct crisv32_watch_entry watches[ARBITERS][NUMBER_OF_BP] =
+{
+ {
+ {regi_marb_foo_bp0},
+ {regi_marb_foo_bp1},
+ {regi_marb_foo_bp2},
+ {regi_marb_foo_bp3}
+ },
+ {
+ {regi_marb_bar_bp0},
+ {regi_marb_bar_bp1},
+ {regi_marb_bar_bp2},
+ {regi_marb_bar_bp3}
+ }
+};
+
+struct arbiter arbiters[ARBITERS] =
+{
+ { /* L2 cache arbiter */
+ .instance = regi_marb_foo,
+ .nbr_regions = 2,
+ .nbr_clients = 15
+ },
+ { /* DDR2 arbiter */
+ .instance = regi_marb_bar,
+ .nbr_regions = 1,
+ .nbr_clients = 9
+ }
+};
+
+static int max_bandwidth[NBR_OF_REGIONS] = {SDRAM_BANDWIDTH, INTMEM_BANDWIDTH};
+
+DEFINE_SPINLOCK(arbiter_lock);
+
+static irqreturn_t
+crisv32_foo_arbiter_irq(int irq, void *dev_id);
+static irqreturn_t
+crisv32_bar_arbiter_irq(int irq, void *dev_id);
+
+/*
+ * "I'm the arbiter, I know the score.
+ * From square one I'll be watching all 64."
+ * (memory arbiter slots, that is)
+ *
+ * Or in other words:
+ * Program the memory arbiter slots for "region" according to what's
+ * in requested_slots[] and active_clients[], while minimizing
+ * latency. A caller may pass a non-zero positive amount for
+ * "unused_slots", which must then be the unallocated, remaining
+ * number of slots, free to hand out to any client.
+ */
+
+static void crisv32_arbiter_config(int arbiter, int region, int unused_slots)
+{
+ int slot;
+ int client;
+ int interval = 0;
+
+ /*
+ * This vector corresponds to the hardware arbiter slots (see
+ * the hardware documentation for semantics). We initialize
+ * each slot with a suitable sentinel value outside the valid
+ * range {0 .. NBR_OF_CLIENTS - 1} and replace them with
+ * client indexes. Then it's fed to the hardware.
+ */
+ s8 val[NBR_OF_SLOTS];
+
+ for (slot = 0; slot < NBR_OF_SLOTS; slot++)
+ val[slot] = -1;
+
+ for (client = 0; client < arbiters[arbiter].nbr_clients; client++) {
+ int pos;
+ /* Allocate the requested non-zero number of slots, but
+ * also give clients with zero-requests one slot each
+ * while stocks last. We do the latter here, in client
+ * order. This makes sure zero-request clients are the
+ * first to get to any spare slots, else those slots
+ * could, when bandwidth is allocated close to the limit,
+ * all be allocated to low-index non-zero-request clients
+ * in the default-fill loop below. Another positive but
+ * secondary effect is a somewhat better spread of the
+ * zero-bandwidth clients in the vector, avoiding some of
+ * the latency that could otherwise be caused by the
+ * partitioning of non-zero-bandwidth clients at low
+ * indexes and zero-bandwidth clients at high
+ * indexes. (Note that this spreading can only affect the
+ * unallocated bandwidth.) All the above only matters for
+ * memory-intensive situations, of course.
+ */
+ if (!arbiters[arbiter].requested_slots[region][client]) {
+ /*
+ * Skip inactive clients. Also skip zero-slot
+ * allocations in this pass when there are no known
+ * free slots.
+ */
+ if (!arbiters[arbiter].active_clients[region][client] ||
+ unused_slots <= 0)
+ continue;
+
+ unused_slots--;
+
+ /* Only allocate one slot for this client. */
+ interval = NBR_OF_SLOTS;
+ } else
+ interval = NBR_OF_SLOTS /
+ arbiters[arbiter].requested_slots[region][client];
+
+ pos = 0;
+ while (pos < NBR_OF_SLOTS) {
+ if (val[pos] >= 0)
+ pos++;
+ else {
+ val[pos] = client;
+ pos += interval;
+ }
+ }
+ }
+
+ client = 0;
+ for (slot = 0; slot < NBR_OF_SLOTS; slot++) {
+ /*
+ * Allocate remaining slots in round-robin
+ * client-number order for active clients. For this
+ * pass, we ignore requested bandwidth and previous
+ * allocations.
+ */
+ if (val[slot] < 0) {
+ int first = client;
+ while (!arbiters[arbiter].active_clients[region][client]) {
+ client = (client + 1) %
+ arbiters[arbiter].nbr_clients;
+ if (client == first)
+ break;
+ }
+ val[slot] = client;
+ client = (client + 1) % arbiters[arbiter].nbr_clients;
+ }
+ if (arbiter == 0) {
+ if (region == EXT_REGION)
+ REG_WR_INT_VECT(marb_foo, regi_marb_foo,
+ rw_l2_slots, slot, val[slot]);
+ else if (region == INT_REGION)
+ REG_WR_INT_VECT(marb_foo, regi_marb_foo,
+ rw_intm_slots, slot, val[slot]);
+ } else {
+ REG_WR_INT_VECT(marb_bar, regi_marb_bar,
+ rw_ddr2_slots, slot, val[slot]);
+ }
+ }
+}
+
+extern char _stext, _etext;
+
+static void crisv32_arbiter_init(void)
+{
+ static int initialized;
+
+ if (initialized)
+ return;
+
+ initialized = 1;
+
+ /*
+ * CPU caches are always set to active, but with zero
+ * bandwidth allocated. It should be ok to allocate zero
+ * bandwidth for the caches, because DMA for other channels
+ * will supposedly finish, once their programmed amount is
+ * done, and then the caches will get access according to the
+ * "fixed scheme" for unclaimed slots. Though, if for some
+ * use-case somewhere, there's a maximum CPU latency for
+ * e.g. some interrupt, we have to start allocating specific
+ * bandwidth for the CPU caches too.
+ */
+ arbiters[0].active_clients[EXT_REGION][11] = 1;
+ arbiters[0].active_clients[EXT_REGION][12] = 1;
+ crisv32_arbiter_config(0, EXT_REGION, 0);
+ crisv32_arbiter_config(0, INT_REGION, 0);
+ crisv32_arbiter_config(1, EXT_REGION, 0);
+
+ if (request_irq(MEMARB_FOO_INTR_VECT, crisv32_foo_arbiter_irq,
+ IRQF_DISABLED, "arbiter", NULL))
+ printk(KERN_ERR "Couldn't allocate arbiter IRQ\n");
+
+ if (request_irq(MEMARB_BAR_INTR_VECT, crisv32_bar_arbiter_irq,
+ IRQF_DISABLED, "arbiter", NULL))
+ printk(KERN_ERR "Couldn't allocate arbiter IRQ\n");
+
+#ifndef CONFIG_ETRAX_KGDB
+ /* Global watch for writes to kernel text segment. */
+ crisv32_arbiter_watch(virt_to_phys(&_stext), &_etext - &_stext,
+ MARB_CLIENTS(arbiter_all_clients, arbiter_bar_all_clients),
+ arbiter_all_write, NULL);
+#endif
+
+ /* Set up max burst sizes by default */
+ REG_WR_INT(marb_bar, regi_marb_bar, rw_h264_rd_burst, 3);
+ REG_WR_INT(marb_bar, regi_marb_bar, rw_h264_wr_burst, 3);
+ REG_WR_INT(marb_bar, regi_marb_bar, rw_ccd_burst, 3);
+ REG_WR_INT(marb_bar, regi_marb_bar, rw_vin_wr_burst, 3);
+ REG_WR_INT(marb_bar, regi_marb_bar, rw_vin_rd_burst, 3);
+ REG_WR_INT(marb_bar, regi_marb_bar, rw_sclr_rd_burst, 3);
+ REG_WR_INT(marb_bar, regi_marb_bar, rw_vout_burst, 3);
+ REG_WR_INT(marb_bar, regi_marb_bar, rw_sclr_fifo_burst, 3);
+ REG_WR_INT(marb_bar, regi_marb_bar, rw_l2cache_burst, 3);
+}
+
+int crisv32_arbiter_allocate_bandwidth(int client, int region,
+ unsigned long bandwidth)
+{
+ int i;
+ int total_assigned = 0;
+ int total_clients = 0;
+ int req;
+ int arbiter = 0;
+
+ crisv32_arbiter_init();
+
+ if (client & 0xffff0000) {
+ arbiter = 1;
+ client >>= 16;
+ }
+
+ for (i = 0; i < arbiters[arbiter].nbr_clients; i++) {
+ total_assigned += arbiters[arbiter].requested_slots[region][i];
+ total_clients += arbiters[arbiter].active_clients[region][i];
+ }
+
+ /* Avoid division by 0 for 0-bandwidth requests. */
+ req = bandwidth == 0
+ ? 0 : NBR_OF_SLOTS / (max_bandwidth[region] / bandwidth);
+
+ /*
+ * We make sure that there are enough slots only for non-zero
+ * requests. Requesting 0 bandwidth *may* allocate slots,
+ * though if all bandwidth is allocated, such a client won't
+ * get any and will have to rely on getting memory access
+ * according to the fixed scheme that's the default when one
+ * of the slot-allocated clients doesn't claim their slot.
+ */
+ if (total_assigned + req > NBR_OF_SLOTS)
+ return -ENOMEM;
+
+ arbiters[arbiter].active_clients[region][client] = 1;
+ arbiters[arbiter].requested_slots[region][client] = req;
+ crisv32_arbiter_config(arbiter, region, NBR_OF_SLOTS - total_assigned);
+
+ /* Propagate allocation from foo to bar */
+ if (arbiter == 0)
+ crisv32_arbiter_allocate_bandwidth(8 << 16,
+ EXT_REGION, bandwidth);
+ return 0;
+}
+
+/*
+ * Main entry for bandwidth deallocation.
+ *
+ * Strictly speaking, for a somewhat constant set of clients where
+ * each client gets a constant bandwidth and is just enabled or
+ * disabled (somewhat dynamically), no action is necessary here to
+ * avoid starvation for non-zero-allocation clients, as the allocated
+ * slots will just be unused. However, handing out those unused slots
+ * to active clients avoids needless latency if the "fixed scheme"
+ * would give unclaimed slots to an eager low-index client.
+ */
+
+void crisv32_arbiter_deallocate_bandwidth(int client, int region)
+{
+ int i;
+ int total_assigned = 0;
+ int arbiter = 0;
+
+ if (client & 0xffff0000)
+ arbiter = 1;
+
+ arbiters[arbiter].requested_slots[region][client] = 0;
+ arbiters[arbiter].active_clients[region][client] = 0;
+
+ for (i = 0; i < arbiters[arbiter].nbr_clients; i++)
+ total_assigned += arbiters[arbiter].requested_slots[region][i];
+
+ crisv32_arbiter_config(arbiter, region, NBR_OF_SLOTS - total_assigned);
+}
+
+int crisv32_arbiter_watch(unsigned long start, unsigned long size,
+ unsigned long clients, unsigned long accesses,
+ watch_callback *cb)
+{
+ int i;
+ int arbiter;
+ int used[2];
+ int ret = 0;
+
+ crisv32_arbiter_init();
+
+ if (start > 0x80000000) {
+ printk(KERN_ERR "Arbiter: %lX doesn't look like a "
+ "physical address", start);
+ return -EFAULT;
+ }
+
+ spin_lock(&arbiter_lock);
+
+ if (clients & 0xffff)
+ used[0] = 1;
+ if (clients & 0xffff0000)
+ used[1] = 1;
+
+ for (arbiter = 0; arbiter < ARBITERS; arbiter++) {
+ if (!used[arbiter])
+ continue;
+
+ for (i = 0; i < NUMBER_OF_BP; i++) {
+ if (!watches[arbiter][i].used) {
+ unsigned intr_mask;
+ if (arbiter)
+ intr_mask = REG_RD_INT(marb_bar,
+ regi_marb_bar, rw_intr_mask);
+ else
+ intr_mask = REG_RD_INT(marb_foo,
+ regi_marb_foo, rw_intr_mask);
+
+ watches[arbiter][i].used = 1;
+ watches[arbiter][i].start = start;
+ watches[arbiter][i].end = start + size;
+ watches[arbiter][i].cb = cb;
+
+ ret |= (i + 1) << (arbiter + 8);
+ if (arbiter) {
+ REG_WR_INT(marb_bar_bp,
+ watches[arbiter][i].instance,
+ rw_first_addr,
+ watches[arbiter][i].start);
+ REG_WR_INT(marb_bar_bp,
+ watches[arbiter][i].instance,
+ rw_last_addr,
+ watches[arbiter][i].end);
+ REG_WR_INT(marb_bar_bp,
+ watches[arbiter][i].instance,
+ rw_op, accesses);
+ REG_WR_INT(marb_bar_bp,
+ watches[arbiter][i].instance,
+ rw_clients,
+ clients & 0xffff);
+ } else {
+ REG_WR_INT(marb_foo_bp,
+ watches[arbiter][i].instance,
+ rw_first_addr,
+ watches[arbiter][i].start);
+ REG_WR_INT(marb_foo_bp,
+ watches[arbiter][i].instance,
+ rw_last_addr,
+ watches[arbiter][i].end);
+ REG_WR_INT(marb_foo_bp,
+ watches[arbiter][i].instance,
+ rw_op, accesses);
+ REG_WR_INT(marb_foo_bp,
+ watches[arbiter][i].instance,
+ rw_clients, clients >> 16);
+ }
+
+ if (i == 0)
+ intr_mask |= 1;
+ else if (i == 1)
+ intr_mask |= 2;
+ else if (i == 2)
+ intr_mask |= 4;
+ else if (i == 3)
+ intr_mask |= 8;
+
+ if (arbiter)
+ REG_WR_INT(marb_bar, regi_marb_bar,
+ rw_intr_mask, intr_mask);
+ else
+ REG_WR_INT(marb_foo, regi_marb_foo,
+ rw_intr_mask, intr_mask);
+
+ spin_unlock(&arbiter_lock);
+
+ break;
+ }
+ }
+ }
+ spin_unlock(&arbiter_lock);
+ if (ret)
+ return ret;
+ else
+ return -ENOMEM;
+}
+
+int crisv32_arbiter_unwatch(int id)
+{
+ int arbiter;
+ int intr_mask;
+
+ crisv32_arbiter_init();
+
+ spin_lock(&arbiter_lock);
+
+ for (arbiter = 0; arbiter < ARBITERS; arbiter++) {
+ int id2;
+
+ if (arbiter)
+ intr_mask = REG_RD_INT(marb_bar, regi_marb_bar,
+ rw_intr_mask);
+ else
+ intr_mask = REG_RD_INT(marb_foo, regi_marb_foo,
+ rw_intr_mask);
+
+ id2 = (id & (0xff << (arbiter + 8))) >> (arbiter + 8);
+ if (id2 == 0)
+ continue;
+ id2--;
+ if ((id2 >= NUMBER_OF_BP) || (!watches[arbiter][id2].used)) {
+ spin_unlock(&arbiter_lock);
+ return -EINVAL;
+ }
+
+ memset(&watches[arbiter][id2], 0,
+ sizeof(struct crisv32_watch_entry));
+
+ if (id2 == 0)
+ intr_mask &= ~1;
+ else if (id2 == 1)
+ intr_mask &= ~2;
+ else if (id2 == 2)
+ intr_mask &= ~4;
+ else if (id2 == 3)
+ intr_mask &= ~8;
+
+ if (arbiter)
+ REG_WR_INT(marb_bar, regi_marb_bar, rw_intr_mask,
+ intr_mask);
+ else
+ REG_WR_INT(marb_foo, regi_marb_foo, rw_intr_mask,
+ intr_mask);
+ }
+
+ spin_unlock(&arbiter_lock);
+ return 0;
+}
+
+extern void show_registers(struct pt_regs *regs);
+
+
+static irqreturn_t
+crisv32_foo_arbiter_irq(int irq, void *dev_id)
+{
+ reg_marb_foo_r_masked_intr masked_intr =
+ REG_RD(marb_foo, regi_marb_foo, r_masked_intr);
+ reg_marb_foo_bp_r_brk_clients r_clients;
+ reg_marb_foo_bp_r_brk_addr r_addr;
+ reg_marb_foo_bp_r_brk_op r_op;
+ reg_marb_foo_bp_r_brk_first_client r_first;
+ reg_marb_foo_bp_r_brk_size r_size;
+ reg_marb_foo_bp_rw_ack ack = {0};
+ reg_marb_foo_rw_ack_intr ack_intr = {
+ .bp0 = 1, .bp1 = 1, .bp2 = 1, .bp3 = 1
+ };
+ struct crisv32_watch_entry *watch;
+ unsigned arbiter = (unsigned)dev_id;
+
+ masked_intr = REG_RD(marb_foo, regi_marb_foo, r_masked_intr);
+
+ if (masked_intr.bp0)
+ watch = &watches[arbiter][0];
+ else if (masked_intr.bp1)
+ watch = &watches[arbiter][1];
+ else if (masked_intr.bp2)
+ watch = &watches[arbiter][2];
+ else if (masked_intr.bp3)
+ watch = &watches[arbiter][3];
+ else
+ return IRQ_NONE;
+
+ /* Retrieve all useful information and print it. */
+ r_clients = REG_RD(marb_foo_bp, watch->instance, r_brk_clients);
+ r_addr = REG_RD(marb_foo_bp, watch->instance, r_brk_addr);
+ r_op = REG_RD(marb_foo_bp, watch->instance, r_brk_op);
+ r_first = REG_RD(marb_foo_bp, watch->instance, r_brk_first_client);
+ r_size = REG_RD(marb_foo_bp, watch->instance, r_brk_size);
+
+ printk(KERN_DEBUG "Arbiter IRQ\n");
+ printk(KERN_DEBUG "Clients %X addr %X op %X first %X size %X\n",
+ REG_TYPE_CONV(int, reg_marb_foo_bp_r_brk_clients, r_clients),
+ REG_TYPE_CONV(int, reg_marb_foo_bp_r_brk_addr, r_addr),
+ REG_TYPE_CONV(int, reg_marb_foo_bp_r_brk_op, r_op),
+ REG_TYPE_CONV(int, reg_marb_foo_bp_r_brk_first_client, r_first),
+ REG_TYPE_CONV(int, reg_marb_foo_bp_r_brk_size, r_size));
+
+ REG_WR(marb_foo_bp, watch->instance, rw_ack, ack);
+ REG_WR(marb_foo, regi_marb_foo, rw_ack_intr, ack_intr);
+
+ printk(KERN_DEBUG "IRQ occured at %X\n", (unsigned)get_irq_regs());
+
+ if (watch->cb)
+ watch->cb();
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+crisv32_bar_arbiter_irq(int irq, void *dev_id)
+{
+ reg_marb_bar_r_masked_intr masked_intr =
+ REG_RD(marb_bar, regi_marb_bar, r_masked_intr);
+ reg_marb_bar_bp_r_brk_clients r_clients;
+ reg_marb_bar_bp_r_brk_addr r_addr;
+ reg_marb_bar_bp_r_brk_op r_op;
+ reg_marb_bar_bp_r_brk_first_client r_first;
+ reg_marb_bar_bp_r_brk_size r_size;
+ reg_marb_bar_bp_rw_ack ack = {0};
+ reg_marb_bar_rw_ack_intr ack_intr = {
+ .bp0 = 1, .bp1 = 1, .bp2 = 1, .bp3 = 1
+ };
+ struct crisv32_watch_entry *watch;
+ unsigned arbiter = (unsigned)dev_id;
+
+ masked_intr = REG_RD(marb_bar, regi_marb_bar, r_masked_intr);
+
+ if (masked_intr.bp0)
+ watch = &watches[arbiter][0];
+ else if (masked_intr.bp1)
+ watch = &watches[arbiter][1];
+ else if (masked_intr.bp2)
+ watch = &watches[arbiter][2];
+ else if (masked_intr.bp3)
+ watch = &watches[arbiter][3];
+ else
+ return IRQ_NONE;
+
+ /* Retrieve all useful information and print it. */
+ r_clients = REG_RD(marb_bar_bp, watch->instance, r_brk_clients);
+ r_addr = REG_RD(marb_bar_bp, watch->instance, r_brk_addr);
+ r_op = REG_RD(marb_bar_bp, watch->instance, r_brk_op);
+ r_first = REG_RD(marb_bar_bp, watch->instance, r_brk_first_client);
+ r_size = REG_RD(marb_bar_bp, watch->instance, r_brk_size);
+
+ printk(KERN_DEBUG "Arbiter IRQ\n");
+ printk(KERN_DEBUG "Clients %X addr %X op %X first %X size %X\n",
+ REG_TYPE_CONV(int, reg_marb_bar_bp_r_brk_clients, r_clients),
+ REG_TYPE_CONV(int, reg_marb_bar_bp_r_brk_addr, r_addr),
+ REG_TYPE_CONV(int, reg_marb_bar_bp_r_brk_op, r_op),
+ REG_TYPE_CONV(int, reg_marb_bar_bp_r_brk_first_client, r_first),
+ REG_TYPE_CONV(int, reg_marb_bar_bp_r_brk_size, r_size));
+
+ REG_WR(marb_bar_bp, watch->instance, rw_ack, ack);
+ REG_WR(marb_bar, regi_marb_bar, rw_ack_intr, ack_intr);
+
+ printk(KERN_DEBUG "IRQ occured at %X\n", (unsigned)get_irq_regs()->erp);
+
+ if (watch->cb)
+ watch->cb();
+
+ return IRQ_HANDLED;
+}
+
diff --git a/arch/cris/arch-v32/mach-a3/cpufreq.c b/arch/cris/arch-v32/mach-a3/cpufreq.c
new file mode 100644
index 00000000000..8e5a3cab8ad
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/cpufreq.c
@@ -0,0 +1,153 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/clkgen_defs.h>
+#include <hwregs/ddr2_defs.h>
+
+static int
+cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val,
+ void *data);
+
+static struct notifier_block cris_sdram_freq_notifier_block = {
+ .notifier_call = cris_sdram_freq_notifier
+};
+
+static struct cpufreq_frequency_table cris_freq_table[] = {
+ {0x01, 6000},
+ {0x02, 200000},
+ {0, CPUFREQ_TABLE_END},
+};
+
+static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
+{
+ reg_clkgen_rw_clk_ctrl clk_ctrl;
+ clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
+ return clk_ctrl.pll ? 200000 : 6000;
+}
+
+static void cris_freq_set_cpu_state(unsigned int state)
+{
+ int i = 0;
+ struct cpufreq_freqs freqs;
+ reg_clkgen_rw_clk_ctrl clk_ctrl;
+ clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
+
+#ifdef CONFIG_SMP
+ for_each_present_cpu(i)
+#endif
+ {
+ freqs.old = cris_freq_get_cpu_frequency(i);
+ freqs.new = cris_freq_table[state].frequency;
+ freqs.cpu = i;
+ }
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ local_irq_disable();
+
+ /* Even though we may be SMP they will share the same clock
+ * so all settings are made on CPU0. */
+ if (cris_freq_table[state].frequency == 200000)
+ clk_ctrl.pll = 1;
+ else
+ clk_ctrl.pll = 0;
+ REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
+
+ local_irq_enable();
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+};
+
+static int cris_freq_verify(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]);
+}
+
+static int cris_freq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ unsigned int newstate = 0;
+
+ if (cpufreq_frequency_table_target(policy, cris_freq_table,
+ target_freq, relation, &newstate))
+ return -EINVAL;
+
+ cris_freq_set_cpu_state(newstate);
+
+ return 0;
+}
+
+static int cris_freq_cpu_init(struct cpufreq_policy *policy)
+{
+ int result;
+
+ /* cpuinfo and default policy values */
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+ policy->cpuinfo.transition_latency = 1000000; /* 1ms */
+ policy->cur = cris_freq_get_cpu_frequency(0);
+
+ result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table);
+ if (result)
+ return (result);
+
+ cpufreq_frequency_table_get_attr(cris_freq_table, policy->cpu);
+
+ return 0;
+}
+
+
+static int cris_freq_cpu_exit(struct cpufreq_policy *policy)
+{
+ cpufreq_frequency_table_put_attr(policy->cpu);
+ return 0;
+}
+
+
+static struct freq_attr *cris_freq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static struct cpufreq_driver cris_freq_driver = {
+ .get = cris_freq_get_cpu_frequency,
+ .verify = cris_freq_verify,
+ .target = cris_freq_target,
+ .init = cris_freq_cpu_init,
+ .exit = cris_freq_cpu_exit,
+ .name = "cris_freq",
+ .owner = THIS_MODULE,
+ .attr = cris_freq_attr,
+};
+
+static int __init cris_freq_init(void)
+{
+ int ret;
+ ret = cpufreq_register_driver(&cris_freq_driver);
+ cpufreq_register_notifier(&cris_sdram_freq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+ return ret;
+}
+
+static int
+cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ int i;
+ struct cpufreq_freqs *freqs = data;
+ if (val == CPUFREQ_PRECHANGE) {
+ reg_ddr2_rw_cfg cfg =
+ REG_RD(ddr2, regi_ddr2_ctrl, rw_cfg);
+ cfg.ref_interval = (freqs->new == 200000 ? 1560 : 46);
+
+ if (freqs->new == 200000)
+ for (i = 0; i < 50000; i++);
+ REG_WR(bif_core, regi_bif_core, rw_sdram_timing, timing);
+ }
+ return 0;
+}
+
+
+module_init(cris_freq_init);
diff --git a/arch/cris/arch-v32/mach-a3/dma.c b/arch/cris/arch-v32/mach-a3/dma.c
new file mode 100644
index 00000000000..25f236ef0b8
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/dma.c
@@ -0,0 +1,185 @@
+/* Wrapper for DMA channel allocator that starts clocks etc */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm/arch/mach/dma.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/marb_defs.h>
+#include <hwregs/clkgen_defs.h>
+#include <hwregs/strmux_defs.h>
+#include <linux/errno.h>
+#include <asm/system.h>
+#include <arbiter.h>
+
+static char used_dma_channels[MAX_DMA_CHANNELS];
+static const char *used_dma_channels_users[MAX_DMA_CHANNELS];
+
+static DEFINE_SPINLOCK(dma_lock);
+
+int crisv32_request_dma(unsigned int dmanr, const char *device_id,
+ unsigned options, unsigned int bandwidth, enum dma_owner owner)
+{
+ unsigned long flags;
+ reg_clkgen_rw_clk_ctrl clk_ctrl;
+ reg_strmux_rw_cfg strmux_cfg;
+
+ if (crisv32_arbiter_allocate_bandwidth(dmanr,
+ options & DMA_INT_MEM ? INT_REGION : EXT_REGION,
+ bandwidth))
+ return -ENOMEM;
+
+ spin_lock_irqsave(&dma_lock, flags);
+
+ if (used_dma_channels[dmanr]) {
+ spin_unlock_irqrestore(&dma_lock, flags);
+ if (options & DMA_VERBOSE_ON_ERROR)
+ printk(KERN_ERR "Failed to request DMA %i for %s, "
+ "already allocated by %s\n",
+ dmanr,
+ device_id,
+ used_dma_channels_users[dmanr]);
+
+ if (options & DMA_PANIC_ON_ERROR)
+ panic("request_dma error!");
+ spin_unlock_irqrestore(&dma_lock, flags);
+ return -EBUSY;
+ }
+ clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
+ strmux_cfg = REG_RD(strmux, regi_strmux, rw_cfg);
+
+ switch (dmanr) {
+ case 0:
+ case 1:
+ clk_ctrl.dma0_1_eth = 1;
+ break;
+ case 2:
+ case 3:
+ clk_ctrl.dma2_3_strcop = 1;
+ break;
+ case 4:
+ case 5:
+ clk_ctrl.dma4_5_iop = 1;
+ break;
+ case 6:
+ case 7:
+ clk_ctrl.sser_ser_dma6_7 = 1;
+ break;
+ case 9:
+ case 11:
+ clk_ctrl.dma9_11 = 1;
+ break;
+#if MAX_DMA_CHANNELS-1 != 11
+#error Check dma.c
+#endif
+ default:
+ spin_unlock_irqrestore(&dma_lock, flags);
+ if (options & DMA_VERBOSE_ON_ERROR)
+ printk(KERN_ERR "Failed to request DMA %i for %s, "
+ "only 0-%i valid)\n",
+ dmanr, device_id, MAX_DMA_CHANNELS-1);
+
+ if (options & DMA_PANIC_ON_ERROR)
+ panic("request_dma error!");
+ return -EINVAL;
+ }
+
+ switch (owner) {
+ case dma_eth:
+ if (dmanr == 0)
+ strmux_cfg.dma0 = regk_strmux_eth;
+ else if (dmanr == 1)
+ strmux_cfg.dma1 = regk_strmux_eth;
+ else
+ panic("Invalid DMA channel for eth\n");
+ break;
+ case dma_ser0:
+ if (dmanr == 0)
+ strmux_cfg.dma0 = regk_strmux_ser0;
+ else if (dmanr == 1)
+ strmux_cfg.dma1 = regk_strmux_ser0;
+ else
+ panic("Invalid DMA channel for ser0\n");
+ break;
+ case dma_ser3:
+ if (dmanr == 2)
+ strmux_cfg.dma2 = regk_strmux_ser3;
+ else if (dmanr == 3)
+ strmux_cfg.dma3 = regk_strmux_ser3;
+ else
+ panic("Invalid DMA channel for ser3\n");
+ break;
+ case dma_strp:
+ if (dmanr == 2)
+ strmux_cfg.dma2 = regk_strmux_strcop;
+ else if (dmanr == 3)
+ strmux_cfg.dma3 = regk_strmux_strcop;
+ else
+ panic("Invalid DMA channel for strp\n");
+ break;
+ case dma_ser1:
+ if (dmanr == 4)
+ strmux_cfg.dma4 = regk_strmux_ser1;
+ else if (dmanr == 5)
+ strmux_cfg.dma5 = regk_strmux_ser1;
+ else
+ panic("Invalid DMA channel for ser1\n");
+ break;
+ case dma_iop:
+ if (dmanr == 4)
+ strmux_cfg.dma4 = regk_strmux_iop;
+ else if (dmanr == 5)
+ strmux_cfg.dma5 = regk_strmux_iop;
+ else
+ panic("Invalid DMA channel for iop\n");
+ break;
+ case dma_ser2:
+ if (dmanr == 6)
+ strmux_cfg.dma6 = regk_strmux_ser2;
+ else if (dmanr == 7)
+ strmux_cfg.dma7 = regk_strmux_ser2;
+ else
+ panic("Invalid DMA channel for ser2\n");
+ break;
+ case dma_sser:
+ if (dmanr == 6)
+ strmux_cfg.dma6 = regk_strmux_sser;
+ else if (dmanr == 7)
+ strmux_cfg.dma7 = regk_strmux_sser;
+ else
+ panic("Invalid DMA channel for sser\n");
+ break;
+ case dma_ser4:
+ if (dmanr == 9)
+ strmux_cfg.dma9 = regk_strmux_ser4;
+ else
+ panic("Invalid DMA channel for ser4\n");
+ break;
+ case dma_jpeg:
+ if (dmanr == 9)
+ strmux_cfg.dma9 = regk_strmux_jpeg;
+ else
+ panic("Invalid DMA channel for JPEG\n");
+ break;
+ case dma_h264:
+ if (dmanr == 11)
+ strmux_cfg.dma11 = regk_strmux_h264;
+ else
+ panic("Invalid DMA channel for H264\n");
+ break;
+ }
+
+ used_dma_channels[dmanr] = 1;
+ used_dma_channels_users[dmanr] = device_id;
+ REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
+ REG_WR(strmux, regi_strmux, rw_cfg, strmux_cfg);
+ spin_unlock_irqrestore(&dma_lock, flags);
+ return 0;
+}
+
+void crisv32_free_dma(unsigned int dmanr)
+{
+ spin_lock(&dma_lock);
+ used_dma_channels[dmanr] = 0;
+ spin_unlock(&dma_lock);
+}
diff --git a/arch/cris/arch-v32/mach-a3/dram_init.S b/arch/cris/arch-v32/mach-a3/dram_init.S
new file mode 100644
index 00000000000..94d6b41cb29
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/dram_init.S
@@ -0,0 +1,104 @@
+/*
+ * DDR SDRAM initialization - alter with care
+ * This file is intended to be included from other assembler files
+ *
+ * Note: This file may not modify r8 or r9 because they are used to
+ * carry information from the decompresser to the kernel
+ *
+ * Copyright (C) 2005-2007 Axis Communications AB
+ *
+ * Authors: Mikael Starvik <starvik@axis.com>
+ */
+
+/* Just to be certain the config file is included, we include it here
+ * explicitely instead of depending on it being included in the file that
+ * uses this code.
+ */
+
+#include <hwregs/asm/reg_map_asm.h>
+#include <hwregs/asm/ddr2_defs_asm.h>
+
+ ;; WARNING! The registers r8 and r9 are used as parameters carrying
+ ;; information from the decompressor (if the kernel was compressed).
+ ;; They should not be used in the code below.
+
+ ;; Refer to ddr2 MDS for initialization sequence
+
+ ; Start clock
+ move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_phy_cfg), $r0
+ move.d REG_STATE(ddr2, rw_phy_cfg, en, yes), $r1
+ move.d $r1, [$r0]
+
+ ; Reset phy and start calibration
+ move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_phy_ctrl), $r0
+ move.d REG_STATE(ddr2, rw_phy_ctrl, rst, yes) | \
+ REG_STATE(ddr2, rw_phy_ctrl, cal_rst, yes), $r1
+ move.d $r1, [$r0]
+ move.d REG_STATE(ddr2, rw_phy_ctrl, cal_start, yes), $r1
+ move.d $r1, [$r0]
+
+ ; 2. Wait 200us
+ move.d 10000, $r2
+1: bne 1b
+ subq 1, $r2
+
+ ; Issue commands
+ move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_ctrl), $r0
+ move.d sdram_commands_start, $r2
+command_loop:
+ movu.b [$r2+], $r1
+ movu.w [$r2+], $r3
+do_cmd:
+ lslq 16, $r1
+ or.d $r3, $r1
+ move.d $r1, [$r0]
+ cmp.d sdram_commands_end, $r2
+ blo command_loop
+ nop
+
+ ; Set timing
+ move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_timing), $r0
+ move.d CONFIG_ETRAX_DDR2_TIMING, $r1
+ move.d $r1, [$r0]
+
+ ; Set latency
+ move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_latency), $r0
+ move.d 0x13, $r1
+ move.d $r1, [$r0]
+
+ ; Set configuration
+ move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_cfg), $r0
+ move.d CONFIG_ETRAX_DDR2_CONFIG, $r1
+ move.d $r1, [$r0]
+
+ ba after_sdram_commands
+ nop
+
+sdram_commands_start:
+ .byte regk_ddr2_deselect
+ .word 0
+ .byte regk_ddr2_pre
+ .word regk_ddr2_pre_all
+ .byte regk_ddr2_emrs2
+ .word 0
+ .byte regk_ddr2_emrs3
+ .word 0
+ .byte regk_ddr2_emrs
+ .word regk_ddr2_dll_en
+ .byte regk_ddr2_mrs
+ .word regk_ddr2_dll_rst
+ .byte regk_ddr2_pre
+ .word regk_ddr2_pre_all
+ .byte regk_ddr2_ref
+ .word 0
+ .byte regk_ddr2_ref
+ .word 0
+ .byte regk_ddr2_mrs
+ .word CONFIG_ETRAX_DDR2_MRS & 0xffff
+ .byte regk_ddr2_emrs
+ .word regk_ddr2_ocd_default | regk_ddr2_dll_en
+ .byte regk_ddr2_emrs
+ .word regk_ddr2_ocd_exit | regk_ddr2_dll_en | (CONFIG_ETRAX_DDR2_MRS >> 16)
+sdram_commands_end:
+ .align 1
+after_sdram_commands:
diff --git a/arch/cris/arch-v32/mach-a3/hw_settings.S b/arch/cris/arch-v32/mach-a3/hw_settings.S
new file mode 100644
index 00000000000..258a6329cd4
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/hw_settings.S
@@ -0,0 +1,51 @@
+/*
+ * This table is used by some tools to extract hardware parameters.
+ * The table should be included in the kernel and the decompressor.
+ * Don't forget to update the tools if you change this table.
+ *
+ * Copyright (C) 2001-2007 Axis Communications AB
+ *
+ * Authors: Mikael Starvik <starvik@axis.com>
+ */
+
+#include <hwregs/asm/reg_map_asm.h>
+#include <hwregs/asm/ddr2_defs_asm.h>
+#include <hwregs/asm/gio_defs_asm.h>
+
+ .ascii "HW_PARAM_MAGIC" ; Magic number
+ .dword 0xc0004000 ; Kernel start address
+
+ ; Debug port
+#ifdef CONFIG_ETRAX_DEBUG_PORT0
+ .dword 0
+#elif defined(CONFIG_ETRAX_DEBUG_PORT1)
+ .dword 1
+#elif defined(CONFIG_ETRAX_DEBUG_PORT2)
+ .dword 2
+#elif defined(CONFIG_ETRAX_DEBUG_PORT3)
+ .dword 3
+#else
+ .dword 4 ; No debug
+#endif
+
+ ; Register values
+ .dword REG_ADDR(ddr2, regi_ddr2_ctrl, rw_cfg)
+ .dword CONFIG_ETRAX_DDR2_CONFIG
+ .dword REG_ADDR(ddr2, regi_ddr2_ctrl, rw_timing)
+ .dword CONFIG_ETRAX_DDR2_TIMING
+ .dword CONFIG_ETRAX_DDR2_MRS
+
+ .dword REG_ADDR(gio, regi_gio, rw_pa_dout)
+ .dword CONFIG_ETRAX_DEF_GIO_PA_OUT
+ .dword REG_ADDR(gio, regi_gio, rw_pa_oe)
+ .dword CONFIG_ETRAX_DEF_GIO_PA_OE
+ .dword REG_ADDR(gio, regi_gio, rw_pb_dout)
+ .dword CONFIG_ETRAX_DEF_GIO_PB_OUT
+ .dword REG_ADDR(gio, regi_gio, rw_pb_oe)
+ .dword CONFIG_ETRAX_DEF_GIO_PB_OE
+ .dword REG_ADDR(gio, regi_gio, rw_pc_dout)
+ .dword CONFIG_ETRAX_DEF_GIO_PC_OUT
+ .dword REG_ADDR(gio, regi_gio, rw_pc_oe)
+ .dword CONFIG_ETRAX_DEF_GIO_PC_OE
+
+ .dword 0 ; No more register values
diff --git a/arch/cris/arch-v32/mach-a3/io.c b/arch/cris/arch-v32/mach-a3/io.c
new file mode 100644
index 00000000000..9eeaf3eca47
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/io.c
@@ -0,0 +1,149 @@
+/*
+ * Helper functions for I/O pins.
+ *
+ * Copyright (c) 2005-2007 Axis Communications AB.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/arch/mach/pinmux.h>
+#include <hwregs/gio_defs.h>
+
+struct crisv32_ioport crisv32_ioports[] = {
+ {
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_oe),
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_dout),
+ (unsigned long *)REG_ADDR(gio, regi_gio, r_pa_din),
+ 32
+ },
+ {
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_oe),
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_dout),
+ (unsigned long *)REG_ADDR(gio, regi_gio, r_pb_din),
+ 32
+ },
+ {
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_oe),
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_dout),
+ (unsigned long *)REG_ADDR(gio, regi_gio, r_pc_din),
+ 16
+ },
+};
+
+#define NBR_OF_PORTS sizeof(crisv32_ioports)/sizeof(struct crisv32_ioport)
+
+struct crisv32_iopin crisv32_led_net0_green;
+struct crisv32_iopin crisv32_led_net0_red;
+struct crisv32_iopin crisv32_led2_green;
+struct crisv32_iopin crisv32_led2_red;
+struct crisv32_iopin crisv32_led3_green;
+struct crisv32_iopin crisv32_led3_red;
+
+/* Dummy port used when green LED and red LED is on the same bit */
+static unsigned long io_dummy;
+static struct crisv32_ioport dummy_port = {
+ &io_dummy,
+ &io_dummy,
+ &io_dummy,
+ 32
+};
+static struct crisv32_iopin dummy_led = {
+ &dummy_port,
+ 0
+};
+
+static int __init crisv32_io_init(void)
+{
+ int ret = 0;
+
+ u32 i;
+
+ /* Locks *should* be dynamically initialized. */
+ for (i = 0; i < ARRAY_SIZE(crisv32_ioports); i++)
+ spin_lock_init(&crisv32_ioports[i].lock);
+ spin_lock_init(&dummy_port.lock);
+
+ /* Initialize LEDs */
+#if (defined(CONFIG_ETRAX_NBR_LED_GRP_ONE) || defined(CONFIG_ETRAX_NBR_LED_GRP_TWO))
+ ret += crisv32_io_get_name(&crisv32_led_net0_green,
+ CONFIG_ETRAX_LED_G_NET0);
+ crisv32_io_set_dir(&crisv32_led_net0_green, crisv32_io_dir_out);
+ if (strcmp(CONFIG_ETRAX_LED_G_NET0, CONFIG_ETRAX_LED_R_NET0)) {
+ ret += crisv32_io_get_name(&crisv32_led_net0_red,
+ CONFIG_ETRAX_LED_R_NET0);
+ crisv32_io_set_dir(&crisv32_led_net0_red, crisv32_io_dir_out);
+ } else
+ crisv32_led_net0_red = dummy_led;
+#endif
+
+ ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_V32_LED2G);
+ ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_V32_LED2R);
+ ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_V32_LED3G);
+ ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_V32_LED3R);
+
+ crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out);
+ crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out);
+ crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out);
+ crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out);
+
+ return ret;
+}
+
+__initcall(crisv32_io_init);
+
+int crisv32_io_get(struct crisv32_iopin *iopin,
+ unsigned int port, unsigned int pin)
+{
+ if (port > NBR_OF_PORTS)
+ return -EINVAL;
+ if (port > crisv32_ioports[port].pin_count)
+ return -EINVAL;
+
+ iopin->bit = 1 << pin;
+ iopin->port = &crisv32_ioports[port];
+
+ if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio))
+ return -EIO;
+
+ return 0;
+}
+
+int crisv32_io_get_name(struct crisv32_iopin *iopin, const char *name)
+{
+ int port;
+ int pin;
+
+ if (toupper(*name) == 'P')
+ name++;
+
+ if (toupper(*name) < 'A' || toupper(*name) > 'E')
+ return -EINVAL;
+
+ port = toupper(*name) - 'A';
+ name++;
+ pin = simple_strtoul(name, NULL, 10);
+
+ if (pin < 0 || pin > crisv32_ioports[port].pin_count)
+ return -EINVAL;
+
+ iopin->bit = 1 << pin;
+ iopin->port = &crisv32_ioports[port];
+
+ if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio))
+ return -EIO;
+
+ return 0;
+}
+
+#ifdef CONFIG_PCI
+/* PCI I/O access stuff */
+struct cris_io_operations *cris_iops = NULL;
+EXPORT_SYMBOL(cris_iops);
+#endif
+
diff --git a/arch/cris/arch-v32/mach-a3/pinmux.c b/arch/cris/arch-v32/mach-a3/pinmux.c
new file mode 100644
index 00000000000..0a28c9bedfb
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/pinmux.c
@@ -0,0 +1,386 @@
+/*
+ * Allocator for I/O pins. All pins are allocated to GPIO at bootup.
+ * Unassigned pins and GPIO pins can be allocated to a fixed interface
+ * or the I/O processor instead.
+ *
+ * Copyright (c) 2005-2007 Axis Communications AB.
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/spinlock.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <pinmux.h>
+#include <hwregs/pinmux_defs.h>
+#include <hwregs/clkgen_defs.h>
+
+#undef DEBUG
+
+#define PINS 80
+#define PORT_PINS 32
+#define PORTS 3
+
+static char pins[PINS];
+static DEFINE_SPINLOCK(pinmux_lock);
+
+static void crisv32_pinmux_set(int port);
+
+int
+crisv32_pinmux_init(void)
+{
+ static int initialized;
+
+ if (!initialized) {
+ initialized = 1;
+ REG_WR_INT(pinmux, regi_pinmux, rw_hwprot, 0);
+ crisv32_pinmux_alloc(PORT_A, 0, 31, pinmux_gpio);
+ crisv32_pinmux_alloc(PORT_B, 0, 31, pinmux_gpio);
+ crisv32_pinmux_alloc(PORT_C, 0, 15, pinmux_gpio);
+ }
+
+ return 0;
+}
+
+int
+crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
+{
+ int i;
+ unsigned long flags;
+
+ crisv32_pinmux_init();
+
+ if (port >= PORTS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&pinmux_lock, flags);
+
+ for (i = first_pin; i <= last_pin; i++) {
+ if ((pins[port * PORT_PINS + i] != pinmux_none) &&
+ (pins[port * PORT_PINS + i] != pinmux_gpio) &&
+ (pins[port * PORT_PINS + i] != mode)) {
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+#ifdef DEBUG
+ panic("Pinmux alloc failed!\n");
+#endif
+ return -EPERM;
+ }
+ }
+
+ for (i = first_pin; i <= last_pin; i++)
+ pins[port * PORT_PINS + i] = mode;
+
+ crisv32_pinmux_set(port);
+
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+
+ return 0;
+}
+
+int
+crisv32_pinmux_alloc_fixed(enum fixed_function function)
+{
+ int ret = -EINVAL;
+ char saved[sizeof pins];
+ unsigned long flags;
+
+ spin_lock_irqsave(&pinmux_lock, flags);
+
+ /* Save internal data for recovery */
+ memcpy(saved, pins, sizeof pins);
+
+ crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
+
+ reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
+ reg_clkgen_rw_clk_ctrl clk_ctrl = REG_RD(clkgen, regi_clkgen,
+ rw_clk_ctrl);
+
+ switch (function) {
+ case pinmux_eth:
+ clk_ctrl.eth = regk_clkgen_yes;
+ clk_ctrl.dma0_1_eth = regk_clkgen_yes;
+ ret = crisv32_pinmux_alloc(PORT_B, 8, 23, pinmux_fixed);
+ ret |= crisv32_pinmux_alloc(PORT_B, 24, 25, pinmux_fixed);
+ hwprot.eth = hwprot.eth_mdio = regk_pinmux_yes;
+ break;
+ case pinmux_geth:
+ ret = crisv32_pinmux_alloc(PORT_B, 0, 7, pinmux_fixed);
+ hwprot.geth = regk_pinmux_yes;
+ break;
+ case pinmux_tg_cmos:
+ clk_ctrl.ccd_tg_100 = clk_ctrl.ccd_tg_200 = regk_clkgen_yes;
+ ret = crisv32_pinmux_alloc(PORT_B, 27, 29, pinmux_fixed);
+ hwprot.tg_clk = regk_pinmux_yes;
+ break;
+ case pinmux_tg_ccd:
+ clk_ctrl.ccd_tg_100 = clk_ctrl.ccd_tg_200 = regk_clkgen_yes;
+ ret = crisv32_pinmux_alloc(PORT_B, 27, 31, pinmux_fixed);
+ ret |= crisv32_pinmux_alloc(PORT_C, 0, 15, pinmux_fixed);
+ hwprot.tg = hwprot.tg_clk = regk_pinmux_yes;
+ break;
+ case pinmux_vout:
+ clk_ctrl.strdma0_2_video = regk_clkgen_yes;
+ ret = crisv32_pinmux_alloc(PORT_A, 8, 18, pinmux_fixed);
+ hwprot.vout = hwprot.vout_sync = regk_pinmux_yes;
+ break;
+ case pinmux_ser1:
+ clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
+ ret = crisv32_pinmux_alloc(PORT_A, 24, 25, pinmux_fixed);
+ hwprot.ser1 = regk_pinmux_yes;
+ break;
+ case pinmux_ser2:
+ clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
+ ret = crisv32_pinmux_alloc(PORT_A, 26, 27, pinmux_fixed);
+ hwprot.ser2 = regk_pinmux_yes;
+ break;
+ case pinmux_ser3:
+ clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
+ ret = crisv32_pinmux_alloc(PORT_A, 28, 29, pinmux_fixed);
+ hwprot.ser3 = regk_pinmux_yes;
+ break;
+ case pinmux_ser4:
+ clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
+ ret = crisv32_pinmux_alloc(PORT_A, 30, 31, pinmux_fixed);
+ hwprot.ser4 = regk_pinmux_yes;
+ break;
+ case pinmux_sser:
+ clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
+ ret = crisv32_pinmux_alloc(PORT_A, 19, 23, pinmux_fixed);
+ hwprot.sser = regk_pinmux_yes;
+ break;
+ case pinmux_pio:
+ hwprot.pio = regk_pinmux_yes;
+ ret = 0;
+ break;
+ case pinmux_pwm0:
+ ret = crisv32_pinmux_alloc(PORT_A, 30, 30, pinmux_fixed);
+ hwprot.pwm0 = regk_pinmux_yes;
+ break;
+ case pinmux_pwm1:
+ ret = crisv32_pinmux_alloc(PORT_A, 31, 31, pinmux_fixed);
+ hwprot.pwm1 = regk_pinmux_yes;
+ break;
+ case pinmux_pwm2:
+ ret = crisv32_pinmux_alloc(PORT_B, 26, 26, pinmux_fixed);
+ hwprot.pwm2 = regk_pinmux_yes;
+ break;
+ case pinmux_i2c0:
+ ret = crisv32_pinmux_alloc(PORT_A, 0, 1, pinmux_fixed);
+ hwprot.i2c0 = regk_pinmux_yes;
+ break;
+ case pinmux_i2c1:
+ ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
+ hwprot.i2c1 = regk_pinmux_yes;
+ break;
+ case pinmux_i2c1_3wire:
+ ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
+ ret |= crisv32_pinmux_alloc(PORT_A, 7, 7, pinmux_fixed);
+ hwprot.i2c1 = hwprot.i2c1_sen = regk_pinmux_yes;
+ break;
+ case pinmux_i2c1_sda1:
+ ret = crisv32_pinmux_alloc(PORT_A, 2, 4, pinmux_fixed);
+ hwprot.i2c1 = hwprot.i2c1_sda1 = regk_pinmux_yes;
+ break;
+ case pinmux_i2c1_sda2:
+ ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
+ ret |= crisv32_pinmux_alloc(PORT_A, 5, 5, pinmux_fixed);
+ hwprot.i2c1 = hwprot.i2c1_sda2 = regk_pinmux_yes;
+ break;
+ case pinmux_i2c1_sda3:
+ ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
+ ret |= crisv32_pinmux_alloc(PORT_A, 6, 6, pinmux_fixed);
+ hwprot.i2c1 = hwprot.i2c1_sda3 = regk_pinmux_yes;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (!ret) {
+ REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
+ REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
+ } else
+ memcpy(pins, saved, sizeof pins);
+
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+
+ return ret;
+}
+
+void
+crisv32_pinmux_set(int port)
+{
+ int i;
+ int gpio_val = 0;
+ int iop_val = 0;
+ int pin = port * PORT_PINS;
+
+ for (i = 0; (i < PORT_PINS) && (pin < PINS); i++, pin++) {
+ if (pins[pin] == pinmux_gpio)
+ gpio_val |= (1 << i);
+ else if (pins[pin] == pinmux_iop)
+ iop_val |= (1 << i);
+ }
+
+ REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_gio_pa + 4 * port,
+ gpio_val);
+ REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_iop_pa + 4 * port,
+ iop_val);
+
+#ifdef DEBUG
+ crisv32_pinmux_dump();
+#endif
+}
+
+int
+crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
+{
+ int i;
+ unsigned long flags;
+
+ crisv32_pinmux_init();
+
+ if (port > PORTS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&pinmux_lock, flags);
+
+ for (i = first_pin; i <= last_pin; i++)
+ pins[port * PORT_PINS + i] = pinmux_none;
+
+ crisv32_pinmux_set(port);
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+
+ return 0;
+}
+
+int
+crisv32_pinmux_dealloc_fixed(enum fixed_function function)
+{
+ int ret = -EINVAL;
+ char saved[sizeof pins];
+ unsigned long flags;
+
+ spin_lock_irqsave(&pinmux_lock, flags);
+
+ /* Save internal data for recovery */
+ memcpy(saved, pins, sizeof pins);
+
+ crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
+
+ reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
+
+ switch (function) {
+ case pinmux_eth:
+ ret = crisv32_pinmux_dealloc(PORT_B, 8, 23);
+ ret |= crisv32_pinmux_dealloc(PORT_B, 24, 25);
+ ret |= crisv32_pinmux_dealloc(PORT_B, 0, 7);
+ hwprot.eth = hwprot.eth_mdio = hwprot.geth = regk_pinmux_no;
+ break;
+ case pinmux_tg_cmos:
+ ret = crisv32_pinmux_dealloc(PORT_B, 27, 29);
+ hwprot.tg_clk = regk_pinmux_no;
+ break;
+ case pinmux_tg_ccd:
+ ret = crisv32_pinmux_dealloc(PORT_B, 27, 31);
+ ret |= crisv32_pinmux_dealloc(PORT_C, 0, 15);
+ hwprot.tg = hwprot.tg_clk = regk_pinmux_no;
+ break;
+ case pinmux_vout:
+ ret = crisv32_pinmux_dealloc(PORT_A, 8, 18);
+ hwprot.vout = hwprot.vout_sync = regk_pinmux_no;
+ break;
+ case pinmux_ser1:
+ ret = crisv32_pinmux_dealloc(PORT_A, 24, 25);
+ hwprot.ser1 = regk_pinmux_no;
+ break;
+ case pinmux_ser2:
+ ret = crisv32_pinmux_dealloc(PORT_A, 26, 27);
+ hwprot.ser2 = regk_pinmux_no;
+ break;
+ case pinmux_ser3:
+ ret = crisv32_pinmux_dealloc(PORT_A, 28, 29);
+ hwprot.ser3 = regk_pinmux_no;
+ break;
+ case pinmux_ser4:
+ ret = crisv32_pinmux_dealloc(PORT_A, 30, 31);
+ hwprot.ser4 = regk_pinmux_no;
+ break;
+ case pinmux_sser:
+ ret = crisv32_pinmux_dealloc(PORT_A, 19, 23);
+ hwprot.sser = regk_pinmux_no;
+ break;
+ case pinmux_pwm0:
+ ret = crisv32_pinmux_dealloc(PORT_A, 30, 30);
+ hwprot.pwm0 = regk_pinmux_no;
+ break;
+ case pinmux_pwm1:
+ ret = crisv32_pinmux_dealloc(PORT_A, 31, 31);
+ hwprot.pwm1 = regk_pinmux_no;
+ break;
+ case pinmux_pwm2:
+ ret = crisv32_pinmux_dealloc(PORT_B, 26, 26);
+ hwprot.pwm2 = regk_pinmux_no;
+ break;
+ case pinmux_i2c0:
+ ret = crisv32_pinmux_dealloc(PORT_A, 0, 1);
+ hwprot.i2c0 = regk_pinmux_no;
+ break;
+ case pinmux_i2c1:
+ ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
+ hwprot.i2c1 = regk_pinmux_no;
+ break;
+ case pinmux_i2c1_3wire:
+ ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
+ ret |= crisv32_pinmux_dealloc(PORT_A, 7, 7);
+ hwprot.i2c1 = hwprot.i2c1_sen = regk_pinmux_no;
+ break;
+ case pinmux_i2c1_sda1:
+ ret = crisv32_pinmux_dealloc(PORT_A, 2, 4);
+ hwprot.i2c1_sda1 = regk_pinmux_no;
+ break;
+ case pinmux_i2c1_sda2:
+ ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
+ ret |= crisv32_pinmux_dealloc(PORT_A, 5, 5);
+ hwprot.i2c1_sda2 = regk_pinmux_no;
+ break;
+ case pinmux_i2c1_sda3:
+ ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
+ ret |= crisv32_pinmux_dealloc(PORT_A, 6, 6);
+ hwprot.i2c1_sda3 = regk_pinmux_no;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (!ret)
+ REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
+ else
+ memcpy(pins, saved, sizeof pins);
+
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+
+ return ret;
+}
+
+void
+crisv32_pinmux_dump(void)
+{
+ int i, j;
+ int pin = 0;
+
+ crisv32_pinmux_init();
+
+ for (i = 0; i < PORTS; i++) {
+ pin++;
+ printk(KERN_DEBUG "Port %c\n", 'A'+i);
+ for (j = 0; (j < PORT_PINS) && (pin < PINS); j++, pin++)
+ printk(KERN_DEBUG
+ " Pin %d = %d\n", j, pins[i * PORT_PINS + j]);
+ }
+}
+
+__initcall(crisv32_pinmux_init);
diff --git a/arch/cris/arch-v32/mach-a3/vcs_hook.c b/arch/cris/arch-v32/mach-a3/vcs_hook.c
new file mode 100644
index 00000000000..58b1a5469fd
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/vcs_hook.c
@@ -0,0 +1,103 @@
+/*
+ * Simulator hook mechanism
+ */
+
+#include "vcs_hook.h"
+#include <asm/io.h>
+#include <stdarg.h>
+
+#define HOOK_TRIG_ADDR 0xb7000000
+#define HOOK_MEM_BASE_ADDR 0xce000000
+
+static volatile unsigned *hook_base;
+
+#define HOOK_DATA(offset) hook_base[offset]
+#define VHOOK_DATA(offset) hook_base[offset]
+#define HOOK_TRIG(funcid) \
+ do { \
+ *((unsigned *) HOOK_TRIG_ADDR) = funcid; \
+ } while (0)
+#define HOOK_DATA_BYTE(offset) ((unsigned char *)hook_base)[offset]
+
+static void hook_init(void)
+{
+ static int first = 1;
+ if (first) {
+ first = 0;
+ hook_base = ioremap(HOOK_MEM_BASE_ADDR, 8192);
+ }
+}
+
+static unsigned hook_trig(unsigned id)
+{
+ unsigned ret;
+
+ /* preempt_disable(); */
+
+ /* Dummy read from mem to make sure data has propagated to memory
+ * before trigging */
+ ret = *hook_base;
+
+ /* trigger hook */
+ HOOK_TRIG(id);
+
+ /* wait for call to finish */
+ while (VHOOK_DATA(0) > 0) ;
+
+ /* extract return value */
+
+ ret = VHOOK_DATA(1);
+
+ return ret;
+}
+
+int hook_call(unsigned id, unsigned pcnt, ...)
+{
+ va_list ap;
+ int i;
+ unsigned ret;
+
+ hook_init();
+
+ HOOK_DATA(0) = id;
+
+ va_start(ap, pcnt);
+ for (i = 1; i <= pcnt; i++)
+ HOOK_DATA(i) = va_arg(ap, unsigned);
+ va_end(ap);
+
+ ret = hook_trig(id);
+
+ return ret;
+}
+
+int hook_call_str(unsigned id, unsigned size, const char *str)
+{
+ int i;
+ unsigned ret;
+
+ hook_init();
+
+ HOOK_DATA(0) = id;
+ HOOK_DATA(1) = size;
+
+ for (i = 0; i < size; i++)
+ HOOK_DATA_BYTE(8 + i) = str[i];
+ HOOK_DATA_BYTE(8 + i) = 0;
+
+ ret = hook_trig(id);
+
+ return ret;
+}
+
+void print_str(const char *str)
+{
+ int i;
+ /* find null at end of string */
+ for (i = 1; str[i]; i++) ;
+ hook_call(hook_print_str, i, str);
+}
+
+void CPU_WATCHDOG_TIMEOUT(unsigned t)
+{
+}
diff --git a/arch/cris/arch-v32/mach-a3/vcs_hook.h b/arch/cris/arch-v32/mach-a3/vcs_hook.h
new file mode 100644
index 00000000000..8b73d0e8392
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/vcs_hook.h
@@ -0,0 +1,58 @@
+/*
+ * Simulator hook call mechanism
+ */
+
+#ifndef __hook_h__
+#define __hook_h__
+
+int hook_call(unsigned id, unsigned pcnt, ...);
+int hook_call_str(unsigned id, unsigned size, const char *str);
+
+enum hook_ids {
+ hook_debug_on = 1,
+ hook_debug_off,
+ hook_stop_sim_ok,
+ hook_stop_sim_fail,
+ hook_alloc_shared,
+ hook_ptr_shared,
+ hook_free_shared,
+ hook_file2shared,
+ hook_cmp_shared,
+ hook_print_params,
+ hook_sim_time,
+ hook_stop_sim,
+ hook_kick_dog,
+ hook_dog_timeout,
+ hook_rand,
+ hook_srand,
+ hook_rand_range,
+ hook_print_str,
+ hook_print_hex,
+ hook_cmp_offset_shared,
+ hook_fill_random_shared,
+ hook_alloc_random_data,
+ hook_calloc_random_data,
+ hook_print_int,
+ hook_print_uint,
+ hook_fputc,
+ hook_init_fd,
+ hook_sbrk,
+ hook_print_context_descr,
+ hook_print_data_descr,
+ hook_print_group_descr,
+ hook_fill_shared,
+ hook_sl_srand,
+ hook_sl_rand_irange,
+ hook_sl_rand_urange,
+ hook_sl_sh_malloc_aligned,
+ hook_sl_sh_calloc_aligned,
+ hook_sl_sh_alloc_random_data,
+ hook_sl_sh_file2mem,
+ hook_sl_vera_mbox_handle,
+ hook_sl_vera_mbox_put,
+ hook_sl_vera_mbox_get,
+ hook_sl_system,
+ hook_sl_sh_hexdump
+};
+
+#endif
diff --git a/arch/cris/arch-v32/mach-fs/Kconfig b/arch/cris/arch-v32/mach-fs/Kconfig
new file mode 100644
index 00000000000..f6d74475f1c
--- /dev/null
+++ b/arch/cris/arch-v32/mach-fs/Kconfig
@@ -0,0 +1,216 @@
+if ETRAXFS
+
+menu "ETRAX FS options"
+ depends on ETRAXFS
+
+config ETRAX_DRAM_VIRTUAL_BASE
+ hex
+ depends on ETRAX_ARCH_V32
+ default "c0000000"
+
+config ETRAX_SERIAL_PORTS
+ int
+ default 4
+
+config ETRAX_MEM_GRP1_CONFIG
+ hex "MEM_GRP1_CONFIG"
+ depends on ETRAX_ARCH_V32
+ default "4044a"
+ help
+ Waitstates for flash. The default value is suitable for the
+ standard flashes used in axis products (120 ns).
+
+config ETRAX_MEM_GRP2_CONFIG
+ hex "MEM_GRP2_CONFIG"
+ depends on ETRAX_ARCH_V32
+ default "0"
+ help
+ Waitstates for SRAM. 0 is a good choice for most Axis products.
+
+config ETRAX_MEM_GRP3_CONFIG
+ hex "MEM_GRP3_CONFIG"
+ depends on ETRAX_ARCH_V32
+ default "0"
+ help
+ Waitstates for CSP0-3. 0 is a good choice for most Axis products.
+ It may need to be changed if external devices such as extra
+ register-mapped LEDs are used.
+
+config ETRAX_MEM_GRP4_CONFIG
+ hex "MEM_GRP4_CONFIG"
+ depends on ETRAX_ARCH_V32
+ default "0"
+ help
+ Waitstates for CSP4-6. 0 is a good choice for most Axis products.
+
+config ETRAX_SDRAM_GRP0_CONFIG
+ hex "SDRAM_GRP0_CONFIG"
+ depends on ETRAX_ARCH_V32
+ default "336"
+ help
+ SDRAM configuration for group 0. The value depends on the
+ hardware configuration. The default value is suitable
+ for 32 MB organized as two 16 bits chips (e.g. Axis
+ part number 18550) connected as one 32 bit device (i.e. in
+ the same group).
+
+config ETRAX_SDRAM_GRP1_CONFIG
+ hex "SDRAM_GRP1_CONFIG"
+ depends on ETRAX_ARCH_V32
+ default "0"
+ help
+ SDRAM configuration for group 1. The defult value is 0
+ because group 1 is not used in the default configuration,
+ described in the help for SDRAM_GRP0_CONFIG.
+
+config ETRAX_SDRAM_TIMING
+ hex "SDRAM_TIMING"
+ depends on ETRAX_ARCH_V32
+ default "104a"
+ help
+ SDRAM timing parameters. The default value is ok for
+ most hardwares but large SDRAMs may require a faster
+ refresh (a.k.a 8K refresh). The default value implies
+ 100MHz clock and SDR mode.
+
+config ETRAX_SDRAM_COMMAND
+ hex "SDRAM_COMMAND"
+ depends on ETRAX_ARCH_V32
+ default "0"
+ help
+ SDRAM command. Should be 0 unless you really know what
+ you are doing (may be != 0 for unusual address line
+ mappings such as in a MCM)..
+
+config ETRAX_DEF_GIO_PA_OE
+ hex "GIO_PA_OE"
+ depends on ETRAX_ARCH_V32
+ default "1c"
+ help
+ Configures the direction of general port A bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used.
+ There are some guidelines though - if you know that only LED's are
+ connected to port PA, then they are usually connected to bits 2-4
+ and you can therefore use 1c. On other boards which don't have the
+ LED's at the general ports, these bits are used for all kinds of
+ stuff. If you don't know what to use, it is always safe to put all
+ as inputs, although floating inputs isn't good.
+
+config ETRAX_DEF_GIO_PA_OUT
+ hex "GIO_PA_OUT"
+ depends on ETRAX_ARCH_V32
+ default "00"
+ help
+ Configures the initial data for the general port A bits. Most
+ products should use 00 here.
+
+config ETRAX_DEF_GIO_PB_OE
+ hex "GIO_PB_OE"
+ depends on ETRAX_ARCH_V32
+ default "00000"
+ help
+ Configures the direction of general port B bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used.
+ There are some guidelines though - if you know that only LED's are
+ connected to port PA, then they are usually connected to bits 2-4
+ and you can therefore use 1c. On other boards which don't have the
+ LED's at the general ports, these bits are used for all kinds of
+ stuff. If you don't know what to use, it is always safe to put all
+ as inputs, although floating inputs isn't good.
+
+config ETRAX_DEF_GIO_PB_OUT
+ hex "GIO_PB_OUT"
+ depends on ETRAX_ARCH_V32
+ default "00000"
+ help
+ Configures the initial data for the general port B bits. Most
+ products should use 00000 here.
+
+config ETRAX_DEF_GIO_PC_OE
+ hex "GIO_PC_OE"
+ depends on ETRAX_ARCH_V32
+ default "00000"
+ help
+ Configures the direction of general port C bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used.
+ There are some guidelines though - if you know that only LED's are
+ connected to port PA, then they are usually connected to bits 2-4
+ and you can therefore use 1c. On other boards which don't have the
+ LED's at the general ports, these bits are used for all kinds of
+ stuff. If you don't know what to use, it is always safe to put all
+ as inputs, although floating inputs isn't good.
+
+config ETRAX_DEF_GIO_PC_OUT
+ hex "GIO_PC_OUT"
+ depends on ETRAX_ARCH_V32
+ default "00000"
+ help
+ Configures the initial data for the general port C bits. Most
+ products should use 00000 here.
+
+config ETRAX_DEF_GIO_PD_OE
+ hex "GIO_PD_OE"
+ depends on ETRAX_ARCH_V32
+ default "00000"
+ help
+ Configures the direction of general port D bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used.
+ There are some guidelines though - if you know that only LED's are
+ connected to port PA, then they are usually connected to bits 2-4
+ and you can therefore use 1c. On other boards which don't have the
+ LED's at the general ports, these bits are used for all kinds of
+ stuff. If you don't know what to use, it is always safe to put all
+ as inputs, although floating inputs isn't good.
+
+config ETRAX_DEF_GIO_PD_OUT
+ hex "GIO_PD_OUT"
+ depends on ETRAX_ARCH_V32
+ default "00000"
+ help
+ Configures the initial data for the general port D bits. Most
+ products should use 00000 here.
+
+config ETRAX_DEF_GIO_PE_OE
+ hex "GIO_PE_OE"
+ depends on ETRAX_ARCH_V32
+ default "00000"
+ help
+ Configures the direction of general port E bits. 1 is out, 0 is in.
+ This is often totally different depending on the product used.
+ There are some guidelines though - if you know that only LED's are
+ connected to port PA, then they are usually connected to bits 2-4
+ and you can therefore use 1c. On other boards which don't have the
+ LED's at the general ports, these bits are used for all kinds of
+ stuff. If you don't know what to use, it is always safe to put all
+ as inputs, although floating inputs isn't good.
+
+config ETRAX_DEF_GIO_PE_OUT
+ hex "GIO_PE_OUT"
+ depends on ETRAX_ARCH_V32
+ default "00000"
+ help
+ Configures the initial data for the general port E bits. Most
+ products should use 00000 here.
+
+config ETRAX_DEF_GIO_PV_OE
+ hex "GIO_PV_OE"
+ depends on ETRAX_VIRTUAL_GPIO
+ default "0000"
+ help
+ Configures the direction of virtual general port V bits. 1 is out,
+ 0 is in. This is often totally different depending on the product
+ used. These bits are used for all kinds of stuff. If you don't know
+ what to use, it is always safe to put all as inputs, although
+ floating inputs isn't good.
+
+config ETRAX_DEF_GIO_PV_OUT
+ hex "GIO_PV_OUT"
+ depends on ETRAX_VIRTUAL_GPIO
+ default "0000"
+ help
+ Configures the initial data for the virtual general port V bits.
+ Most products should use 0000 here.
+
+endmenu
+
+endif
diff --git a/arch/cris/arch-v32/mach-fs/Makefile b/arch/cris/arch-v32/mach-fs/Makefile
new file mode 100644
index 00000000000..4ff407a1b93
--- /dev/null
+++ b/arch/cris/arch-v32/mach-fs/Makefile
@@ -0,0 +1,11 @@
+# $Id: Makefile,v 1.3 2007/03/13 11:57:46 starvik Exp $
+#
+# Makefile for the linux kernel.
+#
+
+obj-y := dma.o pinmux.o io.o arbiter.o
+bj-$(CONFIG_ETRAX_VCS_SIM) += vcs_hook.o
+obj-$(CONFIG_CPU_FREQ) += cpufreq.o
+
+clean:
+
diff --git a/arch/cris/arch-v32/mach-fs/arbiter.c b/arch/cris/arch-v32/mach-fs/arbiter.c
new file mode 100644
index 00000000000..84d31bd7b69
--- /dev/null
+++ b/arch/cris/arch-v32/mach-fs/arbiter.c
@@ -0,0 +1,404 @@
+/*
+ * Memory arbiter functions. Allocates bandwidth through the
+ * arbiter and sets up arbiter breakpoints.
+ *
+ * The algorithm first assigns slots to the clients that has specified
+ * bandwidth (e.g. ethernet) and then the remaining slots are divided
+ * on all the active clients.
+ *
+ * Copyright (c) 2004-2007 Axis Communications AB.
+ */
+
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/marb_defs.h>
+#include <arbiter.h>
+#include <hwregs/intr_vect.h>
+#include <linux/interrupt.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/irq_regs.h>
+
+struct crisv32_watch_entry {
+ unsigned long instance;
+ watch_callback *cb;
+ unsigned long start;
+ unsigned long end;
+ int used;
+};
+
+#define NUMBER_OF_BP 4
+#define NBR_OF_CLIENTS 14
+#define NBR_OF_SLOTS 64
+#define SDRAM_BANDWIDTH 100000000 /* Some kind of expected value */
+#define INTMEM_BANDWIDTH 400000000
+#define NBR_OF_REGIONS 2
+
+static struct crisv32_watch_entry watches[NUMBER_OF_BP] = {
+ {regi_marb_bp0},
+ {regi_marb_bp1},
+ {regi_marb_bp2},
+ {regi_marb_bp3}
+};
+
+static u8 requested_slots[NBR_OF_REGIONS][NBR_OF_CLIENTS];
+static u8 active_clients[NBR_OF_REGIONS][NBR_OF_CLIENTS];
+static int max_bandwidth[NBR_OF_REGIONS] =
+ { SDRAM_BANDWIDTH, INTMEM_BANDWIDTH };
+
+DEFINE_SPINLOCK(arbiter_lock);
+
+static irqreturn_t crisv32_arbiter_irq(int irq, void *dev_id);
+
+/*
+ * "I'm the arbiter, I know the score.
+ * From square one I'll be watching all 64."
+ * (memory arbiter slots, that is)
+ *
+ * Or in other words:
+ * Program the memory arbiter slots for "region" according to what's
+ * in requested_slots[] and active_clients[], while minimizing
+ * latency. A caller may pass a non-zero positive amount for
+ * "unused_slots", which must then be the unallocated, remaining
+ * number of slots, free to hand out to any client.
+ */
+
+static void crisv32_arbiter_config(int region, int unused_slots)
+{
+ int slot;
+ int client;
+ int interval = 0;
+
+ /*
+ * This vector corresponds to the hardware arbiter slots (see
+ * the hardware documentation for semantics). We initialize
+ * each slot with a suitable sentinel value outside the valid
+ * range {0 .. NBR_OF_CLIENTS - 1} and replace them with
+ * client indexes. Then it's fed to the hardware.
+ */
+ s8 val[NBR_OF_SLOTS];
+
+ for (slot = 0; slot < NBR_OF_SLOTS; slot++)
+ val[slot] = -1;
+
+ for (client = 0; client < NBR_OF_CLIENTS; client++) {
+ int pos;
+ /* Allocate the requested non-zero number of slots, but
+ * also give clients with zero-requests one slot each
+ * while stocks last. We do the latter here, in client
+ * order. This makes sure zero-request clients are the
+ * first to get to any spare slots, else those slots
+ * could, when bandwidth is allocated close to the limit,
+ * all be allocated to low-index non-zero-request clients
+ * in the default-fill loop below. Another positive but
+ * secondary effect is a somewhat better spread of the
+ * zero-bandwidth clients in the vector, avoiding some of
+ * the latency that could otherwise be caused by the
+ * partitioning of non-zero-bandwidth clients at low
+ * indexes and zero-bandwidth clients at high
+ * indexes. (Note that this spreading can only affect the
+ * unallocated bandwidth.) All the above only matters for
+ * memory-intensive situations, of course.
+ */
+ if (!requested_slots[region][client]) {
+ /*
+ * Skip inactive clients. Also skip zero-slot
+ * allocations in this pass when there are no known
+ * free slots.
+ */
+ if (!active_clients[region][client]
+ || unused_slots <= 0)
+ continue;
+
+ unused_slots--;
+
+ /* Only allocate one slot for this client. */
+ interval = NBR_OF_SLOTS;
+ } else
+ interval =
+ NBR_OF_SLOTS / requested_slots[region][client];
+
+ pos = 0;
+ while (pos < NBR_OF_SLOTS) {
+ if (val[pos] >= 0)
+ pos++;
+ else {
+ val[pos] = client;
+ pos += interval;
+ }
+ }
+ }
+
+ client = 0;
+ for (slot = 0; slot < NBR_OF_SLOTS; slot++) {
+ /*
+ * Allocate remaining slots in round-robin
+ * client-number order for active clients. For this
+ * pass, we ignore requested bandwidth and previous
+ * allocations.
+ */
+ if (val[slot] < 0) {
+ int first = client;
+ while (!active_clients[region][client]) {
+ client = (client + 1) % NBR_OF_CLIENTS;
+ if (client == first)
+ break;
+ }
+ val[slot] = client;
+ client = (client + 1) % NBR_OF_CLIENTS;
+ }
+ if (region == EXT_REGION)
+ REG_WR_INT_VECT(marb, regi_marb, rw_ext_slots, slot,
+ val[slot]);
+ else if (region == INT_REGION)
+ REG_WR_INT_VECT(marb, regi_marb, rw_int_slots, slot,
+ val[slot]);
+ }
+}
+
+extern char _stext, _etext;
+
+static void crisv32_arbiter_init(void)
+{
+ static int initialized;
+
+ if (initialized)
+ return;
+
+ initialized = 1;
+
+ /*
+ * CPU caches are always set to active, but with zero
+ * bandwidth allocated. It should be ok to allocate zero
+ * bandwidth for the caches, because DMA for other channels
+ * will supposedly finish, once their programmed amount is
+ * done, and then the caches will get access according to the
+ * "fixed scheme" for unclaimed slots. Though, if for some
+ * use-case somewhere, there's a maximum CPU latency for
+ * e.g. some interrupt, we have to start allocating specific
+ * bandwidth for the CPU caches too.
+ */
+ active_clients[EXT_REGION][10] = active_clients[EXT_REGION][11] = 1;
+ crisv32_arbiter_config(EXT_REGION, 0);
+ crisv32_arbiter_config(INT_REGION, 0);
+
+ if (request_irq(MEMARB_INTR_VECT, crisv32_arbiter_irq, IRQF_DISABLED,
+ "arbiter", NULL))
+ printk(KERN_ERR "Couldn't allocate arbiter IRQ\n");
+
+#ifndef CONFIG_ETRAX_KGDB
+ /* Global watch for writes to kernel text segment. */
+ crisv32_arbiter_watch(virt_to_phys(&_stext), &_etext - &_stext,
+ arbiter_all_clients, arbiter_all_write, NULL);
+#endif
+}
+
+/* Main entry for bandwidth allocation. */
+
+int crisv32_arbiter_allocate_bandwidth(int client, int region,
+ unsigned long bandwidth)
+{
+ int i;
+ int total_assigned = 0;
+ int total_clients = 0;
+ int req;
+
+ crisv32_arbiter_init();
+
+ for (i = 0; i < NBR_OF_CLIENTS; i++) {
+ total_assigned += requested_slots[region][i];
+ total_clients += active_clients[region][i];
+ }
+
+ /* Avoid division by 0 for 0-bandwidth requests. */
+ req = bandwidth == 0
+ ? 0 : NBR_OF_SLOTS / (max_bandwidth[region] / bandwidth);
+
+ /*
+ * We make sure that there are enough slots only for non-zero
+ * requests. Requesting 0 bandwidth *may* allocate slots,
+ * though if all bandwidth is allocated, such a client won't
+ * get any and will have to rely on getting memory access
+ * according to the fixed scheme that's the default when one
+ * of the slot-allocated clients doesn't claim their slot.
+ */
+ if (total_assigned + req > NBR_OF_SLOTS)
+ return -ENOMEM;
+
+ active_clients[region][client] = 1;
+ requested_slots[region][client] = req;
+ crisv32_arbiter_config(region, NBR_OF_SLOTS - total_assigned);
+
+ return 0;
+}
+
+/*
+ * Main entry for bandwidth deallocation.
+ *
+ * Strictly speaking, for a somewhat constant set of clients where
+ * each client gets a constant bandwidth and is just enabled or
+ * disabled (somewhat dynamically), no action is necessary here to
+ * avoid starvation for non-zero-allocation clients, as the allocated
+ * slots will just be unused. However, handing out those unused slots
+ * to active clients avoids needless latency if the "fixed scheme"
+ * would give unclaimed slots to an eager low-index client.
+ */
+
+void crisv32_arbiter_deallocate_bandwidth(int client, int region)
+{
+ int i;
+ int total_assigned = 0;
+
+ requested_slots[region][client] = 0;
+ active_clients[region][client] = 0;
+
+ for (i = 0; i < NBR_OF_CLIENTS; i++)
+ total_assigned += requested_slots[region][i];
+
+ crisv32_arbiter_config(region, NBR_OF_SLOTS - total_assigned);
+}
+
+int crisv32_arbiter_watch(unsigned long start, unsigned long size,
+ unsigned long clients, unsigned long accesses,
+ watch_callback *cb)
+{
+ int i;
+
+ crisv32_arbiter_init();
+
+ if (start > 0x80000000) {
+ printk(KERN_ERR "Arbiter: %lX doesn't look like a "
+ "physical address", start);
+ return -EFAULT;
+ }
+
+ spin_lock(&arbiter_lock);
+
+ for (i = 0; i < NUMBER_OF_BP; i++) {
+ if (!watches[i].used) {
+ reg_marb_rw_intr_mask intr_mask =
+ REG_RD(marb, regi_marb, rw_intr_mask);
+
+ watches[i].used = 1;
+ watches[i].start = start;
+ watches[i].end = start + size;
+ watches[i].cb = cb;
+
+ REG_WR_INT(marb_bp, watches[i].instance, rw_first_addr,
+ watches[i].start);
+ REG_WR_INT(marb_bp, watches[i].instance, rw_last_addr,
+ watches[i].end);
+ REG_WR_INT(marb_bp, watches[i].instance, rw_op,
+ accesses);
+ REG_WR_INT(marb_bp, watches[i].instance, rw_clients,
+ clients);
+
+ if (i == 0)
+ intr_mask.bp0 = regk_marb_yes;
+ else if (i == 1)
+ intr_mask.bp1 = regk_marb_yes;
+ else if (i == 2)
+ intr_mask.bp2 = regk_marb_yes;
+ else if (i == 3)
+ intr_mask.bp3 = regk_marb_yes;
+
+ REG_WR(marb, regi_marb, rw_intr_mask, intr_mask);
+ spin_unlock(&arbiter_lock);
+
+ return i;
+ }
+ }
+ spin_unlock(&arbiter_lock);
+ return -ENOMEM;
+}
+
+int crisv32_arbiter_unwatch(int id)
+{
+ reg_marb_rw_intr_mask intr_mask = REG_RD(marb, regi_marb, rw_intr_mask);
+
+ crisv32_arbiter_init();
+
+ spin_lock(&arbiter_lock);
+
+ if ((id < 0) || (id >= NUMBER_OF_BP) || (!watches[id].used)) {
+ spin_unlock(&arbiter_lock);
+ return -EINVAL;
+ }
+
+ memset(&watches[id], 0, sizeof(struct crisv32_watch_entry));
+
+ if (id == 0)
+ intr_mask.bp0 = regk_marb_no;
+ else if (id == 1)
+ intr_mask.bp2 = regk_marb_no;
+ else if (id == 2)
+ intr_mask.bp2 = regk_marb_no;
+ else if (id == 3)
+ intr_mask.bp3 = regk_marb_no;
+
+ REG_WR(marb, regi_marb, rw_intr_mask, intr_mask);
+
+ spin_unlock(&arbiter_lock);
+ return 0;
+}
+
+extern void show_registers(struct pt_regs *regs);
+
+static irqreturn_t crisv32_arbiter_irq(int irq, void *dev_id)
+{
+ reg_marb_r_masked_intr masked_intr =
+ REG_RD(marb, regi_marb, r_masked_intr);
+ reg_marb_bp_r_brk_clients r_clients;
+ reg_marb_bp_r_brk_addr r_addr;
+ reg_marb_bp_r_brk_op r_op;
+ reg_marb_bp_r_brk_first_client r_first;
+ reg_marb_bp_r_brk_size r_size;
+ reg_marb_bp_rw_ack ack = { 0 };
+ reg_marb_rw_ack_intr ack_intr = {
+ .bp0 = 1, .bp1 = 1, .bp2 = 1, .bp3 = 1
+ };
+ struct crisv32_watch_entry *watch;
+
+ if (masked_intr.bp0) {
+ watch = &watches[0];
+ ack_intr.bp0 = regk_marb_yes;
+ } else if (masked_intr.bp1) {
+ watch = &watches[1];
+ ack_intr.bp1 = regk_marb_yes;
+ } else if (masked_intr.bp2) {
+ watch = &watches[2];
+ ack_intr.bp2 = regk_marb_yes;
+ } else if (masked_intr.bp3) {
+ watch = &watches[3];
+ ack_intr.bp3 = regk_marb_yes;
+ } else {
+ return IRQ_NONE;
+ }
+
+ /* Retrieve all useful information and print it. */
+ r_clients = REG_RD(marb_bp, watch->instance, r_brk_clients);
+ r_addr = REG_RD(marb_bp, watch->instance, r_brk_addr);
+ r_op = REG_RD(marb_bp, watch->instance, r_brk_op);
+ r_first = REG_RD(marb_bp, watch->instance, r_brk_first_client);
+ r_size = REG_RD(marb_bp, watch->instance, r_brk_size);
+
+ printk(KERN_INFO "Arbiter IRQ\n");
+ printk(KERN_INFO "Clients %X addr %X op %X first %X size %X\n",
+ REG_TYPE_CONV(int, reg_marb_bp_r_brk_clients, r_clients),
+ REG_TYPE_CONV(int, reg_marb_bp_r_brk_addr, r_addr),
+ REG_TYPE_CONV(int, reg_marb_bp_r_brk_op, r_op),
+ REG_TYPE_CONV(int, reg_marb_bp_r_brk_first_client, r_first),
+ REG_TYPE_CONV(int, reg_marb_bp_r_brk_size, r_size));
+
+ REG_WR(marb_bp, watch->instance, rw_ack, ack);
+ REG_WR(marb, regi_marb, rw_ack_intr, ack_intr);
+
+ printk(KERN_INFO "IRQ occured at %lX\n", get_irq_regs()->erp);
+
+ if (watch->cb)
+ watch->cb();
+
+ return IRQ_HANDLED;
+}
diff --git a/arch/cris/arch-v32/mach-fs/cpufreq.c b/arch/cris/arch-v32/mach-fs/cpufreq.c
new file mode 100644
index 00000000000..d57631c0d8d
--- /dev/null
+++ b/arch/cris/arch-v32/mach-fs/cpufreq.c
@@ -0,0 +1,146 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <hwregs/reg_map.h>
+#include <asm/arch/hwregs/reg_rdwr.h>
+#include <asm/arch/hwregs/config_defs.h>
+#include <asm/arch/hwregs/bif_core_defs.h>
+
+static int
+cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val,
+ void *data);
+
+static struct notifier_block cris_sdram_freq_notifier_block = {
+ .notifier_call = cris_sdram_freq_notifier
+};
+
+static struct cpufreq_frequency_table cris_freq_table[] = {
+ {0x01, 6000},
+ {0x02, 200000},
+ {0, CPUFREQ_TABLE_END},
+};
+
+static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
+{
+ reg_config_rw_clk_ctrl clk_ctrl;
+ clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl);
+ return clk_ctrl.pll ? 200000 : 6000;
+}
+
+static void cris_freq_set_cpu_state(unsigned int state)
+{
+ int i;
+ struct cpufreq_freqs freqs;
+ reg_config_rw_clk_ctrl clk_ctrl;
+ clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl);
+
+ for_each_possible_cpu(i) {
+ freqs.old = cris_freq_get_cpu_frequency(i);
+ freqs.new = cris_freq_table[state].frequency;
+ freqs.cpu = i;
+ }
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ local_irq_disable();
+
+ /* Even though we may be SMP they will share the same clock
+ * so all settings are made on CPU0. */
+ if (cris_freq_table[state].frequency == 200000)
+ clk_ctrl.pll = 1;
+ else
+ clk_ctrl.pll = 0;
+ REG_WR(config, regi_config, rw_clk_ctrl, clk_ctrl);
+
+ local_irq_enable();
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+};
+
+static int cris_freq_verify(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]);
+}
+
+static int cris_freq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq, unsigned int relation)
+{
+ unsigned int newstate = 0;
+
+ if (cpufreq_frequency_table_target
+ (policy, cris_freq_table, target_freq, relation, &newstate))
+ return -EINVAL;
+
+ cris_freq_set_cpu_state(newstate);
+
+ return 0;
+}
+
+static int cris_freq_cpu_init(struct cpufreq_policy *policy)
+{
+ int result;
+
+ /* cpuinfo and default policy values */
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+ policy->cpuinfo.transition_latency = 1000000; /* 1ms */
+ policy->cur = cris_freq_get_cpu_frequency(0);
+
+ result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table);
+ if (result)
+ return (result);
+
+ cpufreq_frequency_table_get_attr(cris_freq_table, policy->cpu);
+
+ return 0;
+}
+
+static int cris_freq_cpu_exit(struct cpufreq_policy *policy)
+{
+ cpufreq_frequency_table_put_attr(policy->cpu);
+ return 0;
+}
+
+static struct freq_attr *cris_freq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static struct cpufreq_driver cris_freq_driver = {
+ .get = cris_freq_get_cpu_frequency,
+ .verify = cris_freq_verify,
+ .target = cris_freq_target,
+ .init = cris_freq_cpu_init,
+ .exit = cris_freq_cpu_exit,
+ .name = "cris_freq",
+ .owner = THIS_MODULE,
+ .attr = cris_freq_attr,
+};
+
+static int __init cris_freq_init(void)
+{
+ int ret;
+ ret = cpufreq_register_driver(&cris_freq_driver);
+ cpufreq_register_notifier(&cris_sdram_freq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+ return ret;
+}
+
+static int
+cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ int i;
+ struct cpufreq_freqs *freqs = data;
+ if (val == CPUFREQ_PRECHANGE) {
+ reg_bif_core_rw_sdram_timing timing =
+ REG_RD(bif_core, regi_bif_core, rw_sdram_timing);
+ timing.cpd = (freqs->new == 200000 ? 0 : 1);
+
+ if (freqs->new == 200000)
+ for (i = 0; i < 50000; i++) ;
+ REG_WR(bif_core, regi_bif_core, rw_sdram_timing, timing);
+ }
+ return 0;
+}
+
+module_init(cris_freq_init);
diff --git a/arch/cris/arch-v32/kernel/dma.c b/arch/cris/arch-v32/mach-fs/dma.c
index 570e19128ff..a6acf4e6345 100644
--- a/arch/cris/arch-v32/kernel/dma.c
+++ b/arch/cris/arch-v32/mach-fs/dma.c
@@ -3,49 +3,54 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <asm/dma.h>
-#include <asm/arch/hwregs/reg_map.h>
-#include <asm/arch/hwregs/reg_rdwr.h>
-#include <asm/arch/hwregs/marb_defs.h>
-#include <asm/arch/hwregs/config_defs.h>
-#include <asm/arch/hwregs/strmux_defs.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/marb_defs.h>
+#include <hwregs/config_defs.h>
+#include <hwregs/strmux_defs.h>
#include <linux/errno.h>
#include <asm/system.h>
-#include <asm/arch/arbiter.h>
+#include <asm/arch/mach/arbiter.h>
static char used_dma_channels[MAX_DMA_CHANNELS];
-static const char * used_dma_channels_users[MAX_DMA_CHANNELS];
+static const char *used_dma_channels_users[MAX_DMA_CHANNELS];
static DEFINE_SPINLOCK(dma_lock);
-int crisv32_request_dma(unsigned int dmanr, const char * device_id,
- unsigned options, unsigned int bandwidth,
+int crisv32_request_dma(unsigned int dmanr, const char *device_id,
+ unsigned options, unsigned int bandwidth,
enum dma_owner owner)
{
unsigned long flags;
reg_config_rw_clk_ctrl clk_ctrl;
reg_strmux_rw_cfg strmux_cfg;
- if (crisv32_arbiter_allocate_bandwidth(dmanr,
- options & DMA_INT_MEM ? INT_REGION : EXT_REGION,
- bandwidth))
- return -ENOMEM;
+ if (crisv32_arbiter_allocate_bandwidth(dmanr,
+ options & DMA_INT_MEM ?
+ INT_REGION : EXT_REGION,
+ bandwidth))
+ return -ENOMEM;
spin_lock_irqsave(&dma_lock, flags);
if (used_dma_channels[dmanr]) {
spin_unlock_irqrestore(&dma_lock, flags);
if (options & DMA_VERBOSE_ON_ERROR) {
- printk("Failed to request DMA %i for %s, already allocated by %s\n", dmanr, device_id, used_dma_channels_users[dmanr]);
+ printk(KERN_ERR "Failed to request DMA %i for %s, "
+ "already allocated by %s\n",
+ dmanr,
+ device_id,
+ used_dma_channels_users[dmanr]);
}
if (options & DMA_PANIC_ON_ERROR)
panic("request_dma error!");
+ spin_unlock_irqrestore(&dma_lock, flags);
return -EBUSY;
}
clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl);
strmux_cfg = REG_RD(strmux, regi_strmux, rw_cfg);
- switch(dmanr)
- {
+ switch (dmanr) {
case 0:
case 1:
clk_ctrl.dma01_eth0 = 1;
@@ -72,7 +77,9 @@ int crisv32_request_dma(unsigned int dmanr, const char * device_id,
default:
spin_unlock_irqrestore(&dma_lock, flags);
if (options & DMA_VERBOSE_ON_ERROR) {
- printk("Failed to request DMA %i for %s, only 0-%i valid)\n", dmanr, device_id, MAX_DMA_CHANNELS-1);
+ printk(KERN_ERR "Failed to request DMA %i for %s, "
+ "only 0-%i valid)\n",
+ dmanr, device_id, MAX_DMA_CHANNELS - 1);
}
if (options & DMA_PANIC_ON_ERROR)
@@ -80,8 +87,7 @@ int crisv32_request_dma(unsigned int dmanr, const char * device_id,
return -EINVAL;
}
- switch(owner)
- {
+ switch (owner) {
case dma_eth0:
if (dmanr == 0)
strmux_cfg.dma0 = regk_strmux_eth0;
@@ -212,7 +218,7 @@ int crisv32_request_dma(unsigned int dmanr, const char * device_id,
used_dma_channels_users[dmanr] = device_id;
REG_WR(config, regi_config, rw_clk_ctrl, clk_ctrl);
REG_WR(strmux, regi_strmux, rw_cfg, strmux_cfg);
- spin_unlock_irqrestore(&dma_lock,flags);
+ spin_unlock_irqrestore(&dma_lock, flags);
return 0;
}
diff --git a/arch/cris/arch-v32/lib/dram_init.S b/arch/cris/arch-v32/mach-fs/dram_init.S
index 218fbe259ee..6fbad336527 100644
--- a/arch/cris/arch-v32/lib/dram_init.S
+++ b/arch/cris/arch-v32/mach-fs/dram_init.S
@@ -1,23 +1,22 @@
-/* $Id: dram_init.S,v 1.4 2005/04/24 18:48:32 starvik Exp $
- *
+/*
* DRAM/SDRAM initialization - alter with care
* This file is intended to be included from other assembler files
*
* Note: This file may not modify r8 or r9 because they are used to
* carry information from the decompresser to the kernel
*
- * Copyright (C) 2000-2003 Axis Communications AB
+ * Copyright (C) 2000-2007 Axis Communications AB
*
- * Authors: Mikael Starvik (starvik@axis.com)
+ * Authors: Mikael Starvik <starvik@axis.com>
*/
/* Just to be certain the config file is included, we include it here
- * explicitly instead of depending on it being included in the file that
+ * explicitely instead of depending on it being included in the file that
* uses this code.
*/
-#include <asm/arch/hwregs/asm/reg_map_asm.h>
-#include <asm/arch/hwregs/asm/bif_core_defs_asm.h>
+#include <hwregs/asm/reg_map_asm.h>
+#include <hwregs/asm/bif_core_defs_asm.h>
;; WARNING! The registers r8 and r9 are used as parameters carrying
;; information from the decompressor (if the kernel was compressed).
@@ -46,7 +45,7 @@
move.d 0x40, $r4 ; Assume 32 bits and CAS latency = 2
move.d CONFIG_ETRAX_SDRAM_TIMING, $r1
- and.d 0x07, $r1 ; Get CAS latency
+ and.d 0x07, $r1 ; Get CAS latency
cmpq 2, $r1 ; CL = 2 ?
beq _bw_check
nop
@@ -80,12 +79,10 @@ _set_timing:
subq 1, $r2
; Issue initialization command sequence
- move.d _sdram_commands_start, $r2
- and.d 0x000fffff, $r2 ; Make sure commands are read from flash
- move.d _sdram_commands_end, $r3
- and.d 0x000fffff, $r3
+ lapc _sdram_commands_start, $r2
+ lapc _sdram_commands_end, $r3
1: clear.d $r6
- move.b [$r2+], $r6 ; Load command
+ move.b [$r2+], $r6 ; Load command
or.d $r4, $r6 ; Add calculated mrs
move.d $r6, [$r5] ; Write rw_sdram_cmd
; Wait 80 ns between each command
diff --git a/arch/cris/arch-v32/lib/hw_settings.S b/arch/cris/arch-v32/mach-fs/hw_settings.S
index fff9443513d..8bde93c3621 100644
--- a/arch/cris/arch-v32/lib/hw_settings.S
+++ b/arch/cris/arch-v32/mach-fs/hw_settings.S
@@ -1,18 +1,16 @@
/*
- * $Id: hw_settings.S,v 1.3 2005/04/24 18:36:57 starvik Exp $
- *
* This table is used by some tools to extract hardware parameters.
* The table should be included in the kernel and the decompressor.
* Don't forget to update the tools if you change this table.
*
- * Copyright (C) 2001 Axis Communications AB
+ * Copyright (C) 2001-2007 Axis Communications AB
*
- * Authors: Mikael Starvik (starvik@axis.com)
+ * Authors: Mikael Starvik <starvik@axis.com>
*/
-#include <asm/arch/hwregs/asm/reg_map_asm.h>
-#include <asm/arch/hwregs/asm/bif_core_defs_asm.h>
-#include <asm/arch/hwregs/asm/gio_defs_asm.h>
+#include <hwregs/asm/reg_map_asm.h>
+#include <hwregs/asm/bif_core_defs_asm.h>
+#include <hwregs/asm/gio_defs_asm.h>
.ascii "HW_PARAM_MAGIC" ; Magic number
.dword 0xc0004000 ; Kernel start address
diff --git a/arch/cris/arch-v32/mach-fs/io.c b/arch/cris/arch-v32/mach-fs/io.c
new file mode 100644
index 00000000000..a03a3ad3a18
--- /dev/null
+++ b/arch/cris/arch-v32/mach-fs/io.c
@@ -0,0 +1,191 @@
+/*
+ * Helper functions for I/O pins.
+ *
+ * Copyright (c) 2004-2007 Axis Communications AB.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/hwregs/gio_defs.h>
+
+#ifndef DEBUG
+#define DEBUG(x)
+#endif
+
+struct crisv32_ioport crisv32_ioports[] = {
+ {
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_oe),
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_dout),
+ (unsigned long *)REG_ADDR(gio, regi_gio, r_pa_din),
+ 8
+ },
+ {
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_oe),
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_dout),
+ (unsigned long *)REG_ADDR(gio, regi_gio, r_pb_din),
+ 18
+ },
+ {
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_oe),
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_dout),
+ (unsigned long *)REG_ADDR(gio, regi_gio, r_pc_din),
+ 18
+ },
+ {
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pd_oe),
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pd_dout),
+ (unsigned long *)REG_ADDR(gio, regi_gio, r_pd_din),
+ 18
+ },
+ {
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pe_oe),
+ (unsigned long *)REG_ADDR(gio, regi_gio, rw_pe_dout),
+ (unsigned long *)REG_ADDR(gio, regi_gio, r_pe_din),
+ 18
+ }
+};
+
+#define NBR_OF_PORTS sizeof(crisv32_ioports)/sizeof(struct crisv32_ioport)
+
+struct crisv32_iopin crisv32_led_net0_green;
+struct crisv32_iopin crisv32_led_net0_red;
+struct crisv32_iopin crisv32_led_net1_green;
+struct crisv32_iopin crisv32_led_net1_red;
+struct crisv32_iopin crisv32_led2_green;
+struct crisv32_iopin crisv32_led2_red;
+struct crisv32_iopin crisv32_led3_green;
+struct crisv32_iopin crisv32_led3_red;
+
+/* Dummy port used when green LED and red LED is on the same bit */
+static unsigned long io_dummy;
+static struct crisv32_ioport dummy_port = {
+ &io_dummy,
+ &io_dummy,
+ &io_dummy,
+ 18
+};
+static struct crisv32_iopin dummy_led = {
+ &dummy_port,
+ 0
+};
+
+static int __init crisv32_io_init(void)
+{
+ int ret = 0;
+
+ u32 i;
+
+ /* Locks *should* be dynamically initialized. */
+ for (i = 0; i < ARRAY_SIZE(crisv32_ioports); i++)
+ spin_lock_init(&crisv32_ioports[i].lock);
+ spin_lock_init(&dummy_port.lock);
+
+ /* Initialize LEDs */
+#if (defined(CONFIG_ETRAX_NBR_LED_GRP_ONE) || defined(CONFIG_ETRAX_NBR_LED_GRP_TWO))
+ ret +=
+ crisv32_io_get_name(&crisv32_led_net0_green,
+ CONFIG_ETRAX_LED_G_NET0);
+ crisv32_io_set_dir(&crisv32_led_net0_green, crisv32_io_dir_out);
+ if (strcmp(CONFIG_ETRAX_LED_G_NET0, CONFIG_ETRAX_LED_R_NET0)) {
+ ret +=
+ crisv32_io_get_name(&crisv32_led_net0_red,
+ CONFIG_ETRAX_LED_R_NET0);
+ crisv32_io_set_dir(&crisv32_led_net0_red, crisv32_io_dir_out);
+ } else
+ crisv32_led_net0_red = dummy_led;
+#endif
+
+#ifdef CONFIG_ETRAX_NBR_LED_GRP_TWO
+ ret +=
+ crisv32_io_get_name(&crisv32_led_net1_green,
+ CONFIG_ETRAX_LED_G_NET1);
+ crisv32_io_set_dir(&crisv32_led_net1_green, crisv32_io_dir_out);
+ if (strcmp(CONFIG_ETRAX_LED_G_NET1, CONFIG_ETRAX_LED_R_NET1)) {
+ crisv32_io_get_name(&crisv32_led_net1_red,
+ CONFIG_ETRAX_LED_R_NET1);
+ crisv32_io_set_dir(&crisv32_led_net1_red, crisv32_io_dir_out);
+ } else
+ crisv32_led_net1_red = dummy_led;
+#endif
+
+ ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_V32_LED2G);
+ ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_V32_LED2R);
+ ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_V32_LED3G);
+ ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_V32_LED3R);
+
+ crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out);
+ crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out);
+ crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out);
+ crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out);
+
+ return ret;
+}
+
+__initcall(crisv32_io_init);
+
+int crisv32_io_get(struct crisv32_iopin *iopin,
+ unsigned int port, unsigned int pin)
+{
+ if (port > NBR_OF_PORTS)
+ return -EINVAL;
+ if (port > crisv32_ioports[port].pin_count)
+ return -EINVAL;
+
+ iopin->bit = 1 << pin;
+ iopin->port = &crisv32_ioports[port];
+
+ /* Only allocate pinmux gpiopins if port != PORT_A (port 0) */
+ /* NOTE! crisv32_pinmux_alloc thinks PORT_B is port 0 */
+ if (port != 0 && crisv32_pinmux_alloc(port - 1, pin, pin, pinmux_gpio))
+ return -EIO;
+ DEBUG(printk(KERN_DEBUG "crisv32_io_get: Allocated pin %d on port %d\n",
+ pin, port));
+
+ return 0;
+}
+
+int crisv32_io_get_name(struct crisv32_iopin *iopin, const char *name)
+{
+ int port;
+ int pin;
+
+ if (toupper(*name) == 'P')
+ name++;
+
+ if (toupper(*name) < 'A' || toupper(*name) > 'E')
+ return -EINVAL;
+
+ port = toupper(*name) - 'A';
+ name++;
+ pin = simple_strtoul(name, NULL, 10);
+
+ if (pin < 0 || pin > crisv32_ioports[port].pin_count)
+ return -EINVAL;
+
+ iopin->bit = 1 << pin;
+ iopin->port = &crisv32_ioports[port];
+
+ /* Only allocate pinmux gpiopins if port != PORT_A (port 0) */
+ /* NOTE! crisv32_pinmux_alloc thinks PORT_B is port 0 */
+ if (port != 0 && crisv32_pinmux_alloc(port - 1, pin, pin, pinmux_gpio))
+ return -EIO;
+
+ DEBUG(printk(KERN_DEBUG
+ "crisv32_io_get_name: Allocated pin %d on port %d\n",
+ pin, port));
+
+ return 0;
+}
+
+#ifdef CONFIG_PCI
+/* PCI I/O access stuff */
+struct cris_io_operations *cris_iops = NULL;
+EXPORT_SYMBOL(cris_iops);
+#endif
diff --git a/arch/cris/arch-v32/mach-fs/pinmux.c b/arch/cris/arch-v32/mach-fs/pinmux.c
new file mode 100644
index 00000000000..d722ad9ae62
--- /dev/null
+++ b/arch/cris/arch-v32/mach-fs/pinmux.c
@@ -0,0 +1,309 @@
+/*
+ * Allocator for I/O pins. All pins are allocated to GPIO at bootup.
+ * Unassigned pins and GPIO pins can be allocated to a fixed interface
+ * or the I/O processor instead.
+ *
+ * Copyright (c) 2004-2007 Axis Communications AB.
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/spinlock.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <pinmux.h>
+#include <hwregs/pinmux_defs.h>
+
+#undef DEBUG
+
+#define PORT_PINS 18
+#define PORTS 4
+
+static char pins[PORTS][PORT_PINS];
+static DEFINE_SPINLOCK(pinmux_lock);
+
+static void crisv32_pinmux_set(int port);
+
+int crisv32_pinmux_init(void)
+{
+ static int initialized;
+
+ if (!initialized) {
+ reg_pinmux_rw_pa pa = REG_RD(pinmux, regi_pinmux, rw_pa);
+ initialized = 1;
+ REG_WR_INT(pinmux, regi_pinmux, rw_hwprot, 0);
+ pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 =
+ pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes;
+ REG_WR(pinmux, regi_pinmux, rw_pa, pa);
+ crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio);
+ crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio);
+ crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio);
+ crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio);
+ }
+
+ return 0;
+}
+
+int
+crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
+{
+ int i;
+ unsigned long flags;
+
+ crisv32_pinmux_init();
+
+ if (port > PORTS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&pinmux_lock, flags);
+
+ for (i = first_pin; i <= last_pin; i++) {
+ if ((pins[port][i] != pinmux_none)
+ && (pins[port][i] != pinmux_gpio)
+ && (pins[port][i] != mode)) {
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+#ifdef DEBUG
+ panic("Pinmux alloc failed!\n");
+#endif
+ return -EPERM;
+ }
+ }
+
+ for (i = first_pin; i <= last_pin; i++)
+ pins[port][i] = mode;
+
+ crisv32_pinmux_set(port);
+
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+
+ return 0;
+}
+
+int crisv32_pinmux_alloc_fixed(enum fixed_function function)
+{
+ int ret = -EINVAL;
+ char saved[sizeof pins];
+ unsigned long flags;
+
+ spin_lock_irqsave(&pinmux_lock, flags);
+
+ /* Save internal data for recovery */
+ memcpy(saved, pins, sizeof pins);
+
+ crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */
+
+ reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
+
+ switch (function) {
+ case pinmux_ser1:
+ ret = crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed);
+ hwprot.ser1 = regk_pinmux_yes;
+ break;
+ case pinmux_ser2:
+ ret = crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed);
+ hwprot.ser2 = regk_pinmux_yes;
+ break;
+ case pinmux_ser3:
+ ret = crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed);
+ hwprot.ser3 = regk_pinmux_yes;
+ break;
+ case pinmux_sser0:
+ ret = crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed);
+ ret |= crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
+ hwprot.sser0 = regk_pinmux_yes;
+ break;
+ case pinmux_sser1:
+ ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
+ hwprot.sser1 = regk_pinmux_yes;
+ break;
+ case pinmux_ata0:
+ ret = crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed);
+ ret |= crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed);
+ hwprot.ata0 = regk_pinmux_yes;
+ break;
+ case pinmux_ata1:
+ ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
+ ret |= crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed);
+ hwprot.ata1 = regk_pinmux_yes;
+ break;
+ case pinmux_ata2:
+ ret = crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed);
+ ret |= crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed);
+ hwprot.ata2 = regk_pinmux_yes;
+ break;
+ case pinmux_ata3:
+ ret = crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed);
+ ret |= crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed);
+ hwprot.ata2 = regk_pinmux_yes;
+ break;
+ case pinmux_ata:
+ ret = crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed);
+ ret |= crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed);
+ hwprot.ata = regk_pinmux_yes;
+ break;
+ case pinmux_eth1:
+ ret = crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed);
+ hwprot.eth1 = regk_pinmux_yes;
+ hwprot.eth1_mgm = regk_pinmux_yes;
+ break;
+ case pinmux_timer:
+ ret = crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
+ hwprot.timer = regk_pinmux_yes;
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+ return ret;
+ }
+
+ if (!ret)
+ REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
+ else
+ memcpy(pins, saved, sizeof pins);
+
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+
+ return ret;
+}
+
+void crisv32_pinmux_set(int port)
+{
+ int i;
+ int gpio_val = 0;
+ int iop_val = 0;
+
+ for (i = 0; i < PORT_PINS; i++) {
+ if (pins[port][i] == pinmux_gpio)
+ gpio_val |= (1 << i);
+ else if (pins[port][i] == pinmux_iop)
+ iop_val |= (1 << i);
+ }
+
+ REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_gio + 8 * port,
+ gpio_val);
+ REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_iop + 8 * port,
+ iop_val);
+
+#ifdef DEBUG
+ crisv32_pinmux_dump();
+#endif
+}
+
+int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
+{
+ int i;
+ unsigned long flags;
+
+ crisv32_pinmux_init();
+
+ if (port > PORTS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&pinmux_lock, flags);
+
+ for (i = first_pin; i <= last_pin; i++)
+ pins[port][i] = pinmux_none;
+
+ crisv32_pinmux_set(port);
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+
+ return 0;
+}
+
+int crisv32_pinmux_dealloc_fixed(enum fixed_function function)
+{
+ int ret = -EINVAL;
+ char saved[sizeof pins];
+ unsigned long flags;
+
+ spin_lock_irqsave(&pinmux_lock, flags);
+
+ /* Save internal data for recovery */
+ memcpy(saved, pins, sizeof pins);
+
+ crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */
+
+ reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
+
+ switch (function) {
+ case pinmux_ser1:
+ ret = crisv32_pinmux_dealloc(PORT_C, 4, 7);
+ hwprot.ser1 = regk_pinmux_no;
+ break;
+ case pinmux_ser2:
+ ret = crisv32_pinmux_dealloc(PORT_C, 8, 11);
+ hwprot.ser2 = regk_pinmux_no;
+ break;
+ case pinmux_ser3:
+ ret = crisv32_pinmux_dealloc(PORT_C, 12, 15);
+ hwprot.ser3 = regk_pinmux_no;
+ break;
+ case pinmux_sser0:
+ ret = crisv32_pinmux_dealloc(PORT_C, 0, 3);
+ ret |= crisv32_pinmux_dealloc(PORT_C, 16, 16);
+ hwprot.sser0 = regk_pinmux_no;
+ break;
+ case pinmux_sser1:
+ ret = crisv32_pinmux_dealloc(PORT_D, 0, 4);
+ hwprot.sser1 = regk_pinmux_no;
+ break;
+ case pinmux_ata0:
+ ret = crisv32_pinmux_dealloc(PORT_D, 5, 7);
+ ret |= crisv32_pinmux_dealloc(PORT_D, 15, 17);
+ hwprot.ata0 = regk_pinmux_no;
+ break;
+ case pinmux_ata1:
+ ret = crisv32_pinmux_dealloc(PORT_D, 0, 4);
+ ret |= crisv32_pinmux_dealloc(PORT_E, 17, 17);
+ hwprot.ata1 = regk_pinmux_no;
+ break;
+ case pinmux_ata2:
+ ret = crisv32_pinmux_dealloc(PORT_C, 11, 15);
+ ret |= crisv32_pinmux_dealloc(PORT_E, 3, 3);
+ hwprot.ata2 = regk_pinmux_no;
+ break;
+ case pinmux_ata3:
+ ret = crisv32_pinmux_dealloc(PORT_C, 8, 10);
+ ret |= crisv32_pinmux_dealloc(PORT_C, 0, 2);
+ hwprot.ata2 = regk_pinmux_no;
+ break;
+ case pinmux_ata:
+ ret = crisv32_pinmux_dealloc(PORT_B, 0, 15);
+ ret |= crisv32_pinmux_dealloc(PORT_D, 8, 15);
+ hwprot.ata = regk_pinmux_no;
+ break;
+ case pinmux_eth1:
+ ret = crisv32_pinmux_dealloc(PORT_E, 0, 17);
+ hwprot.eth1 = regk_pinmux_no;
+ hwprot.eth1_mgm = regk_pinmux_no;
+ break;
+ case pinmux_timer:
+ ret = crisv32_pinmux_dealloc(PORT_C, 16, 16);
+ hwprot.timer = regk_pinmux_no;
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+ return ret;
+ }
+
+ if (!ret)
+ REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
+ else
+ memcpy(pins, saved, sizeof pins);
+
+ spin_unlock_irqrestore(&pinmux_lock, flags);
+
+ return ret;
+}
+
+void crisv32_pinmux_dump(void)
+{
+ int i, j;
+
+ crisv32_pinmux_init();
+
+ for (i = 0; i < PORTS; i++) {
+ printk(KERN_DEBUG "Port %c\n", 'B' + i);
+ for (j = 0; j < PORT_PINS; j++)
+ printk(KERN_DEBUG " Pin %d = %d\n", j, pins[i][j]);
+ }
+}
+
+__initcall(crisv32_pinmux_init);
diff --git a/arch/cris/arch-v32/mach-fs/vcs_hook.c b/arch/cris/arch-v32/mach-fs/vcs_hook.c
new file mode 100644
index 00000000000..593b10f07ef
--- /dev/null
+++ b/arch/cris/arch-v32/mach-fs/vcs_hook.c
@@ -0,0 +1,100 @@
+/*
+ * Call simulator hook. This is the part running in the
+ * simulated program.
+ */
+
+#include "vcs_hook.h"
+#include <stdarg.h>
+#include <asm/arch-v32/hwregs/reg_map.h>
+#include <asm/arch-v32/hwregs/intr_vect_defs.h>
+
+#define HOOK_TRIG_ADDR 0xb7000000 /* hook cvlog model reg address */
+#define HOOK_MEM_BASE_ADDR 0xa0000000 /* csp4 (shared mem) base addr */
+
+#define HOOK_DATA(offset) ((unsigned *)HOOK_MEM_BASE_ADDR)[offset]
+#define VHOOK_DATA(offset) ((volatile unsigned *)HOOK_MEM_BASE_ADDR)[offset]
+#define HOOK_TRIG(funcid) \
+ do { \
+ *((unsigned *) HOOK_TRIG_ADDR) = funcid; \
+ } while (0)
+#define HOOK_DATA_BYTE(offset) ((unsigned char *)HOOK_MEM_BASE_ADDR)[offset]
+
+int hook_call(unsigned id, unsigned pcnt, ...)
+{
+ va_list ap;
+ unsigned i;
+ unsigned ret;
+#ifdef USING_SOS
+ PREEMPT_OFF_SAVE();
+#endif
+
+ /* pass parameters */
+ HOOK_DATA(0) = id;
+
+ /* Have to make hook_print_str a special case since we call with a
+ * parameter of byte type. Should perhaps be a separate
+ * hook_call. */
+
+ if (id == hook_print_str) {
+ int i;
+ char *str;
+
+ HOOK_DATA(1) = pcnt;
+
+ va_start(ap, pcnt);
+ str = (char *)va_arg(ap, unsigned);
+
+ for (i = 0; i != pcnt; i++)
+ HOOK_DATA_BYTE(8 + i) = str[i];
+
+ HOOK_DATA_BYTE(8 + i) = 0; /* null byte */
+ } else {
+ va_start(ap, pcnt);
+ for (i = 1; i <= pcnt; i++)
+ HOOK_DATA(i) = va_arg(ap, unsigned);
+ va_end(ap);
+ }
+
+ /* read from mem to make sure data has propagated to memory before
+ * trigging */
+ ret = *((volatile unsigned *)HOOK_MEM_BASE_ADDR);
+
+ /* trigger hook */
+ HOOK_TRIG(id);
+
+ /* wait for call to finish */
+ while (VHOOK_DATA(0) > 0) ;
+
+ /* extract return value */
+
+ ret = VHOOK_DATA(1);
+
+#ifdef USING_SOS
+ PREEMPT_RESTORE();
+#endif
+ return ret;
+}
+
+unsigned hook_buf(unsigned i)
+{
+ return (HOOK_DATA(i));
+}
+
+void print_str(const char *str)
+{
+ int i;
+ /* find null at end of string */
+ for (i = 1; str[i]; i++) ;
+ hook_call(hook_print_str, i, str);
+}
+
+void CPU_KICK_DOG(void)
+{
+ (void)hook_call(hook_kick_dog, 0);
+}
+
+void CPU_WATCHDOG_TIMEOUT(unsigned t)
+{
+ (void)hook_call(hook_dog_timeout, 1, t);
+}
+
diff --git a/arch/cris/arch-v32/kernel/vcs_hook.h b/arch/cris/arch-v32/mach-fs/vcs_hook.h
index 7d73709e3cc..c000b9fece4 100644
--- a/arch/cris/arch-v32/kernel/vcs_hook.h
+++ b/arch/cris/arch-v32/mach-fs/vcs_hook.h
@@ -1,11 +1,11 @@
-// $Id: vcs_hook.h,v 1.1 2003/08/12 12:01:06 starvik Exp $
-//
-// Call simulator hook functions
+/*
+ * Call simulator hook functions
+ */
#ifndef HOOK_H
#define HOOK_H
-int hook_call( unsigned id, unsigned pcnt, ...);
+int hook_call(unsigned id, unsigned pcnt, ...);
enum hook_ids {
hook_debug_on = 1,
diff --git a/arch/cris/arch-v32/mm/Makefile b/arch/cris/arch-v32/mm/Makefile
index 9146f88484b..0b801f2964a 100644
--- a/arch/cris/arch-v32/mm/Makefile
+++ b/arch/cris/arch-v32/mm/Makefile
@@ -1,3 +1,4 @@
# Makefile for the Linux/cris parts of the memory manager.
-obj-y := mmu.o init.o tlb.o intmem.o
+obj-y += mmu.o init.o tlb.o intmem.o
+obj-$(CONFIG_ETRAX_L2CACHE) += l2cache.o
diff --git a/arch/cris/arch-v32/mm/init.c b/arch/cris/arch-v32/mm/init.c
index a84ba7ff22d..5a9ac583464 100644
--- a/arch/cris/arch-v32/mm/init.c
+++ b/arch/cris/arch-v32/mm/init.c
@@ -65,7 +65,7 @@ cris_mmu_init(void)
REG_STATE(mmu, rw_mm_cfg, seg_d, page) |
REG_STATE(mmu, rw_mm_cfg, seg_c, linear) |
REG_STATE(mmu, rw_mm_cfg, seg_b, linear) |
-#ifndef CONFIG_ETRAXFS_SIM
+#ifndef CONFIG_ETRAX_VCS_SIM
REG_STATE(mmu, rw_mm_cfg, seg_a, page) |
#else
REG_STATE(mmu, rw_mm_cfg, seg_a, linear) |
@@ -84,13 +84,9 @@ cris_mmu_init(void)
mmu_kbase_hi = ( REG_FIELD(mmu, rw_mm_kbase_hi, base_f, 0x0) |
REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 0x8) |
REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 0x0) |
-#ifndef CONFIG_ETRAXFS_SIM
REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 0x4) |
-#else
- REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 0x0) |
-#endif
REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb) |
-#ifndef CONFIG_ETRAXFS_SIM
+#ifndef CONFIG_ETRAX_VCS_SIM
REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0x0) |
#else
REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0xa) |
diff --git a/arch/cris/arch-v32/mm/intmem.c b/arch/cris/arch-v32/mm/intmem.c
index 41ee7f7997f..9e8b69cdf19 100644
--- a/arch/cris/arch-v32/mm/intmem.c
+++ b/arch/cris/arch-v32/mm/intmem.c
@@ -7,11 +7,17 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <asm/io.h>
-#include <asm/arch/memmap.h>
+#include <memmap.h>
#define STATUS_FREE 0
#define STATUS_ALLOCATED 1
+#ifdef CONFIG_ETRAX_L2CACHE
+#define RESERVED_SIZE 66*1024
+#else
+#define RESERVED_SIZE 0
+#endif
+
struct intmem_allocation {
struct list_head entry;
unsigned int size;
@@ -30,9 +36,10 @@ static void crisv32_intmem_init(void)
struct intmem_allocation* alloc =
(struct intmem_allocation*)kmalloc(sizeof *alloc, GFP_KERNEL);
INIT_LIST_HEAD(&intmem_allocations);
- intmem_virtual = ioremap(MEM_INTMEM_START, MEM_INTMEM_SIZE);
+ intmem_virtual = ioremap(MEM_INTMEM_START + RESERVED_SIZE,
+ MEM_INTMEM_SIZE - RESERVED_SIZE);
initiated = 1;
- alloc->size = MEM_INTMEM_SIZE;
+ alloc->size = MEM_INTMEM_SIZE - RESERVED_SIZE;
alloc->offset = 0;
alloc->status = STATUS_FREE;
list_add_tail(&alloc->entry, &intmem_allocations);
@@ -59,19 +66,23 @@ void* crisv32_intmem_alloc(unsigned size, unsigned align)
(struct intmem_allocation*)
kmalloc(sizeof *alloc, GFP_ATOMIC);
alloc->status = STATUS_FREE;
- alloc->size = allocation->size - size - alignment;
- alloc->offset = allocation->offset + size;
+ alloc->size = allocation->size - size -
+ alignment;
+ alloc->offset = allocation->offset + size +
+ alignment;
list_add(&alloc->entry, &allocation->entry);
if (alignment) {
- struct intmem_allocation* tmp;
- tmp = (struct intmem_allocation*)
- kmalloc(sizeof *tmp, GFP_ATOMIC);
+ struct intmem_allocation *tmp;
+ tmp = (struct intmem_allocation *)
+ kmalloc(sizeof *tmp,
+ GFP_ATOMIC);
tmp->offset = allocation->offset;
tmp->size = alignment;
tmp->status = STATUS_FREE;
allocation->offset += alignment;
- list_add_tail(&tmp->entry, &allocation->entry);
+ list_add_tail(&tmp->entry,
+ &allocation->entry);
}
}
allocation->status = STATUS_ALLOCATED;
@@ -96,22 +107,24 @@ void crisv32_intmem_free(void* addr)
list_for_each_entry_safe(allocation, tmp, &intmem_allocations, entry) {
if (allocation->offset == (int)(addr - intmem_virtual)) {
- struct intmem_allocation* prev =
+ struct intmem_allocation *prev =
list_entry(allocation->entry.prev,
struct intmem_allocation, entry);
- struct intmem_allocation* next =
+ struct intmem_allocation *next =
list_entry(allocation->entry.next,
struct intmem_allocation, entry);
allocation->status = STATUS_FREE;
/* Join with prev and/or next if also free */
- if (prev->status == STATUS_FREE) {
+ if ((prev != &intmem_allocations) &&
+ (prev->status == STATUS_FREE)) {
prev->size += allocation->size;
list_del(&allocation->entry);
kfree(allocation);
allocation = prev;
}
- if (next->status == STATUS_FREE) {
+ if ((next != &intmem_allocations) &&
+ (next->status == STATUS_FREE)) {
allocation->size += next->size;
list_del(&next->entry);
kfree(next);
@@ -125,15 +138,16 @@ void crisv32_intmem_free(void* addr)
void* crisv32_intmem_phys_to_virt(unsigned long addr)
{
- return (void*)(addr - MEM_INTMEM_START+
- (unsigned long)intmem_virtual);
+ return (void *)(addr - (MEM_INTMEM_START + RESERVED_SIZE) +
+ (unsigned long)intmem_virtual);
}
unsigned long crisv32_intmem_virt_to_phys(void* addr)
{
return (unsigned long)((unsigned long )addr -
- (unsigned long)intmem_virtual + MEM_INTMEM_START);
+ (unsigned long)intmem_virtual + MEM_INTMEM_START +
+ RESERVED_SIZE);
}
-
+module_init(crisv32_intmem_init);
diff --git a/arch/cris/arch-v32/mm/l2cache.c b/arch/cris/arch-v32/mm/l2cache.c
new file mode 100644
index 00000000000..332ff10dcc6
--- /dev/null
+++ b/arch/cris/arch-v32/mm/l2cache.c
@@ -0,0 +1,29 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <memmap.h>
+#include <hwregs/reg_map.h>
+#include <hwregs/reg_rdwr.h>
+#include <hwregs/l2cache_defs.h>
+#include <asm/io.h>
+
+#define L2CACHE_SIZE 64
+
+int __init l2cache_init(void)
+{
+ reg_l2cache_rw_ctrl ctrl = {0};
+ reg_l2cache_rw_cfg cfg = {.en = regk_l2cache_yes};
+
+ ctrl.csize = L2CACHE_SIZE;
+ ctrl.cbase = L2CACHE_SIZE / 4 + (L2CACHE_SIZE % 4 ? 1 : 0);
+ REG_WR(l2cache, regi_l2cache, rw_ctrl, ctrl);
+
+ /* Flush the tag memory */
+ memset((void *)(MEM_INTMEM_START | MEM_NON_CACHEABLE), 0, 2*1024);
+
+ /* Enable the cache */
+ REG_WR(l2cache, regi_l2cache, rw_cfg, cfg);
+
+ return 0;
+}
+
diff --git a/arch/cris/arch-v32/mm/mmu.S b/arch/cris/arch-v32/mm/mmu.S
index 27b70e5006a..2238d154bde 100644
--- a/arch/cris/arch-v32/mm/mmu.S
+++ b/arch/cris/arch-v32/mm/mmu.S
@@ -1,3 +1,5 @@
+; WARNING : The refill handler has been modified, see below !!!
+
/*
* Copyright (C) 2003 Axis Communications AB
*
@@ -61,6 +63,14 @@
; Note that the code is optimized to minimize stalls (makes the code harder
; to read).
;
+; WARNING !!!
+; Modified by Mikael Asker 060725: added a workaround for strange TLB
+; behavior. If the same PTE is present in more than one set, the TLB
+; doesn't recognize it and we get stuck in a loop of refill exceptions.
+; The workaround detects such loops and exits them by flushing
+; the TLB contents. The problem and workaround were verified
+; in VCS by Mikael Starvik.
+;
; Each page is 8 KB. Each PMD holds 8192/4 PTEs (each PTE is 4 bytes) so each
; PMD holds 16 MB of virtual memory.
; Bits 0-12 : Offset within a page
@@ -68,6 +78,11 @@
; Bits 24-31 : PMD offset within the PGD
.macro MMU_REFILL_HANDLER handler, mmu
+ .data
+1: .dword 0 ; refill_count
+ ; == 0 <=> last_refill_cause is invalid
+2: .dword 0 ; last_refill_cause
+ .text
.globl \handler
\handler:
subq 4, $sp
@@ -76,42 +91,96 @@
subq 4, $sp
move \mmu, $srs ; Select MMU support register bank
move.d $acr, [$sp]
- subq 4, $sp
- move.d $r0, [$sp]
+ subq 12, $sp
+ move.d 1b, $acr ; Point to refill_count
+ movem $r2, [$sp]
+
+ test.d [$acr] ; refill_count == 0 ?
+ beq 5f ; yes, last_refill_cause is invalid
+ move.d $acr, $r1
+
+ ; last_refill_cause is valid, investigate cause
+ addq 4, $r1 ; Point to last_refill_cause
+ move $s3, $r0 ; Get rw_mm_cause
+ move.d [$r1], $r2 ; Get last_refill_cause
+ cmp.d $r0, $r2 ; rw_mm_cause == last_refill_cause ?
+ beq 6f ; yes, increment count
+ moveq 1, $r2
+
+ ; rw_mm_cause != last_refill_cause
+ move.d $r2, [$acr] ; refill_count = 1
+ move.d $r0, [$r1] ; last_refill_cause = rw_mm_cause
+
+3: ; Probably not in a loop, continue normal processing
#ifdef CONFIG_SMP
move $s7, $acr ; PGD
#else
move.d per_cpu__current_pgd, $acr ; PGD
#endif
; Look up PMD in PGD
- move $s3, $r0 ; rw_mm_cause
lsrq 24, $r0 ; Get PMD index into PGD (bit 24-31)
move.d [$acr], $acr ; PGD for the current process
addi $r0.d, $acr, $acr
move $s3, $r0 ; rw_mm_cause
move.d [$acr], $acr ; Get PMD
- beq 1f
+ beq 8f
; Look up PTE in PMD
lsrq PAGE_SHIFT, $r0
and.w PAGE_MASK, $acr ; Remove PMD flags
and.d 0x7ff, $r0 ; Get PTE index into PMD (bit 13-23)
addi $r0.d, $acr, $acr
move.d [$acr], $acr ; Get PTE
- beq 2f
- move.d [$sp+], $r0 ; Pop r0 in delayslot
+ beq 9f
+ movem [$sp], $r2 ; Restore r0-r2 in delay slot
+ addq 12, $sp
; Store in TLB
move $acr, $s5
- ; Return
+4: ; Return
move.d [$sp+], $acr
- move [$sp], $srs
+ move [$sp], $srs
addq 4, $sp
rete
rfe
-1: ; PMD missing, let the mm subsystem fix it up.
- move.d [$sp+], $r0 ; Pop r0
-2: ; PTE missing, let the mm subsystem fix it up.
+
+5: ; last_refill_cause is invalid
+ moveq 1, $r2
+ addq 4, $r1 ; Point to last_refill_cause
+ move.d $r2, [$acr] ; refill_count = 1
+ move $s3, $r0 ; Get rw_mm_cause
+ ba 3b ; Continue normal processing
+ move.d $r0,[$r1] ; last_refill_cause = rw_mm_cause
+
+6: ; rw_mm_cause == last_refill_cause
+ move.d [$acr], $r2 ; Get refill_count
+ cmpq 4, $r2 ; refill_count > 4 ?
+ bhi 7f ; yes
+ addq 1, $r2 ; refill_count++
+ ba 3b ; Continue normal processing
+ move.d $r2, [$acr]
+
+7: ; refill_count > 4, error
+ move.d $acr, $r0 ; Save pointer to refill_count
+ clear.d [$r0] ; refill_count = 0
+
+ ;; rewind the short stack
+ movem [$sp], $r2 ; Restore r0-r2
+ addq 12, $sp
+ move.d [$sp+], $acr
+ move [$sp], $srs
+ addq 4, $sp
+ ;; Keep it simple (slow), save all the regs.
+ SAVE_ALL
+ jsr __flush_tlb_all
+ nop
+ ba ret_from_intr ; Return
+ nop
+
+8: ; PMD missing, let the mm subsystem fix it up.
+ movem [$sp], $r2 ; Restore r0-r2
+9: ; PTE missing, let the mm subsystem fix it up.
+ addq 12, $sp
move.d [$sp+], $acr
- move [$sp], $srs
+ move [$sp], $srs
addq 4, $sp
SAVE_ALL
move \mmu, $srs
diff --git a/arch/cris/arch-v32/mm/tlb.c b/arch/cris/arch-v32/mm/tlb.c
index a076ef6e938..eda5ebcaea5 100644
--- a/arch/cris/arch-v32/mm/tlb.c
+++ b/arch/cris/arch-v32/mm/tlb.c
@@ -13,8 +13,8 @@
#include <asm/arch/hwregs/supp_reg.h>
#define UPDATE_TLB_SEL_IDX(val) \
-do { \
- unsigned long tlb_sel; \
+do { \
+ unsigned long tlb_sel; \
\
tlb_sel = REG_FIELD(mmu, rw_mm_tlb_sel, idx, val); \
SUPP_REG_WR(RW_MM_TLB_SEL, tlb_sel); \
@@ -30,8 +30,8 @@ do { \
* The TLB can host up to 256 different mm contexts at the same time. The running
* context is found in the PID register. Each TLB entry contains a page_id that
* has to match the PID register to give a hit. page_id_map keeps track of which
- * mm is assigned to which page_id, making sure it's known when to invalidate TLB
- * entries.
+ * mm's is assigned to which page_id's, making sure it's known when to
+ * invalidate TLB entries.
*
* The last page_id is never running, it is used as an invalid page_id so that
* it's possible to make TLB entries that will nerver match.
@@ -179,29 +179,29 @@ void
switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
- int cpu = smp_processor_id();
-
- /* Make sure there is a MMU context. */
- spin_lock(&mmu_context_lock);
- get_mmu_context(next);
- cpu_set(cpu, next->cpu_vm_mask);
- spin_unlock(&mmu_context_lock);
-
- /*
- * Remember the pgd for the fault handlers. Keep a separate copy of it
- * because current and active_mm might be invalid at points where
- * there's still a need to derefer the pgd.
- */
- per_cpu(current_pgd, cpu) = next->pgd;
-
- /* Switch context in the MMU. */
- if (tsk && task_thread_info(tsk))
- {
- SPEC_REG_WR(SPEC_REG_PID, next->context.page_id | task_thread_info(tsk)->tls);
- }
- else
- {
- SPEC_REG_WR(SPEC_REG_PID, next->context.page_id);
- }
+ if (prev != next) {
+ int cpu = smp_processor_id();
+
+ /* Make sure there is a MMU context. */
+ spin_lock(&mmu_context_lock);
+ get_mmu_context(next);
+ cpu_set(cpu, next->cpu_vm_mask);
+ spin_unlock(&mmu_context_lock);
+
+ /*
+ * Remember the pgd for the fault handlers. Keep a seperate
+ * copy of it because current and active_mm might be invalid
+ * at points where * there's still a need to derefer the pgd.
+ */
+ per_cpu(current_pgd, cpu) = next->pgd;
+
+ /* Switch context in the MMU. */
+ if (tsk && task_thread_info(tsk)) {
+ SPEC_REG_WR(SPEC_REG_PID, next->context.page_id |
+ task_thread_info(tsk)->tls);
+ } else {
+ SPEC_REG_WR(SPEC_REG_PID, next->context.page_id);
+ }
+ }
}
diff --git a/arch/cris/arch-v32/vmlinux.lds.S b/arch/cris/arch-v32/vmlinux.lds.S
index fead8c59ea6..d5f28e40717 100644
--- a/arch/cris/arch-v32/vmlinux.lds.S
+++ b/arch/cris/arch-v32/vmlinux.lds.S
@@ -9,6 +9,13 @@
*/
#include <asm-generic/vmlinux.lds.h>
+#include <asm/page.h>
+
+#ifdef CONFIG_ETRAX_VMEM_SIZE
+#define __CONFIG_ETRAX_VMEM_SIZE CONFIG_ETRAX_VMEM_SIZE
+#else
+#define __CONFIG_ETRAX_VMEM_SIZE 0
+#endif
jiffies = jiffies_64;
SECTIONS
@@ -17,18 +24,19 @@ SECTIONS
dram_start = .;
ebp_start = .;
- /* The boot section is only necessary until the VCS top level testbench */
- /* includes both flash and DRAM. */
+ /* The boot section is only necessary until the VCS top */
+ /* level testbench includes both flash and DRAM. */
.boot : { *(.boot) }
- . = DRAM_VIRTUAL_BASE + 0x4000; /* See head.S and pages reserved at the start. */
+ /* See head.S and pages reserved at the start. */
+ . = DRAM_VIRTUAL_BASE + 0x4000;
_text = .; /* Text and read-only data. */
text_start = .; /* Lots of aliases. */
_stext = .;
__stext = .;
.text : {
- *(.text)
+ TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
*(.fixup)
@@ -39,9 +47,9 @@ SECTIONS
__etext = .;
. = ALIGN(4); /* Exception table. */
- __start___ex_table = .;
- __ex_table : { *(__ex_table) }
- __stop___ex_table = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
RODATA
@@ -54,33 +62,27 @@ SECTIONS
__edata = . ; /* End of data section. */
_edata = . ;
- . = ALIGN(8192); /* init_task and stack, must be aligned. */
- .data.init_task : { *(.data.init_task) }
+ . = ALIGN(PAGE_SIZE); /* init_task and stack, must be aligned. */
+ .data.init_task : { *(.data.init_task) }
- . = ALIGN(8192); /* Init code and data. */
- __init_begin = .;
+ . = ALIGN(PAGE_SIZE); /* Init code and data. */
+ __init_begin = .;
.init.text : {
_sinittext = .;
INIT_TEXT
_einittext = .;
}
.init.data : { INIT_DATA }
- . = ALIGN(16);
- __setup_start = .;
- .init.setup : { *(.init.setup) }
- __setup_end = .;
+ . = ALIGN(16);
+ __setup_start = .;
+ .init.setup : { *(.init.setup) }
+ __setup_end = .;
__start___param = .;
__param : { *(__param) }
__stop___param = .;
- .initcall.init : {
+ .initcall.init : {
__initcall_start = .;
- *(.initcall1.init);
- *(.initcall2.init);
- *(.initcall3.init);
- *(.initcall4.init);
- *(.initcall5.init);
- *(.initcall6.init);
- *(.initcall7.init);
+ INITCALLS
__initcall_end = .;
}
@@ -91,25 +93,23 @@ SECTIONS
}
SECURITY_INIT
- PERCPU(8192)
+ __vmlinux_end = .; /* Last address of the physical file. */
+ PERCPU(PAGE_SIZE)
-#ifdef CONFIG_BLK_DEV_INITRD
.init.ramfs : {
__initramfs_start = .;
*(.init.ramfs)
__initramfs_end = .;
- /*
- * We fill to the next page, so we can discard all init
- * pages without needing to consider what payload might be
- * appended to the kernel image.
- */
- FILL (0);
- . = ALIGN (8192);
}
-#endif
- __vmlinux_end = .; /* Last address of the physical file. */
- __init_end = .;
+ /*
+ * We fill to the next page, so we can discard all init
+ * pages without needing to consider what payload might be
+ * appended to the kernel image.
+ */
+ . = ALIGN (PAGE_SIZE);
+
+ __init_end = .;
__data_end = . ; /* Move to _edata? */
__bss_start = .; /* BSS. */
@@ -123,11 +123,11 @@ SECTIONS
__end = .;
/* Sections to be discarded */
- /DISCARD/ : {
+ /DISCARD/ : {
EXIT_TEXT
EXIT_DATA
*(.exitcall.exit)
}
- dram_end = dram_start + CONFIG_ETRAX_DRAM_SIZE*1024*1024;
+ dram_end = dram_start + (CONFIG_ETRAX_DRAM_SIZE - __CONFIG_ETRAX_VMEM_SIZE)*1024*1024;
}
diff --git a/arch/cris/artpec_3_defconfig b/arch/cris/artpec_3_defconfig
new file mode 100644
index 00000000000..41fe67409aa
--- /dev/null
+++ b/arch/cris/artpec_3_defconfig
@@ -0,0 +1,582 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.24-rc3
+# Mon Dec 3 11:18:54 2007
+#
+CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NO_IOPORT=y
+CONFIG_FORCE_MAX_ZONEORDER=6
+CONFIG_CRIS=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# General setup
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_ETRAX_CMDLINE="root=/dev/mtdblock3 init=/linuxrc"
+# CONFIG_ETRAX_WATCHDOG is not set
+CONFIG_ETRAX_FAST_TIMER=y
+# CONFIG_ETRAX_KMALLOCED_MODULES is not set
+# CONFIG_OOM_REBOOT is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+
+#
+# Hardware setup
+#
+# CONFIG_ETRAX100LX is not set
+# CONFIG_ETRAX100LX_V2 is not set
+# CONFIG_SVINTO_SIM is not set
+# CONFIG_ETRAXFS is not set
+CONFIG_CRIS_MACH_ARTPEC3=y
+# CONFIG_ETRAX_VCS_SIM is not set
+# CONFIG_ETRAX_ARCH_V10 is not set
+CONFIG_ETRAX_ARCH_V32=y
+CONFIG_ETRAX_DRAM_SIZE=32
+CONFIG_ETRAX_VMEM_SIZE=8
+CONFIG_ETRAX_FLASH_BUSWIDTH=2
+CONFIG_ETRAX_NANDFLASH_BUSWIDTH=1
+CONFIG_ETRAX_FLASH1_SIZE=4
+CONFIG_ETRAX_DEBUG_PORT0=y
+# CONFIG_ETRAX_DEBUG_PORT1 is not set
+# CONFIG_ETRAX_DEBUG_PORT2 is not set
+# CONFIG_ETRAX_DEBUG_PORT3 is not set
+# CONFIG_ETRAX_DEBUG_PORT_NULL is not set
+CONFIG_ETRAX_DRAM_VIRTUAL_BASE=c0000000
+CONFIG_ETRAX_SERIAL_PORTS=5
+CONFIG_ETRAX_DEF_GIO_PA_OE=1c
+CONFIG_ETRAX_DEF_GIO_PA_OUT=00
+CONFIG_ETRAX_DEF_GIO_PB_OE=00000
+CONFIG_ETRAX_DEF_GIO_PB_OUT=00000
+CONFIG_ETRAX_DEF_GIO_PC_OE=00000
+CONFIG_ETRAX_DEF_GIO_PC_OUT=00000
+
+#
+# Artpec-3 options
+#
+CONFIG_ETRAX_L2CACHE=y
+CONFIG_ETRAX_DDR=y
+CONFIG_ETRAX_DDR2_MRS=0
+CONFIG_ETRAX_DDR2_TIMING=0
+CONFIG_ETRAX_DDR2_CONFIG=0
+CONFIG_ETRAX_PIO_CE0_CFG=0
+CONFIG_ETRAX_PIO_CE1_CFG=0
+CONFIG_ETRAX_PIO_CE2_CFG=0
+# CONFIG_CPU_FREQ is not set
+# CONFIG_ETRAX_NBR_LED_GRP_ZERO is not set
+CONFIG_ETRAX_NBR_LED_GRP_ONE=y
+# CONFIG_ETRAX_NBR_LED_GRP_TWO is not set
+CONFIG_ETRAX_LED_G_NET0="PA3"
+CONFIG_ETRAX_LED_R_NET0="PA4"
+CONFIG_ETRAX_V32_LED2G="PA5"
+CONFIG_ETRAX_V32_LED2R="PA6"
+CONFIG_ETRAX_V32_LED3G="PA7"
+CONFIG_ETRAX_V32_LED3R="PA7"
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Drivers for built-in interfaces
+#
+CONFIG_ETRAX_ETHERNET=y
+# CONFIG_ETRAX_IDE is not set
+CONFIG_ETRAX_AXISFLASHMAP=y
+CONFIG_ETRAX_PTABLE_SECTOR=65536
+# CONFIG_ETRAX_I2C is not set
+# CONFIG_ETRAX_GPIO is not set
+# CONFIG_ETRAX_NO_PHY is not set
+# CONFIG_ETRAX_ETHERNET_IFACE0 is not set
+# CONFIG_ETRAX_ETHERNET_GBIT is not set
+# CONFIG_ETRAXFS_SERIAL is not set
+# CONFIG_ETRAX_SYNCHRONOUS_SERIAL is not set
+# CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE is not set
+# CONFIG_ETRAX_NANDFLASH is not set
+# CONFIG_ETRAX_CARDBUS is not set
+# CONFIG_ETRAX_IOP_FW_LOAD is not set
+# CONFIG_ETRAX_STREAMCOPROC is not set
+# CONFIG_ETRAX_SPI_MMC is not set
+# CONFIG_ETRAX_SPI_MMC_BOARD is not set
+# CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK is not set
+CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY=y
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=y
+CONFIG_MTDRAM_TOTAL_SIZE=0
+CONFIG_MTDRAM_ERASE_SIZE=64
+CONFIG_MTDRAM_ABS_POS=0x0
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_RTC_CLASS is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_HW_RANDOM=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PROFILING is not set
+# CONFIG_SYSTEM_PROFILER is not set
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SAMPLES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_DMA=y
diff --git a/arch/cris/defconfig b/arch/cris/defconfig
index 9c33ae65993..59f36a58f84 100644
--- a/arch/cris/defconfig
+++ b/arch/cris/defconfig
@@ -1,52 +1,91 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11
-# Mon Jun 20 13:42:02 2005
+# Linux kernel version: 2.6.24-rc3
+# Mon Dec 3 11:34:27 2007
#
CONFIG_MMU=y
-CONFIG_UID16=y
+CONFIG_ZONE_DMA=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_IOMAP=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NO_IOPORT=y
+CONFIG_FORCE_MAX_ZONEORDER=6
CONFIG_CRIS=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
+CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
# CONFIG_SWAP is not set
# CONFIG_SYSVIPC is not set
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
#
-# Loadable module support
+# IO Schedulers
#
-# CONFIG_MODULES is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
#
# General setup
@@ -54,12 +93,27 @@ CONFIG_CC_ALIGN_JUMPS=0
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_GENERIC_HARDIRQS=y
-# CONFIG_SMP is not set
CONFIG_ETRAX_CMDLINE="root=/dev/mtdblock3 init=/linuxrc"
# CONFIG_ETRAX_WATCHDOG is not set
CONFIG_ETRAX_FAST_TIMER=y
-# CONFIG_PREEMPT is not set
+# CONFIG_ETRAX_KMALLOCED_MODULES is not set
# CONFIG_OOM_REBOOT is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
#
# Hardware setup
@@ -68,127 +122,180 @@ CONFIG_ETRAX_FAST_TIMER=y
CONFIG_ETRAX100LX_V2=y
# CONFIG_SVINTO_SIM is not set
# CONFIG_ETRAXFS is not set
-# CONFIG_ETRAXFS_SIM is not set
+# CONFIG_CRIS_MACH_ARTPEC3 is not set
+# CONFIG_ETRAX_VCS_SIM is not set
CONFIG_ETRAX_ARCH_V10=y
# CONFIG_ETRAX_ARCH_V32 is not set
CONFIG_ETRAX_DRAM_SIZE=32
CONFIG_ETRAX_FLASH_BUSWIDTH=2
+CONFIG_ETRAX_NANDFLASH_BUSWIDTH=1
CONFIG_ETRAX_FLASH1_SIZE=4
+# CONFIG_ETRAX_DEBUG_PORT0 is not set
+# CONFIG_ETRAX_DEBUG_PORT1 is not set
+# CONFIG_ETRAX_DEBUG_PORT2 is not set
+# CONFIG_ETRAX_DEBUG_PORT3 is not set
+CONFIG_ETRAX_DEBUG_PORT_NULL=y
+
+#
+# CRIS v10 options
+#
CONFIG_ETRAX_DRAM_VIRTUAL_BASE=c0000000
CONFIG_ETRAX_PA_LEDS=y
# CONFIG_ETRAX_PB_LEDS is not set
# CONFIG_ETRAX_CSP0_LEDS is not set
# CONFIG_ETRAX_NO_LEDS is not set
CONFIG_ETRAX_LED1G=2
-CONFIG_ETRAX_LED1R=2
-CONFIG_ETRAX_LED2G=3
-CONFIG_ETRAX_LED2R=3
+CONFIG_ETRAX_LED1R=3
+CONFIG_ETRAX_LED2G=4
+CONFIG_ETRAX_LED2R=5
CONFIG_ETRAX_LED3G=2
CONFIG_ETRAX_LED3R=2
-CONFIG_ETRAX_DEBUG_PORT0=y
-# CONFIG_ETRAX_DEBUG_PORT1 is not set
-# CONFIG_ETRAX_DEBUG_PORT2 is not set
-# CONFIG_ETRAX_DEBUG_PORT3 is not set
-# CONFIG_ETRAX_DEBUG_PORT_NULL is not set
CONFIG_ETRAX_RESCUE_SER0=y
# CONFIG_ETRAX_RESCUE_SER1 is not set
# CONFIG_ETRAX_RESCUE_SER2 is not set
# CONFIG_ETRAX_RESCUE_SER3 is not set
-CONFIG_ETRAX_DEF_R_WAITSTATES=0x95a6
-CONFIG_ETRAX_DEF_R_BUS_CONFIG=0x4
-CONFIG_ETRAX_SDRAM=y
-CONFIG_ETRAX_DEF_R_SDRAM_CONFIG=0x09e05757
-CONFIG_ETRAX_DEF_R_SDRAM_TIMING=0x80008002
-CONFIG_ETRAX_DEF_R_PORT_PA_DIR=0x1d
-CONFIG_ETRAX_DEF_R_PORT_PA_DATA=0x00
-CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG=0x00
-CONFIG_ETRAX_DEF_R_PORT_PB_DIR=0x1e
-CONFIG_ETRAX_DEF_R_PORT_PB_DATA=0xf3
+CONFIG_ETRAX_DEF_R_WAITSTATES=95a6
+CONFIG_ETRAX_DEF_R_BUS_CONFIG=104
+# CONFIG_ETRAX_SDRAM is not set
+CONFIG_ETRAX_DEF_R_DRAM_CONFIG=1a200040
+CONFIG_ETRAX_DEF_R_DRAM_TIMING=5611
+CONFIG_ETRAX_DEF_R_PORT_PA_DIR=1c
+CONFIG_ETRAX_DEF_R_PORT_PA_DATA=00
+CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG=00
+CONFIG_ETRAX_DEF_R_PORT_PB_DIR=00
+CONFIG_ETRAX_DEF_R_PORT_PB_DATA=ff
# CONFIG_ETRAX_SOFT_SHUTDOWN is not set
#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
# Drivers for built-in interfaces
#
CONFIG_ETRAX_ETHERNET=y
-# CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK is not set
-CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY=y
CONFIG_ETRAX_SERIAL=y
# CONFIG_ETRAX_SERIAL_FAST_TIMER is not set
# CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is not set
CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS=5
-CONFIG_ETRAX_SERIAL_PORT0=y
-# CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_OUT is not set
-CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT=y
-# CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_IN is not set
-CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN=y
-CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_NONE=y
-# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PA is not set
-# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB is not set
-# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED is not set
-CONFIG_ETRAX_SER0_DTR_ON_PA_BIT=-1
-CONFIG_ETRAX_SER0_RI_ON_PA_BIT=-1
-CONFIG_ETRAX_SER0_DSR_ON_PA_BIT=-1
-CONFIG_ETRAX_SER0_CD_ON_PA_BIT=-1
-CONFIG_ETRAX_SER0_DTR_ON_PB_BIT=-1
-CONFIG_ETRAX_SER0_RI_ON_PB_BIT=-1
-CONFIG_ETRAX_SER0_DSR_ON_PB_BIT=-1
-CONFIG_ETRAX_SER0_CD_ON_PB_BIT=-1
+# CONFIG_ETRAX_SERIAL_PORT0 is not set
# CONFIG_ETRAX_SERIAL_PORT1 is not set
-CONFIG_ETRAX_SERIAL_PORT2=y
-# CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_OUT is not set
-CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT=y
-# CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_IN is not set
-CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN=y
-CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_NONE=y
-# CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PA is not set
-# CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PB is not set
-# CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED is not set
-CONFIG_ETRAX_SER2_DTR_ON_PA_BIT=-1
-CONFIG_ETRAX_SER2_RI_ON_PA_BIT=-1
-CONFIG_ETRAX_SER2_DSR_ON_PA_BIT=-1
-CONFIG_ETRAX_SER2_CD_ON_PA_BIT=-1
-CONFIG_ETRAX_SER2_DTR_ON_PB_BIT=-1
-CONFIG_ETRAX_SER2_RI_ON_PB_BIT=-1
-CONFIG_ETRAX_SER2_DSR_ON_PB_BIT=-1
-CONFIG_ETRAX_SER2_CD_ON_PB_BIT=-1
+# CONFIG_ETRAX_SERIAL_PORT2 is not set
# CONFIG_ETRAX_SERIAL_PORT3 is not set
-CONFIG_ETRAX_RS485=y
-# CONFIG_ETRAX_RS485_ON_PA is not set
-# CONFIG_ETRAX_RS485_DISABLE_RECEIVER is not set
-CONFIG_ETRAX_IDE=y
-CONFIG_ETRAX_IDE_DELAY=15
-CONFIG_ETRAX_IDE_PB7_RESET=y
-# CONFIG_ETRAX_IDE_G27_RESET is not set
-CONFIG_ETRAX_USB_HOST=y
-CONFIG_ETRAX_USB_HOST_PORT1=y
-CONFIG_ETRAX_USB_HOST_PORT2=y
+# CONFIG_ETRAX_RS485 is not set
+# CONFIG_ETRAX_IDE is not set
+# CONFIG_ETRAX_USB_HOST is not set
CONFIG_ETRAX_AXISFLASHMAP=y
CONFIG_ETRAX_PTABLE_SECTOR=65536
# CONFIG_ETRAX_I2C is not set
# CONFIG_ETRAX_GPIO is not set
-CONFIG_ETRAX_RTC=y
-CONFIG_ETRAX_DS1302=y
-# CONFIG_ETRAX_PCF8563 is not set
-CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT=y
-CONFIG_ETRAX_DS1302_RSTBIT=0
-CONFIG_ETRAX_DS1302_SCLBIT=1
-CONFIG_ETRAX_DS1302_SDABIT=0
-CONFIG_ETRAX_DS1302_TRICKLE_CHARGE=0
+# CONFIG_ETRAX_RTC is not set
+# CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK is not set
+CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY=y
#
# Generic Driver Options
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
+# CONFIG_SYS_HYPERVISOR is not set
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -196,16 +303,20 @@ CONFIG_MTD_CONCAT=y
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
#
# RAM/ROM/Flash chip drivers
#
CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
@@ -220,20 +331,18 @@ CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_RAM=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC is not set
#
# Mapping drivers for chip access
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
@@ -244,7 +353,6 @@ CONFIG_MTD_MTDRAM=y
CONFIG_MTDRAM_TOTAL_SIZE=0
CONFIG_MTDRAM_ERASE_SIZE=64
CONFIG_MTDRAM_ABS_POS=0x0
-# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
@@ -253,216 +361,54 @@ CONFIG_MTDRAM_ABS_POS=0x0
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
+# UBI - Unsorted block images
#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
+# CONFIG_MTD_UBI is not set
+CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
# CONFIG_ATA_OVER_ETH is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-# CONFIG_PARIDE is not set
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_IDE_GENERIC is not set
-# CONFIG_IDE_ARM is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-# CONFIG_ISCSI_TCP is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_AF_RXRPC is not set
-# CONFIG_AF_RXRPC_DEBUG is not set
-# CONFIG_BT is not set
-# CONFIG_I2C is not set
-
CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_RTC_CLASS is not set
#
# Input device support
@@ -470,7 +416,7 @@ CONFIG_NET_ETHERNET=y
# CONFIG_INPUT is not set
#
-# Input I/O drivers
+# Hardware I/O ports
#
CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
@@ -480,94 +426,39 @@ CONFIG_SERIO=y
# CONFIG_GAMEPORT is not set
#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TABLET is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
# Character devices
#
# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_RTC_LIB is not set
-# CONFIG_RTC_CLASS is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
+# CONFIG_EXT4DEV_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -587,13 +478,12 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -605,15 +495,15 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-CONFIG_JFFS_FS=y
-CONFIG_JFFS_FS_VERBOSE=0
-# CONFIG_JFFS_PROC_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
@@ -622,12 +512,10 @@ CONFIG_CRAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
@@ -649,181 +537,44 @@ CONFIG_SUNRPC=y
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
# CONFIG_NLS is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Generic devices
-#
-# CONFIG_SND_MPU401_UART is not set
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-# CONFIG_PARPORT_PC_PCMCIA is not set
-# CONFIG_NET_PCMCIA is not set
-
-#
-# PC-card bridges
-#
-
-#
-# USB support
-#
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_OTG is not set
-# CONFIG_USB_ARCH_HAS_HCD is not set
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_SL811_HCD is not set
-
-#
-# USB Device Class drivers
-#
-
-#
-# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
-#
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-# CONFIG_USB_STORAGE is not set
-
-#
-# USB Input Devices
-#
-# CONFIG_USB_HID is not set
-# HID_SUPPORT is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_EGALAX is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-CONFIG_USB_RTL8150=y
-# CONFIG_USB_USBNET is not set
-
-#
-# USB port drivers
-#
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGETKIT is not set
-# CONFIG_USB_PHIDGETSERVO is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_TEST is not set
-
-#
-# USB ATM/DSL drivers
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
+# CONFIG_DLM is not set
#
# Kernel hacking
#
# CONFIG_PROFILING is not set
# CONFIG_SYSTEM_PROFILER is not set
-# CONFIG_ETRAX_KGDB is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_FRAME_POINTER is not set
-# CONFIG_DEBUG_NMI_OOPS is not set
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SAMPLES is not set
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
#
-# Hardware crypto devices
-# CONFIG_CRYPTO_HW is not set
-
-#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_DMA=y
diff --git a/arch/cris/etraxfs_defconfig b/arch/cris/etraxfs_defconfig
new file mode 100644
index 00000000000..73c646a3725
--- /dev/null
+++ b/arch/cris/etraxfs_defconfig
@@ -0,0 +1,585 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.24-rc3
+# Fri Nov 30 14:24:26 2007
+#
+CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NO_IOPORT=y
+CONFIG_FORCE_MAX_ZONEORDER=6
+CONFIG_CRIS=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# General setup
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_ETRAX_CMDLINE="root=/dev/mtdblock3 init=/linuxrc"
+# CONFIG_ETRAX_WATCHDOG is not set
+CONFIG_ETRAX_FAST_TIMER=y
+# CONFIG_ETRAX_KMALLOCED_MODULES is not set
+# CONFIG_OOM_REBOOT is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+
+#
+# Hardware setup
+#
+# CONFIG_ETRAX100LX is not set
+# CONFIG_ETRAX100LX_V2 is not set
+# CONFIG_SVINTO_SIM is not set
+CONFIG_ETRAXFS=y
+# CONFIG_CRIS_MACH_ARTPEC3 is not set
+# CONFIG_ETRAX_VCS_SIM is not set
+# CONFIG_ETRAX_ARCH_V10 is not set
+CONFIG_ETRAX_ARCH_V32=y
+CONFIG_ETRAX_DRAM_SIZE=32
+CONFIG_ETRAX_FLASH_BUSWIDTH=2
+CONFIG_ETRAX_NANDFLASH_BUSWIDTH=1
+CONFIG_ETRAX_FLASH1_SIZE=4
+CONFIG_ETRAX_DEBUG_PORT0=y
+# CONFIG_ETRAX_DEBUG_PORT1 is not set
+# CONFIG_ETRAX_DEBUG_PORT2 is not set
+# CONFIG_ETRAX_DEBUG_PORT3 is not set
+# CONFIG_ETRAX_DEBUG_PORT_NULL is not set
+CONFIG_ETRAX_DRAM_VIRTUAL_BASE=c0000000
+
+#
+# ETRAX FS options
+#
+CONFIG_ETRAX_SERIAL_PORTS=4
+CONFIG_ETRAX_MEM_GRP1_CONFIG=4044a
+CONFIG_ETRAX_MEM_GRP2_CONFIG=0
+CONFIG_ETRAX_MEM_GRP3_CONFIG=0
+CONFIG_ETRAX_MEM_GRP4_CONFIG=0
+CONFIG_ETRAX_SDRAM_GRP0_CONFIG=336
+CONFIG_ETRAX_SDRAM_GRP1_CONFIG=0
+CONFIG_ETRAX_SDRAM_TIMING=104a
+CONFIG_ETRAX_SDRAM_COMMAND=0
+CONFIG_ETRAX_DEF_GIO_PA_OE=1c
+CONFIG_ETRAX_DEF_GIO_PA_OUT=00
+CONFIG_ETRAX_DEF_GIO_PB_OE=00000
+CONFIG_ETRAX_DEF_GIO_PB_OUT=00000
+CONFIG_ETRAX_DEF_GIO_PC_OE=00000
+CONFIG_ETRAX_DEF_GIO_PC_OUT=00000
+CONFIG_ETRAX_DEF_GIO_PD_OE=00000
+CONFIG_ETRAX_DEF_GIO_PD_OUT=00000
+CONFIG_ETRAX_DEF_GIO_PE_OE=00000
+CONFIG_ETRAX_DEF_GIO_PE_OUT=00000
+# CONFIG_CPU_FREQ is not set
+# CONFIG_ETRAX_NBR_LED_GRP_ZERO is not set
+CONFIG_ETRAX_NBR_LED_GRP_ONE=y
+# CONFIG_ETRAX_NBR_LED_GRP_TWO is not set
+CONFIG_ETRAX_LED_G_NET0="PA3"
+CONFIG_ETRAX_LED_R_NET0="PA4"
+CONFIG_ETRAX_V32_LED2G="PA5"
+CONFIG_ETRAX_V32_LED2R="PA6"
+CONFIG_ETRAX_V32_LED3G="PA7"
+CONFIG_ETRAX_V32_LED3R="PA7"
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Drivers for built-in interfaces
+#
+CONFIG_ETRAX_ETHERNET=y
+# CONFIG_ETRAX_IDE is not set
+CONFIG_ETRAX_AXISFLASHMAP=y
+CONFIG_ETRAX_PTABLE_SECTOR=65536
+# CONFIG_ETRAX_I2C is not set
+# CONFIG_ETRAX_GPIO is not set
+# CONFIG_ETRAX_NO_PHY is not set
+# CONFIG_ETRAX_ETHERNET_IFACE0 is not set
+# CONFIG_ETRAX_ETHERNET_IFACE1 is not set
+# CONFIG_ETRAXFS_SERIAL is not set
+# CONFIG_ETRAX_SYNCHRONOUS_SERIAL is not set
+# CONFIG_ETRAX_AXISFLASHMAP_MTD0WHOLE is not set
+# CONFIG_ETRAX_NANDFLASH is not set
+# CONFIG_ETRAX_CARDBUS is not set
+# CONFIG_ETRAX_IOP_FW_LOAD is not set
+# CONFIG_ETRAX_STREAMCOPROC is not set
+# CONFIG_ETRAX_SPI_MMC is not set
+# CONFIG_ETRAX_SPI_MMC_BOARD is not set
+# CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK is not set
+CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY=y
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+CONFIG_MTD_MTDRAM=y
+CONFIG_MTDRAM_TOTAL_SIZE=0
+CONFIG_MTDRAM_ERASE_SIZE=64
+CONFIG_MTDRAM_ABS_POS=0x0
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_RTC_CLASS is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_HW_RANDOM=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PROFILING is not set
+# CONFIG_SYSTEM_PROFILER is not set
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SAMPLES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_DMA=y
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c
index 11b867df861..a187833febc 100644
--- a/arch/cris/kernel/module.c
+++ b/arch/cris/kernel/module.c
@@ -28,20 +28,28 @@
#define DEBUGP(fmt , ...)
#endif
+#ifdef CONFIG_ETRAX_KMALLOCED_MODULES
+#define MALLOC_MODULE(size) kmalloc(size, GFP_KERNEL)
+#define FREE_MODULE(region) kfree(region)
+#else
+#define MALLOC_MODULE(size) vmalloc_exec(size)
+#define FREE_MODULE(region) vfree(region)
+#endif
+
void *module_alloc(unsigned long size)
{
if (size == 0)
return NULL;
- return vmalloc_exec(size);
+ return MALLOC_MODULE(size);
}
/* Free memory returned from module_alloc */
void module_free(struct module *mod, void *module_region)
{
- vfree(module_region);
+ FREE_MODULE(module_region);
/* FIXME: If module_region == mod->init_region, trim exception
- table entries. */
+ table entries. */
}
/* We don't need anything special. */
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 9ca558fc5bc..ef2db8fd102 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -1,5 +1,4 @@
-/* $Id: process.c,v 1.21 2005/03/04 08:16:17 starvik Exp $
- *
+/*
* linux/arch/cris/kernel/process.c
*
* Copyright (C) 1995 Linus Torvalds
@@ -7,105 +6,6 @@
*
* Authors: Bjorn Wesen (bjornw@axis.com)
*
- * $Log: process.c,v $
- * Revision 1.21 2005/03/04 08:16:17 starvik
- * Merge of Linux 2.6.11.
- *
- * Revision 1.20 2005/01/18 05:57:22 starvik
- * Renamed hlt_counter to cris_hlt_counter and made it global.
- *
- * Revision 1.19 2004/10/19 13:07:43 starvik
- * Merge of Linux 2.6.9
- *
- * Revision 1.18 2004/08/16 12:37:23 starvik
- * Merge of Linux 2.6.8
- *
- * Revision 1.17 2004/04/05 13:53:48 starvik
- * Merge of Linux 2.6.5
- *
- * Revision 1.16 2003/10/27 08:04:33 starvik
- * Merge of Linux 2.6.0-test9
- *
- * Revision 1.15 2003/09/11 07:29:52 starvik
- * Merge of Linux 2.6.0-test5
- *
- * Revision 1.14 2003/06/10 10:21:12 johana
- * Moved thread_saved_pc() from arch/cris/kernel/process.c to
- * subarch specific process.c. arch-v32 has an erp, no irp.
- *
- * Revision 1.13 2003/04/09 05:20:47 starvik
- * Merge of Linux 2.5.67
- *
- * Revision 1.12 2002/12/11 15:41:11 starvik
- * Extracted v10 (ETRAX 100LX) specific stuff to arch/cris/arch-v10/kernel
- *
- * Revision 1.11 2002/12/10 09:00:10 starvik
- * Merge of Linux 2.5.51
- *
- * Revision 1.10 2002/11/27 08:42:34 starvik
- * Argument to user_regs() is thread_info*
- *
- * Revision 1.9 2002/11/26 09:44:21 starvik
- * New threads exits through ret_from_fork (necessary for preemptive scheduling)
- *
- * Revision 1.8 2002/11/19 14:35:24 starvik
- * Changes from linux 2.4
- * Changed struct initializer syntax to the currently prefered notation
- *
- * Revision 1.7 2002/11/18 07:39:42 starvik
- * thread_saved_pc moved here from processor.h
- *
- * Revision 1.6 2002/11/14 06:51:27 starvik
- * Made cpu_idle more similar with other archs
- * init_task_union -> init_thread_union
- * Updated for new interrupt macros
- * sys_clone and do_fork have a new argument, user_tid
- *
- * Revision 1.5 2002/11/05 06:45:11 starvik
- * Merge of Linux 2.5.45
- *
- * Revision 1.4 2002/02/05 15:37:44 bjornw
- * Need init_task.h
- *
- * Revision 1.3 2002/01/21 15:22:49 bjornw
- * current->counter is gone
- *
- * Revision 1.22 2001/11/13 09:40:43 orjanf
- * Added dump_fpu (needed for core dumps).
- *
- * Revision 1.21 2001/11/12 18:26:21 pkj
- * Fixed compiler warnings.
- *
- * Revision 1.20 2001/10/03 08:21:39 jonashg
- * cause_of_death does not exist if CONFIG_SVINTO_SIM is defined.
- *
- * Revision 1.19 2001/09/26 11:52:54 bjornw
- * INIT_MMAP is gone in 2.4.10
- *
- * Revision 1.18 2001/08/21 21:43:51 hp
- * Move last watchdog fix inside #ifdef CONFIG_ETRAX_WATCHDOG
- *
- * Revision 1.17 2001/08/21 13:48:01 jonashg
- * Added fix by HP to avoid oops when doing a hard_reset_now.
- *
- * Revision 1.16 2001/06/21 02:00:40 hp
- * * entry.S: Include asm/unistd.h.
- * (_sys_call_table): Use section .rodata, not .data.
- * (_kernel_thread): Move from...
- * * process.c: ... here.
- * * entryoffsets.c (VAL): Break out from...
- * (OF): Use VAL.
- * (LCLONE_VM): New asmified value from CLONE_VM.
- *
- * Revision 1.15 2001/06/20 16:31:57 hp
- * Add comments to describe empty functions according to review.
- *
- * Revision 1.14 2001/05/29 11:27:59 markusl
- * Fixed so that hard_reset_now will do reset even if watchdog wasn't enabled
- *
- * Revision 1.13 2001/03/20 19:44:06 bjornw
- * Use the 7th syscall argument for regs instead of current_regs
- *
*/
/*
@@ -206,6 +106,7 @@ EXPORT_SYMBOL(pm_power_off);
* low exit latency (ie sit in a loop waiting for
* somebody to say that they'd like to reschedule)
*/
+
void cpu_idle (void)
{
/* endless idle loop with no priority at all */
diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c
index 3ccd20e85dc..b326023baab 100644
--- a/arch/cris/kernel/ptrace.c
+++ b/arch/cris/kernel/ptrace.c
@@ -2,65 +2,11 @@
* linux/arch/cris/kernel/ptrace.c
*
* Parts taken from the m68k port.
- *
+ *
* Copyright (c) 2000, 2001, 2002 Axis Communications AB
*
* Authors: Bjorn Wesen
*
- * $Log: ptrace.c,v $
- * Revision 1.10 2004/09/22 11:50:01 orjanf
- * * Moved get_reg/put_reg to arch-specific files.
- * * Added functions to access debug registers (CRISv32).
- * * Added support for PTRACE_SINGLESTEP (CRISv32).
- * * Added S flag to CCS_MASK (CRISv32).
- *
- * Revision 1.9 2003/07/04 12:56:11 tobiasa
- * Moved arch-specific code to arch-specific files.
- *
- * Revision 1.8 2003/04/09 05:20:47 starvik
- * Merge of Linux 2.5.67
- *
- * Revision 1.7 2002/11/27 08:42:34 starvik
- * Argument to user_regs() is thread_info*
- *
- * Revision 1.6 2002/11/20 11:56:11 starvik
- * Merge of Linux 2.5.48
- *
- * Revision 1.5 2002/11/18 07:41:19 starvik
- * Removed warning
- *
- * Revision 1.4 2002/11/11 12:47:28 starvik
- * SYSCALL_TRACE has been moved to thread flags
- *
- * Revision 1.3 2002/02/05 15:37:18 bjornw
- * * Add do_notify_resume (replaces do_signal in the callchain)
- * * syscall_trace is now do_syscall_trace
- * * current->ptrace flag PT_TRACESYS -> PT_SYSCALLTRACE
- * * Keep track of the current->work.syscall_trace counter
- *
- * Revision 1.2 2001/12/18 13:35:20 bjornw
- * Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
- *
- * Revision 1.8 2001/11/12 18:26:21 pkj
- * Fixed compiler warnings.
- *
- * Revision 1.7 2001/09/26 11:53:49 bjornw
- * PTRACE_DETACH works more simple in 2.4.10
- *
- * Revision 1.6 2001/07/25 16:08:47 bjornw
- * PTRACE_ATTACH bulk moved into arch-independent code in 2.4.7
- *
- * Revision 1.5 2001/03/26 14:24:28 orjanf
- * * Changed loop condition.
- * * Added comment documenting non-standard ptrace behaviour.
- *
- * Revision 1.4 2001/03/20 19:44:41 bjornw
- * Use the user_regs macro instead of thread.esp0
- *
- * Revision 1.3 2000/12/18 23:45:25 bjornw
- * Linux/CRIS first version
- *
- *
*/
#include <linux/kernel.h>
@@ -85,7 +31,7 @@ extern int do_signal(int canrestart, struct pt_regs *regs);
void do_notify_resume(int canrestart, struct pt_regs *regs,
- __u32 thread_info_flags )
+ __u32 thread_info_flags)
{
/* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING)
diff --git a/arch/cris/kernel/semaphore.c b/arch/cris/kernel/semaphore.c
index b884263d3cd..f137a439041 100644
--- a/arch/cris/kernel/semaphore.c
+++ b/arch/cris/kernel/semaphore.c
@@ -4,7 +4,6 @@
*/
#include <linux/sched.h>
-#include <linux/init.h>
#include <asm/semaphore-helper.h>
/*
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index 65466c49d7a..04d48dd91dd 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -18,7 +18,7 @@
#include <linux/screen_info.h>
#include <linux/utsname.h>
#include <linux/pfn.h>
-
+#include <linux/cpu.h>
#include <asm/setup.h>
/*
@@ -36,6 +36,8 @@ extern unsigned long dram_start, dram_end;
extern unsigned long romfs_start, romfs_length, romfs_in_flash; /* from head.S */
+static struct cpu cpu_devices[NR_CPUS];
+
extern void show_etrax_copyright(void); /* arch-vX/kernel/setup.c */
/* This mainly sets up the memory area, and can be really confusing.
@@ -45,24 +47,23 @@ extern void show_etrax_copyright(void); /* arch-vX/kernel/setup.c */
* given by the macro __pa().
*
* In this DRAM, the kernel code and data is loaded, in the beginning.
- * It really starts at c0004000 to make room for some special pages -
+ * It really starts at c0004000 to make room for some special pages -
* the start address is text_start. The kernel data ends at _end. After
* this the ROM filesystem is appended (if there is any).
- *
+ *
* Between this address and dram_end, we have RAM pages usable to the
* boot code and the system.
*
*/
-void __init
-setup_arch(char **cmdline_p)
+void __init setup_arch(char **cmdline_p)
{
extern void init_etrax_debug(void);
unsigned long bootmap_size;
unsigned long start_pfn, max_pfn;
unsigned long memory_start;
- /* register an initial console printing routine for printk's */
+ /* register an initial console printing routine for printk's */
init_etrax_debug();
@@ -121,7 +122,7 @@ setup_arch(char **cmdline_p)
min_low_pfn = PAGE_OFFSET >> PAGE_SHIFT;
bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
- min_low_pfn,
+ min_low_pfn,
max_low_pfn);
/* And free all memory not belonging to the kernel (addr, size) */
@@ -137,7 +138,7 @@ setup_arch(char **cmdline_p)
* Arguments are start, size
*/
- reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size);
+ reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size, BOOTMEM_DEFAULT);
/* paging_init() sets up the MMU and marks all pages as reserved */
@@ -180,11 +181,23 @@ static void c_stop(struct seq_file *m, void *v)
extern int show_cpuinfo(struct seq_file *m, void *v);
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
.show = show_cpuinfo,
};
+static int __init topology_init(void)
+{
+ int i;
+
+ for_each_possible_cpu(i) {
+ return register_cpu(&cpu_devices[i], i);
+ }
+
+ return 0;
+}
+
+subsys_initcall(topology_init);
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index 7a2cc7efbcf..ff4c6aa75de 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -1,5 +1,4 @@
-/* $Id: time.c,v 1.18 2005/03/04 08:16:17 starvik Exp $
- *
+/*
* linux/arch/cris/kernel/time.c
*
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
@@ -18,7 +17,7 @@
* Linux/CRIS specific code:
*
* Authors: Bjorn Wesen
- * Johan Adolfsson
+ * Johan Adolfsson
*
*/
@@ -208,10 +207,16 @@ cris_do_profile(struct pt_regs* regs)
#endif
#ifdef CONFIG_PROFILING
- profile_tick(CPU_PROFILING);
+ profile_tick(CPU_PROFILING);
#endif
}
+unsigned long long sched_clock(void)
+{
+ return (unsigned long long)jiffies * (1000000000 / HZ) +
+ get_ns_in_jiffie();
+}
+
static int
__init init_udelay(void)
{
diff --git a/arch/cris/kernel/traps.c b/arch/cris/kernel/traps.c
index 520d92205fe..541efbf0937 100644
--- a/arch/cris/kernel/traps.c
+++ b/arch/cris/kernel/traps.c
@@ -1,66 +1,78 @@
-/* $Id: traps.c,v 1.11 2005/01/24 16:03:19 orjanf Exp $
- *
+/*
* linux/arch/cris/traps.c
*
- * Here we handle the break vectors not used by the system call
- * mechanism, as well as some general stack/register dumping
+ * Here we handle the break vectors not used by the system call
+ * mechanism, as well as some general stack/register dumping
* things.
- *
- * Copyright (C) 2000-2002 Axis Communications AB
+ *
+ * Copyright (C) 2000-2007 Axis Communications AB
*
* Authors: Bjorn Wesen
- * Hans-Peter Nilsson
+ * Hans-Peter Nilsson
*
*/
#include <linux/init.h>
#include <linux/module.h>
+
#include <asm/pgtable.h>
#include <asm/uaccess.h>
+extern void arch_enable_nmi(void);
+extern void stop_watchdog(void);
+extern void reset_watchdog(void);
+extern void show_registers(struct pt_regs *regs);
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+extern void handle_BUG(struct pt_regs *regs);
+#else
+#define handle_BUG(regs)
+#endif
+
static int kstack_depth_to_print = 24;
-extern int raw_printk(const char *fmt, ...);
+void (*nmi_handler)(struct pt_regs *);
-void show_trace(unsigned long * stack)
+void
+show_trace(unsigned long *stack)
{
unsigned long addr, module_start, module_end;
extern char _stext, _etext;
int i;
- raw_printk("\nCall Trace: ");
+ printk("\nCall Trace: ");
- i = 1;
- module_start = VMALLOC_START;
- module_end = VMALLOC_END;
+ i = 1;
+ module_start = VMALLOC_START;
+ module_end = VMALLOC_END;
- while (((long) stack & (THREAD_SIZE-1)) != 0) {
- if (__get_user (addr, stack)) {
+ while (((long)stack & (THREAD_SIZE-1)) != 0) {
+ if (__get_user(addr, stack)) {
/* This message matches "failing address" marked
s390 in ksymoops, so lines containing it will
not be filtered out by ksymoops. */
- raw_printk ("Failing address 0x%lx\n", (unsigned long)stack);
+ printk("Failing address 0x%lx\n", (unsigned long)stack);
break;
}
stack++;
- /*
- * If the address is either in the text segment of the
- * kernel, or in the region which contains vmalloc'ed
- * memory, it *may* be the address of a calling
- * routine; if so, print it so that someone tracing
- * down the cause of the crash will be able to figure
- * out the call path that was taken.
- */
- if (((addr >= (unsigned long) &_stext) &&
- (addr <= (unsigned long) &_etext)) ||
- ((addr >= module_start) && (addr <= module_end))) {
- if (i && ((i % 8) == 0))
- raw_printk("\n ");
- raw_printk("[<%08lx>] ", addr);
- i++;
- }
- }
+ /*
+ * If the address is either in the text segment of the
+ * kernel, or in the region which contains vmalloc'ed
+ * memory, it *may* be the address of a calling
+ * routine; if so, print it so that someone tracing
+ * down the cause of the crash will be able to figure
+ * out the call path that was taken.
+ */
+ if (((addr >= (unsigned long)&_stext) &&
+ (addr <= (unsigned long)&_etext)) ||
+ ((addr >= module_start) && (addr <= module_end))) {
+ if (i && ((i % 8) == 0))
+ printk("\n ");
+ printk("[<%08lx>] ", addr);
+ i++;
+ }
+ }
}
/*
@@ -78,109 +90,149 @@ void show_trace(unsigned long * stack)
* with the ksymoops maintainer.
*/
-void
+void
show_stack(struct task_struct *task, unsigned long *sp)
{
- unsigned long *stack, addr;
- int i;
+ unsigned long *stack, addr;
+ int i;
/*
* debugging aid: "show_stack(NULL);" prints a
* back trace.
*/
- if(sp == NULL) {
+ if (sp == NULL) {
if (task)
sp = (unsigned long*)task->thread.ksp;
else
sp = (unsigned long*)rdsp();
}
- stack = sp;
+ stack = sp;
- raw_printk("\nStack from %08lx:\n ", (unsigned long)stack);
- for(i = 0; i < kstack_depth_to_print; i++) {
- if (((long) stack & (THREAD_SIZE-1)) == 0)
- break;
- if (i && ((i % 8) == 0))
- raw_printk("\n ");
- if (__get_user (addr, stack)) {
+ printk("\nStack from %08lx:\n ", (unsigned long)stack);
+ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (((long)stack & (THREAD_SIZE-1)) == 0)
+ break;
+ if (i && ((i % 8) == 0))
+ printk("\n ");
+ if (__get_user(addr, stack)) {
/* This message matches "failing address" marked
s390 in ksymoops, so lines containing it will
not be filtered out by ksymoops. */
- raw_printk ("Failing address 0x%lx\n", (unsigned long)stack);
+ printk("Failing address 0x%lx\n", (unsigned long)stack);
break;
}
stack++;
- raw_printk("%08lx ", addr);
- }
+ printk("%08lx ", addr);
+ }
show_trace(sp);
}
-static void (*nmi_handler)(struct pt_regs*);
-extern void arch_enable_nmi(void);
+#if 0
+/* displays a short stack trace */
-void set_nmi_handler(void (*handler)(struct pt_regs*))
+int
+show_stack(void)
{
- nmi_handler = handler;
- arch_enable_nmi();
+ unsigned long *sp = (unsigned long *)rdusp();
+ int i;
+
+ printk("Stack dump [0x%08lx]:\n", (unsigned long)sp);
+ for (i = 0; i < 16; i++)
+ printk("sp + %d: 0x%08lx\n", i*4, sp[i]);
+ return 0;
}
+#endif
-void handle_nmi(struct pt_regs* regs)
+void
+dump_stack(void)
{
- if (nmi_handler)
- nmi_handler(regs);
+ show_stack(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
+
+void
+set_nmi_handler(void (*handler)(struct pt_regs *))
+{
+ nmi_handler = handler;
+ arch_enable_nmi();
}
#ifdef CONFIG_DEBUG_NMI_OOPS
-void oops_nmi_handler(struct pt_regs* regs)
+void
+oops_nmi_handler(struct pt_regs *regs)
{
- stop_watchdog();
- raw_printk("NMI!\n");
- show_registers(regs);
+ stop_watchdog();
+ oops_in_progress = 1;
+ printk("NMI!\n");
+ show_registers(regs);
+ oops_in_progress = 0;
}
-static int
-__init oops_nmi_register(void)
+static int __init
+oops_nmi_register(void)
{
- set_nmi_handler(oops_nmi_handler);
- return 0;
+ set_nmi_handler(oops_nmi_handler);
+ return 0;
}
__initcall(oops_nmi_register);
#endif
-#if 0
-/* displays a short stack trace */
-
-int
-show_stack()
+/*
+ * This gets called from entry.S when the watchdog has bitten. Show something
+ * similiar to an Oops dump, and if the kernel is configured to be a nice
+ * doggy, then halt instead of reboot.
+ */
+void
+watchdog_bite_hook(struct pt_regs *regs)
{
- unsigned long *sp = (unsigned long *)rdusp();
- int i;
- raw_printk("Stack dump [0x%08lx]:\n", (unsigned long)sp);
- for(i = 0; i < 16; i++)
- raw_printk("sp + %d: 0x%08lx\n", i*4, sp[i]);
- return 0;
-}
+#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
+ local_irq_disable();
+ stop_watchdog();
+ show_registers(regs);
+
+ while (1)
+ ; /* Do nothing. */
+#else
+ show_registers(regs);
#endif
+}
-void dump_stack(void)
+/* This is normally the Oops function. */
+void
+die_if_kernel(const char *str, struct pt_regs *regs, long err)
{
- show_stack(NULL, NULL);
-}
+ if (user_mode(regs))
+ return;
-EXPORT_SYMBOL(dump_stack);
+#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
+ /*
+ * This printout might take too long and could trigger
+ * the watchdog normally. If NICE_DOGGY is set, simply
+ * stop the watchdog during the printout.
+ */
+ stop_watchdog();
+#endif
-void __init
-trap_init(void)
-{
- /* Nothing needs to be done */
+ handle_BUG(regs);
+
+ printk("%s: %04lx\n", str, err & 0xffff);
+
+ show_registers(regs);
+
+ oops_in_progress = 0;
+
+#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
+ reset_watchdog();
+#endif
+ do_exit(SIGSEGV);
}
-void spinning_cpu(void* addr)
+void __init
+trap_init(void)
{
- raw_printk("CPU %d spinning on %X\n", smp_processor_id(), addr);
- dump_stack();
+ /* Nothing needs to be done */
}
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c
index 3034f3ff950..c4c76db90f9 100644
--- a/arch/cris/mm/fault.c
+++ b/arch/cris/mm/fault.c
@@ -1,130 +1,9 @@
/*
* linux/arch/cris/mm/fault.c
*
- * Copyright (C) 2000, 2001 Axis Communications AB
- *
- * Authors: Bjorn Wesen
- *
- * $Log: fault.c,v $
- * Revision 1.20 2005/03/04 08:16:18 starvik
- * Merge of Linux 2.6.11.
- *
- * Revision 1.19 2005/01/14 10:07:59 starvik
- * Fixed warning.
- *
- * Revision 1.18 2005/01/12 08:10:14 starvik
- * Re-added the change of frametype when handling kernel page fault fixup
- * for v10. This is necessary to avoid that the CPU remakes the faulting
- * access.
- *
- * Revision 1.17 2005/01/11 13:53:05 starvik
- * Use raw_printk.
- *
- * Revision 1.16 2004/12/17 11:39:41 starvik
- * SMP support.
- *
- * Revision 1.15 2004/11/23 18:36:18 starvik
- * Stack is now non-executable.
- * Signal handler trampolines are placed in a reserved page mapped into all
- * processes.
- *
- * Revision 1.14 2004/11/23 07:10:21 starvik
- * Moved find_fixup_code to generic code.
- *
- * Revision 1.13 2004/11/23 07:00:54 starvik
- * Actually use the execute permission bit in the MMU. This makes it possible
- * to prevent e.g. attacks where executable code is put on the stack.
- *
- * Revision 1.12 2004/09/29 06:16:04 starvik
- * Use instruction_pointer
- *
- * Revision 1.11 2004/05/14 07:58:05 starvik
- * Merge of changes from 2.4
- *
- * Revision 1.10 2003/10/27 14:51:24 starvik
- * Removed debugcode
- *
- * Revision 1.9 2003/10/27 14:50:42 starvik
- * Changed do_page_fault signature
- *
- * Revision 1.8 2003/07/04 13:02:48 tobiasa
- * Moved code snippet from arch/cris/mm/fault.c that searches for fixup code
- * to separate function in arch-specific files.
- *
- * Revision 1.7 2003/01/22 06:48:38 starvik
- * Fixed warnings issued by GCC 3.2.1
- *
- * Revision 1.6 2003/01/09 14:42:52 starvik
- * Merge of Linux 2.5.55
- *
- * Revision 1.5 2002/12/11 14:44:48 starvik
- * Extracted v10 (ETRAX 100LX) specific stuff to arch/cris/arch-v10/mm
- *
- * Revision 1.4 2002/11/13 15:10:28 starvik
- * pte_offset has been renamed to pte_offset_kernel
- *
- * Revision 1.3 2002/11/05 06:45:13 starvik
- * Merge of Linux 2.5.45
- *
- * Revision 1.2 2001/12/18 13:35:22 bjornw
- * Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
- *
- * Revision 1.20 2001/11/22 13:34:06 bjornw
- * * Bug workaround (LX TR89): force a rerun of the whole of an interrupted
- * unaligned write, because the second half of the write will be corrupted
- * otherwise. Affected unaligned writes spanning not-yet mapped pages.
- * * Optimization: use the wr_rd bit in R_MMU_CAUSE to know whether a miss
- * was due to a read or a write (before we didn't know this until the next
- * restart of the interrupted instruction, thus wasting one fault-irq)
- *
- * Revision 1.19 2001/11/12 19:02:10 pkj
- * Fixed compiler warnings.
- *
- * Revision 1.18 2001/07/18 22:14:32 bjornw
- * Enable interrupts in the bulk of do_page_fault
- *
- * Revision 1.17 2001/07/18 13:07:23 bjornw
- * * Detect non-existant PTE's in vmalloc pmd synchronization
- * * Remove comment about fast-paths for VMALLOC_START etc, because all that
- * was totally bogus anyway it turned out :)
- * * Fix detection of vmalloc-area synchronization
- * * Add some comments
- *
- * Revision 1.16 2001/06/13 00:06:08 bjornw
- * current_pgd should be volatile
- *
- * Revision 1.15 2001/06/13 00:02:23 bjornw
- * Use a separate variable to store the current pgd to avoid races in schedule
- *
- * Revision 1.14 2001/05/16 17:41:07 hp
- * Last comment tweak further tweaked.
- *
- * Revision 1.13 2001/05/15 00:58:44 hp
- * Expand a bit on the comment why we compare address >= TASK_SIZE rather
- * than >= VMALLOC_START.
- *
- * Revision 1.12 2001/04/04 10:51:14 bjornw
- * mmap_sem is grabbed for reading
- *
- * Revision 1.11 2001/03/23 07:36:07 starvik
- * Corrected according to review remarks
- *
- * Revision 1.10 2001/03/21 16:10:11 bjornw
- * CRIS_FRAME_FIXUP not needed anymore, use FRAME_NORMAL
- *
- * Revision 1.9 2001/03/05 13:22:20 bjornw
- * Spell-fix and fix in vmalloc_fault handling
- *
- * Revision 1.8 2000/11/22 14:45:31 bjornw
- * * 2.4.0-test10 removed the set_pgdir instantaneous kernel global mapping
- * into all processes. Instead we fill in the missing PTE entries on demand.
- *
- * Revision 1.7 2000/11/21 16:39:09 bjornw
- * fixup switches frametype
- *
- * Revision 1.6 2000/11/17 16:54:08 bjornw
- * More detailed siginfo reporting
+ * Copyright (C) 2000-2006 Axis Communications AB
*
+ * Authors: Bjorn Wesen
*
*/
@@ -135,7 +14,6 @@
extern int find_fixup_code(struct pt_regs *);
extern void die_if_kernel(const char *, struct pt_regs *, long);
-extern int raw_printk(const char *fmt, ...);
/* debug of low-level TLB reload */
#undef DEBUG
@@ -164,8 +42,8 @@ unsigned long cris_signal_return_page;
* address.
*
* error_code:
- * bit 0 == 0 means no page found, 1 means protection fault
- * bit 1 == 0 means read, 1 means write
+ * bit 0 == 0 means no page found, 1 means protection fault
+ * bit 1 == 0 means read, 1 means write
*
* If this routine detects a bad access, it returns 1, otherwise it
* returns 0.
@@ -181,9 +59,10 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
siginfo_t info;
int fault;
- D(printk("Page fault for %lX on %X at %lX, prot %d write %d\n",
- address, smp_processor_id(), instruction_pointer(regs),
- protection, writeaccess));
+ D(printk(KERN_DEBUG
+ "Page fault for %lX on %X at %lX, prot %d write %d\n",
+ address, smp_processor_id(), instruction_pointer(regs),
+ protection, writeaccess));
tsk = current;
@@ -233,7 +112,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
* context, we must not take the fault..
*/
- if (in_atomic() || !mm)
+ if (in_interrupt() || !mm)
goto no_context;
down_read(&mm->mmap_sem);
@@ -319,6 +198,9 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
/* info.si_code has been set above */
info.si_addr = (void *)address;
force_sig_info(SIGSEGV, &info, tsk);
+ printk(KERN_NOTICE "%s (pid %d) segfaults for page "
+ "address %08lx at pc %08lx\n",
+ tsk->comm, tsk->pid, address, instruction_pointer(regs));
return;
}
@@ -326,7 +208,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
/* Are we prepared to handle this kernel fault?
*
- * (The kernel has valid exception-points in the source
+ * (The kernel has valid exception-points in the source
* when it acesses user-memory. When it fails in one
* of those points, we find it in a table and do a jump
* to some fixup code that loads an appropriate error
@@ -341,13 +223,18 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
* terminate things with extreme prejudice.
*/
- if ((unsigned long) (address) < PAGE_SIZE)
- raw_printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
- else
- raw_printk(KERN_ALERT "Unable to handle kernel access");
- raw_printk(" at virtual address %08lx\n",address);
-
- die_if_kernel("Oops", regs, (writeaccess << 1) | protection);
+ if (!oops_in_progress) {
+ oops_in_progress = 1;
+ if ((unsigned long) (address) < PAGE_SIZE)
+ printk(KERN_ALERT "Unable to handle kernel NULL "
+ "pointer dereference");
+ else
+ printk(KERN_ALERT "Unable to handle kernel access"
+ " at virtual address %08lx\n", address);
+
+ die_if_kernel("Oops", regs, (writeaccess << 1) | protection);
+ oops_in_progress = 0;
+ }
do_exit(SIGKILL);
@@ -360,7 +247,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
up_read(&mm->mmap_sem);
printk("VM: killing process %s\n", tsk->comm);
if (user_mode(regs))
- do_group_exit(SIGKILL);
+ do_exit(SIGKILL);
goto no_context;
do_sigbus:
@@ -406,8 +293,8 @@ vmalloc_fault:
/* Since we're two-level, we don't need to do both
* set_pgd and set_pmd (they do the same thing). If
* we go three-level at some point, do the right thing
- * with pgd_present and set_pgd here.
- *
+ * with pgd_present and set_pgd here.
+ *
* Also, since the vmalloc area is global, we don't
* need to copy individual PTE's, it is enough to
* copy the pgd pointer into the pte page of the
diff --git a/arch/cris/mm/init.c b/arch/cris/mm/init.c
index 0c833d17622..4207a2b5275 100644
--- a/arch/cris/mm/init.c
+++ b/arch/cris/mm/init.c
@@ -6,117 +6,6 @@
*
* Authors: Bjorn Wesen (bjornw@axis.com)
*
- * $Log: init.c,v $
- * Revision 1.11 2004/05/28 09:28:56 starvik
- * Calculation of loops_per_usec moved because initialization order has changed
- * in Linux 2.6.
- *
- * Revision 1.10 2004/05/14 07:58:05 starvik
- * Merge of changes from 2.4
- *
- * Revision 1.9 2003/07/04 08:27:54 starvik
- * Merge of Linux 2.5.74
- *
- * Revision 1.8 2003/04/09 05:20:48 starvik
- * Merge of Linux 2.5.67
- *
- * Revision 1.7 2003/01/22 06:48:38 starvik
- * Fixed warnings issued by GCC 3.2.1
- *
- * Revision 1.6 2002/12/11 14:44:48 starvik
- * Extracted v10 (ETRAX 100LX) specific stuff to arch/cris/arch-v10/mm
- *
- * Revision 1.5 2002/11/18 07:37:37 starvik
- * Added cache bug workaround (from Linux 2.4)
- *
- * Revision 1.4 2002/11/13 15:40:24 starvik
- * Removed the page table cache stuff (as done in other archs)
- *
- * Revision 1.3 2002/11/05 06:45:13 starvik
- * Merge of Linux 2.5.45
- *
- * Revision 1.2 2001/12/18 13:35:22 bjornw
- * Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
- *
- * Revision 1.31 2001/11/13 16:22:00 bjornw
- * Skip calculating totalram and sharedram in si_meminfo
- *
- * Revision 1.30 2001/11/12 19:02:10 pkj
- * Fixed compiler warnings.
- *
- * Revision 1.29 2001/07/25 16:09:50 bjornw
- * val->sharedram will stay 0
- *
- * Revision 1.28 2001/06/28 16:30:17 bjornw
- * Oops. This needs to wait until 2.4.6 is merged
- *
- * Revision 1.27 2001/06/28 14:04:07 bjornw
- * Fill in sharedram
- *
- * Revision 1.26 2001/06/18 06:36:02 hp
- * Enable free_initmem of __init-type pages
- *
- * Revision 1.25 2001/06/13 00:02:23 bjornw
- * Use a separate variable to store the current pgd to avoid races in schedule
- *
- * Revision 1.24 2001/05/15 00:52:20 hp
- * Only map segment 0xa as seg if CONFIG_JULIETTE
- *
- * Revision 1.23 2001/04/04 14:35:40 bjornw
- * * Removed get_pte_slow and friends (2.4.3 change)
- * * Removed bad_pmd handling (2.4.3 change)
- *
- * Revision 1.22 2001/04/04 13:38:04 matsfg
- * Moved ioremap to a separate function instead
- *
- * Revision 1.21 2001/03/27 09:28:33 bjornw
- * ioremap used too early - lets try it in mem_init instead
- *
- * Revision 1.20 2001/03/23 07:39:21 starvik
- * Corrected according to review remarks
- *
- * Revision 1.19 2001/03/15 14:25:17 bjornw
- * More general shadow registers and ioremaped addresses for external I/O
- *
- * Revision 1.18 2001/02/23 12:46:44 bjornw
- * * 0xc was not CSE1; 0x8 is, same as uncached flash, so we move the uncached
- * flash during CRIS_LOW_MAP from 0xe to 0x8 so both the flash and the I/O
- * is mapped straight over (for !CRIS_LOW_MAP the uncached flash is still 0xe)
- *
- * Revision 1.17 2001/02/22 15:05:21 bjornw
- * Map 0x9 straight over during LOW_MAP to allow for memory mapped LEDs
- *
- * Revision 1.16 2001/02/22 15:02:35 bjornw
- * Map 0xc straight over during LOW_MAP to allow for memory mapped I/O
- *
- * Revision 1.15 2001/01/10 21:12:10 bjornw
- * loops_per_sec -> loops_per_jiffy
- *
- * Revision 1.14 2000/11/22 16:23:20 bjornw
- * Initialize totalhigh counters to 0 to make /proc/meminfo look nice.
- *
- * Revision 1.13 2000/11/21 16:37:51 bjornw
- * Temporarily disable initmem freeing
- *
- * Revision 1.12 2000/11/21 13:55:07 bjornw
- * Use CONFIG_CRIS_LOW_MAP for the low VM map instead of explicit CPU type
- *
- * Revision 1.11 2000/10/06 12:38:22 bjornw
- * Cast empty_bad_page correctly (should really be of * type from the start..
- *
- * Revision 1.10 2000/10/04 16:53:57 bjornw
- * Fix memory-map due to LX features
- *
- * Revision 1.9 2000/09/13 15:47:49 bjornw
- * Wrong count in reserved-pages loop
- *
- * Revision 1.8 2000/09/13 14:35:10 bjornw
- * 2.4.0-test8 added a new arg to free_area_init_node
- *
- * Revision 1.7 2000/08/17 15:35:55 bjornw
- * 2.4.0-test6 removed MAP_NR and inserted virt_to_page
- *
- *
*/
#include <linux/init.h>
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index bf0468cbe71..a5aac1b0756 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -5,6 +5,7 @@
config FRV
bool
default y
+ select HAVE_IDE
config ZONE_DMA
bool
@@ -57,6 +58,10 @@ config ARCH_HAS_ILOG2_U64
bool
default y
+config HZ
+ int
+ default 1000
+
mainmenu "Fujitsu FR-V Kernel Configuration"
source "init/Kconfig"
@@ -138,6 +143,15 @@ config UCPAGE_OFFSET_C0000000
endchoice
+config PAGE_OFFSET
+ hex
+ default 0x20000000 if UCPAGE_OFFSET_20000000
+ default 0x40000000 if UCPAGE_OFFSET_40000000
+ default 0x60000000 if UCPAGE_OFFSET_60000000
+ default 0x80000000 if UCPAGE_OFFSET_80000000
+ default 0xA0000000 if UCPAGE_OFFSET_A0000000
+ default 0xC0000000
+
config PROTECT_KERNEL
bool "Protect core kernel against userspace"
depends on !MMU
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 99046b1f51c..ca6a345b87e 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1494,7 +1494,7 @@ sys_call_table:
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index a74c08786b2..0669e138238 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -708,7 +708,7 @@ static void __init reserve_dma_coherent(void)
/*
* calibrate the delay loop
*/
-void __init calibrate_delay(void)
+void __cpuinit calibrate_delay(void)
{
loops_per_jiffy = __delay_loops_MHz * (1000000 / HZ);
@@ -925,13 +925,15 @@ static void __init setup_linux_memory(void)
#endif
/* take back the memory occupied by the kernel image and the bootmem alloc map */
- reserve_bootmem(kstart, kend - kstart + bootmap_size);
+ reserve_bootmem(kstart, kend - kstart + bootmap_size,
+ BOOTMEM_DEFAULT);
/* reserve the memory occupied by the initial ramdisk */
#ifdef CONFIG_BLK_DEV_INITRD
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (low_top_pfn << PAGE_SHIFT)) {
- reserve_bootmem(INITRD_START, INITRD_SIZE);
+ reserve_bootmem(INITRD_START, INITRD_SIZE,
+ BOOTMEM_DEFAULT);
initrd_start = INITRD_START + PAGE_OFFSET;
initrd_end = initrd_start + INITRD_SIZE;
}
@@ -986,9 +988,10 @@ static void __init setup_uclinux_memory(void)
/* now take back the bits the core kernel is occupying */
#ifndef CONFIG_PROTECT_KERNEL
- reserve_bootmem(kend, bootmap_size);
+ reserve_bootmem(kend, bootmap_size, BOOTMEM_DEFAULT);
reserve_bootmem((unsigned long) &__kernel_image_start,
- kend - (unsigned long) &__kernel_image_start);
+ kend - (unsigned long) &__kernel_image_start,
+ BOOTMEM_DEFAULT);
#else
dampr = __get_DAMPR(0);
@@ -996,14 +999,15 @@ static void __init setup_uclinux_memory(void)
dampr = (dampr >> 4) + 17;
dampr = 1 << dampr;
- reserve_bootmem(__get_DAMPR(0) & xAMPRx_PPFN, dampr);
+ reserve_bootmem(__get_DAMPR(0) & xAMPRx_PPFN, dampr, BOOTMEM_DEFAULT);
#endif
/* reserve some memory to do uncached DMA through if requested */
#ifdef CONFIG_RESERVE_DMA_COHERENT
if (dma_coherent_mem_start)
reserve_bootmem(dma_coherent_mem_start,
- dma_coherent_mem_end - dma_coherent_mem_start);
+ dma_coherent_mem_end - dma_coherent_mem_start,
+ BOOTMEM_DEFAULT);
#endif
} /* end setup_uclinux_memory() */
@@ -1109,7 +1113,7 @@ static void c_stop(struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 925fb0199a0..69f6a4ef5d6 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -63,6 +63,7 @@ static irqreturn_t timer_interrupt(int irq, void *dummy)
/* last time the cmos clock got updated */
static long last_rtc_update = 0;
+ profile_tick(CPU_PROFILING);
/*
* Here we are in the timer irq handler. We just have irqs locally
* disabled but we don't know if the timer_bh is running on the other
@@ -73,8 +74,6 @@ static irqreturn_t timer_interrupt(int irq, void *dummy)
write_seqlock(&xtime_lock);
do_timer(1);
- update_process_times(user_mode(get_irq_regs()));
- profile_tick(CPU_PROFILING);
/*
* If we have an externally synchronized Linux clock, then update
@@ -99,6 +98,9 @@ static irqreturn_t timer_interrupt(int irq, void *dummy)
#endif /* CONFIG_HEARTBEAT */
write_sequnlock(&xtime_lock);
+
+ update_process_times(user_mode(get_irq_regs()));
+
return IRQ_HANDLED;
}
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index f42b328b1dd..17725a55aed 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -13,7 +13,7 @@ ENTRY(_start)
jiffies = jiffies_64 + 4;
-__page_offset = 0xc0000000; /* start of area covered by struct pages */
+__page_offset = CONFIG_PAGE_OFFSET; /* start of area covered by struct pages */
__kernel_image_start = __page_offset; /* address at which kernel image resides */
SECTIONS
@@ -105,11 +105,9 @@ SECTIONS
SCHED_TEXT
LOCK_TEXT
#ifdef CONFIG_DEBUG_INFO
- *(
INIT_TEXT
EXIT_TEXT
- .exitcall.exit
- )
+ *(.exitcall.exit)
#endif
*(.fixup)
*(.gnu.warning)
diff --git a/arch/frv/mm/mmu-context.c b/arch/frv/mm/mmu-context.c
index 1530a4111e6..81757d55a5b 100644
--- a/arch/frv/mm/mmu-context.c
+++ b/arch/frv/mm/mmu-context.c
@@ -181,7 +181,7 @@ int cxn_pin_by_pid(pid_t pid)
/* get a handle on the mm_struct */
read_lock(&tasklist_lock);
- tsk = find_task_by_pid(pid);
+ tsk = find_task_by_vpid(pid);
if (tsk) {
ret = -EINVAL;
diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c
index 7787c3cc52c..66f616fb486 100644
--- a/arch/frv/mm/pgalloc.c
+++ b/arch/frv/mm/pgalloc.c
@@ -28,7 +28,7 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
return pte;
}
-struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *page;
@@ -37,9 +37,11 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
#else
page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
#endif
- if (page)
+ if (page) {
clear_highpage(page);
- flush_dcache_page(page);
+ pgtable_page_ctor(page);
+ flush_dcache_page(page);
+ }
return page;
}
@@ -140,7 +142,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return pgd;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
/* in the non-PAE case, clear_page_tables() clears user pgd entries */
quicklist_free(0, pgd_dtor, pgd);
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index dc61222e112..085dc6ec152 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -8,6 +8,7 @@ mainmenu "uClinux/h8300 (w/o MMU) Kernel Configuration"
config H8300
bool
default y
+ select HAVE_IDE
config MMU
bool
@@ -65,6 +66,9 @@ config TIME_LOW_RES
bool
default y
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
config NO_IOPORT
def_bool y
@@ -79,6 +83,10 @@ config PCI
bool
default n
+config HZ
+ int
+ default 100
+
source "init/Kconfig"
source "arch/h8300/Kconfig.cpu"
diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c
index 8dec4dd57b4..5a1b4cfea05 100644
--- a/arch/h8300/kernel/irq.c
+++ b/arch/h8300/kernel/irq.c
@@ -14,6 +14,7 @@
#include <linux/random.h>
#include <linux/bootmem.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/traps.h>
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c
index b2e86d0255e..b1f25c20a5d 100644
--- a/arch/h8300/kernel/setup.c
+++ b/arch/h8300/kernel/setup.c
@@ -173,7 +173,7 @@ void __init setup_arch(char **cmdline_p)
* the bootmem bitmap so we then reserve it after freeing it :-)
*/
free_bootmem(memory_start, memory_end - memory_start);
- reserve_bootmem(memory_start, bootmap_size);
+ reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
/*
* get kmalloc into gear
*/
@@ -236,7 +236,7 @@ static void c_stop(struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index b0de1132dfc..dff9edfc746 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -15,6 +15,7 @@ config IA64
select ACPI if (!IA64_HP_SIM)
select PM if (!IA64_HP_SIM)
select ARCH_SUPPORTS_MSI
+ select HAVE_IDE
select HAVE_OPROFILE
select HAVE_KPROBES
default y
@@ -231,7 +232,14 @@ config PGTABLE_4
endchoice
+if IA64_HP_SIM
+config HZ
+ default 32
+endif
+
+if !IA64_HP_SIM
source kernel/Kconfig.hz
+endif
config IA64_BRL_EMU
bool
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 45bf04eb7d7..a94445422cc 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1265,7 +1265,7 @@ sba_fill_pdir(
* the sglist do both.
*/
static SBA_INLINE int
-sba_coalesce_chunks( struct ioc *ioc,
+sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
struct scatterlist *startsg,
int nents)
{
@@ -1275,6 +1275,7 @@ sba_coalesce_chunks( struct ioc *ioc,
struct scatterlist *dma_sg; /* next DMA stream head */
unsigned long dma_offset, dma_len; /* start/len of DMA stream */
int n_mappings = 0;
+ unsigned int max_seg_size = dma_get_max_seg_size(dev);
while (nents > 0) {
unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
@@ -1314,6 +1315,9 @@ sba_coalesce_chunks( struct ioc *ioc,
> DMA_CHUNK_SIZE)
break;
+ if (dma_len + startsg->length > max_seg_size)
+ break;
+
/*
** Then look for virtually contiguous blocks.
**
@@ -1441,7 +1445,7 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
** w/o this association, we wouldn't have coherent DMA!
** Access to the virtual address is what forces a two pass algorithm.
*/
- coalesced = sba_coalesce_chunks(ioc, sglist, nents);
+ coalesced = sba_coalesce_chunks(ioc, dev, sglist, nents);
/*
** Program the I/O Pdir
@@ -1871,7 +1875,7 @@ ioc_show(struct seq_file *s, void *v)
return 0;
}
-static struct seq_operations ioc_seq_ops = {
+static const struct seq_operations ioc_seq_ops = {
.start = ioc_start,
.next = ioc_next,
.stop = ioc_stop,
diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c
index d1d50cd1c38..896b1ebbfb2 100644
--- a/arch/ia64/ia32/ia32_support.c
+++ b/arch/ia64/ia32/ia32_support.c
@@ -27,7 +27,7 @@
#include "ia32priv.h"
-extern void die_if_kernel (char *str, struct pt_regs *regs, long err);
+extern int die_if_kernel (char *str, struct pt_regs *regs, long err);
struct exec_domain ia32_exec_domain;
struct page *ia32_shared_page[NR_CPUS];
@@ -217,7 +217,8 @@ ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs)
{
siginfo_t siginfo;
- die_if_kernel("Bad IA-32 interrupt", regs, int_num);
+ if (die_if_kernel("Bad IA-32 interrupt", regs, int_num))
+ return;
siginfo.si_signo = SIGTRAP;
siginfo.si_errno = int_num; /* XXX is it OK to abuse si_errno like this? */
diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c
index 5a216c01992..cbe6cee5a55 100644
--- a/arch/ia64/kernel/acpi-processor.c
+++ b/arch/ia64/kernel/acpi-processor.c
@@ -45,6 +45,12 @@ static void init_intel_pdc(struct acpi_processor *pr)
buf[0] = ACPI_PDC_REVISION_ID;
buf[1] = 1;
buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
+ /*
+ * The default of PDC_SMP_T_SWCOORD bit is set for IA64 cpu so
+ * that OSPM is capable of native ACPI throttling software
+ * coordination using BIOS supplied _TSD info.
+ */
+ buf[2] |= ACPI_PDC_SMP_T_SWCOORD;
obj->type = ACPI_TYPE_BUFFER;
obj->buffer.length = 12;
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 00b5d08f6da..78f28d825f3 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -69,6 +69,20 @@ unsigned int acpi_cpei_phys_cpuid;
unsigned long acpi_wakeup_address = 0;
+#ifdef CONFIG_IA64_GENERIC
+static unsigned long __init acpi_find_rsdp(void)
+{
+ unsigned long rsdp_phys = 0;
+
+ if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
+ rsdp_phys = efi.acpi20;
+ else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
+ printk(KERN_WARNING PREFIX
+ "v1.0/r0.71 tables no longer supported\n");
+ return rsdp_phys;
+}
+#endif
+
const char __init *
acpi_get_sysname(void)
{
@@ -152,7 +166,7 @@ int acpi_request_vector(u32 int_type)
return vector;
}
-char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
+char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
{
return __va(phys_addr);
}
@@ -601,8 +615,6 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity)
IOSAPIC_LEVEL);
}
-EXPORT_SYMBOL(acpi_register_gsi);
-
void acpi_unregister_gsi(u32 gsi)
{
if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
@@ -611,8 +623,6 @@ void acpi_unregister_gsi(u32 gsi)
iosapic_unregister_intr(gsi);
}
-EXPORT_SYMBOL(acpi_unregister_gsi);
-
static int __init acpi_parse_fadt(struct acpi_table_header *table)
{
struct acpi_table_header *fadt_header;
@@ -631,18 +641,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
return 0;
}
-unsigned long __init acpi_find_rsdp(void)
-{
- unsigned long rsdp_phys = 0;
-
- if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
- rsdp_phys = efi.acpi20;
- else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
- printk(KERN_WARNING PREFIX
- "v1.0/r0.71 tables no longer supported\n");
- return rsdp_phys;
-}
-
int __init acpi_boot_init(void)
{
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 242d7934112..919070a9aed 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -1,7 +1,8 @@
/*
* Extensible Firmware Interface
*
- * Based on Extensible Firmware Interface Specification version 0.9 April 30, 1999
+ * Based on Extensible Firmware Interface Specification version 0.9
+ * April 30, 1999
*
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
@@ -48,145 +49,157 @@ static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL;
#define efi_call_virt(f, args...) (*(f))(args)
-#define STUB_GET_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_time_cap_t *atc = NULL; \
- efi_status_t ret; \
- \
- if (tc) \
- atc = adjust_arg(tc); \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), atc); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_GET_TIME(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_time_cap_t *atc = NULL; \
+ efi_status_t ret; \
+ \
+ if (tc) \
+ atc = adjust_arg(tc); \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), \
+ adjust_arg(tm), atc); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_SET_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_set_time (efi_time_t *tm) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), adjust_arg(tm)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_SET_TIME(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_set_time (efi_time_t *tm) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_status_t ret; \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), \
+ adjust_arg(tm)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \
- adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, \
+ efi_time_t *tm) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_status_t ret; \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix( \
+ (efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \
+ adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_time_t *atm = NULL; \
- efi_status_t ret; \
- \
- if (tm) \
- atm = adjust_arg(tm); \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \
- enabled, atm); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_time_t *atm = NULL; \
+ efi_status_t ret; \
+ \
+ if (tm) \
+ atm = adjust_arg(tm); \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix( \
+ (efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \
+ enabled, atm); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_GET_VARIABLE(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \
- unsigned long *data_size, void *data) \
-{ \
- struct ia64_fpreg fr[6]; \
- u32 *aattr = NULL; \
- efi_status_t ret; \
- \
- if (attr) \
- aattr = adjust_arg(attr); \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable), \
- adjust_arg(name), adjust_arg(vendor), aattr, \
- adjust_arg(data_size), adjust_arg(data)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_GET_VARIABLE(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \
+ unsigned long *data_size, void *data) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ u32 *aattr = NULL; \
+ efi_status_t ret; \
+ \
+ if (attr) \
+ aattr = adjust_arg(attr); \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix( \
+ (efi_get_variable_t *) __va(runtime->get_variable), \
+ adjust_arg(name), adjust_arg(vendor), aattr, \
+ adjust_arg(data_size), adjust_arg(data)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_next_variable_t *) __va(runtime->get_next_variable), \
- adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, \
+ efi_guid_t *vendor) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_status_t ret; \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix( \
+ (efi_get_next_variable_t *) __va(runtime->get_next_variable), \
+ adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_SET_VARIABLE(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, unsigned long attr, \
- unsigned long data_size, void *data) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_set_variable_t *) __va(runtime->set_variable), \
- adjust_arg(name), adjust_arg(vendor), attr, data_size, \
- adjust_arg(data)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_SET_VARIABLE(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, \
+ unsigned long attr, unsigned long data_size, \
+ void *data) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_status_t ret; \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix( \
+ (efi_set_variable_t *) __va(runtime->set_variable), \
+ adjust_arg(name), adjust_arg(vendor), attr, data_size, \
+ adjust_arg(data)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \
-static efi_status_t \
-prefix##_get_next_high_mono_count (u32 *count) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_status_t ret; \
- \
- ia64_save_scratch_fpregs(fr); \
- ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \
- __va(runtime->get_next_high_mono_count), adjust_arg(count)); \
- ia64_load_scratch_fpregs(fr); \
- return ret; \
+#define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \
+static efi_status_t \
+prefix##_get_next_high_mono_count (u32 *count) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_status_t ret; \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \
+ __va(runtime->get_next_high_mono_count), \
+ adjust_arg(count)); \
+ ia64_load_scratch_fpregs(fr); \
+ return ret; \
}
-#define STUB_RESET_SYSTEM(prefix, adjust_arg) \
-static void \
-prefix##_reset_system (int reset_type, efi_status_t status, \
- unsigned long data_size, efi_char16_t *data) \
-{ \
- struct ia64_fpreg fr[6]; \
- efi_char16_t *adata = NULL; \
- \
- if (data) \
- adata = adjust_arg(data); \
- \
- ia64_save_scratch_fpregs(fr); \
- efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system), \
- reset_type, status, data_size, adata); \
- /* should not return, but just in case... */ \
- ia64_load_scratch_fpregs(fr); \
+#define STUB_RESET_SYSTEM(prefix, adjust_arg) \
+static void \
+prefix##_reset_system (int reset_type, efi_status_t status, \
+ unsigned long data_size, efi_char16_t *data) \
+{ \
+ struct ia64_fpreg fr[6]; \
+ efi_char16_t *adata = NULL; \
+ \
+ if (data) \
+ adata = adjust_arg(data); \
+ \
+ ia64_save_scratch_fpregs(fr); \
+ efi_call_##prefix( \
+ (efi_reset_system_t *) __va(runtime->reset_system), \
+ reset_type, status, data_size, adata); \
+ /* should not return, but just in case... */ \
+ ia64_load_scratch_fpregs(fr); \
}
#define phys_ptr(arg) ((__typeof__(arg)) ia64_tpa(arg))
@@ -223,7 +236,8 @@ efi_gettimeofday (struct timespec *ts)
return;
}
- ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
+ ts->tv_sec = mktime(tm.year, tm.month, tm.day,
+ tm.hour, tm.minute, tm.second);
ts->tv_nsec = tm.nanosecond;
}
@@ -297,8 +311,8 @@ walk (efi_freemem_callback_t callback, void *arg, u64 attr)
}
/*
- * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
- * has memory that is available for OS use.
+ * Walk the EFI memory map and call CALLBACK once for each EFI memory
+ * descriptor that has memory that is available for OS use.
*/
void
efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
@@ -307,8 +321,8 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
}
/*
- * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
- * has memory that is available for uncached allocator.
+ * Walk the EFI memory map and call CALLBACK once for each EFI memory
+ * descriptor that has memory that is available for uncached allocator.
*/
void
efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg)
@@ -317,11 +331,10 @@ efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg)
}
/*
- * Look for the PAL_CODE region reported by EFI and maps it using an
+ * Look for the PAL_CODE region reported by EFI and map it using an
* ITR to enable safe PAL calls in virtual mode. See IA-64 Processor
* Abstraction Layer chapter 11 in ADAG
*/
-
void *
efi_get_pal_addr (void)
{
@@ -341,45 +354,47 @@ efi_get_pal_addr (void)
continue;
if (++pal_code_count > 1) {
- printk(KERN_ERR "Too many EFI Pal Code memory ranges, dropped @ %lx\n",
- md->phys_addr);
+ printk(KERN_ERR "Too many EFI Pal Code memory ranges, "
+ "dropped @ %lx\n", md->phys_addr);
continue;
}
/*
- * The only ITLB entry in region 7 that is used is the one installed by
- * __start(). That entry covers a 64MB range.
+ * The only ITLB entry in region 7 that is used is the one
+ * installed by __start(). That entry covers a 64MB range.
*/
mask = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1);
vaddr = PAGE_OFFSET + md->phys_addr;
/*
- * We must check that the PAL mapping won't overlap with the kernel
- * mapping.
+ * We must check that the PAL mapping won't overlap with the
+ * kernel mapping.
*
- * PAL code is guaranteed to be aligned on a power of 2 between 4k and
- * 256KB and that only one ITR is needed to map it. This implies that the
- * PAL code is always aligned on its size, i.e., the closest matching page
- * size supported by the TLB. Therefore PAL code is guaranteed never to
- * cross a 64MB unless it is bigger than 64MB (very unlikely!). So for
- * now the following test is enough to determine whether or not we need a
- * dedicated ITR for the PAL code.
+ * PAL code is guaranteed to be aligned on a power of 2 between
+ * 4k and 256KB and that only one ITR is needed to map it. This
+ * implies that the PAL code is always aligned on its size,
+ * i.e., the closest matching page size supported by the TLB.
+ * Therefore PAL code is guaranteed never to cross a 64MB unless
+ * it is bigger than 64MB (very unlikely!). So for now the
+ * following test is enough to determine whether or not we need
+ * a dedicated ITR for the PAL code.
*/
if ((vaddr & mask) == (KERNEL_START & mask)) {
- printk(KERN_INFO "%s: no need to install ITR for PAL code\n",
- __FUNCTION__);
+ printk(KERN_INFO "%s: no need to install ITR for "
+ "PAL code\n", __FUNCTION__);
continue;
}
if (efi_md_size(md) > IA64_GRANULE_SIZE)
- panic("Woah! PAL code size bigger than a granule!");
+ panic("Whoa! PAL code size bigger than a granule!");
#if EFI_DEBUG
mask = ~((1 << IA64_GRANULE_SHIFT) - 1);
- printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
- smp_processor_id(), md->phys_addr,
- md->phys_addr + efi_md_size(md),
- vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
+ printk(KERN_INFO "CPU %d: mapping PAL code "
+ "[0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
+ smp_processor_id(), md->phys_addr,
+ md->phys_addr + efi_md_size(md),
+ vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
#endif
return __va(md->phys_addr);
}
@@ -401,11 +416,11 @@ efi_map_pal_code (void)
* Cannot write to CRx with PSR.ic=1
*/
psr = ia64_clear_ic();
- ia64_itr(0x1, IA64_TR_PALCODE, GRANULEROUNDDOWN((unsigned long) pal_vaddr),
+ ia64_itr(0x1, IA64_TR_PALCODE,
+ GRANULEROUNDDOWN((unsigned long) pal_vaddr),
pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)),
IA64_GRANULE_SHIFT);
ia64_set_psr(psr); /* restore psr */
- ia64_srlz_i();
}
void __init
@@ -418,7 +433,10 @@ efi_init (void)
char *cp, vendor[100] = "unknown";
int i;
- /* it's too early to be able to use the standard kernel command line support... */
+ /*
+ * It's too early to be able to use the standard kernel command line
+ * support...
+ */
for (cp = boot_command_line; *cp; ) {
if (memcmp(cp, "mem=", 4) == 0) {
mem_limit = memparse(cp + 4, &cp);
@@ -434,9 +452,11 @@ efi_init (void)
}
}
if (min_addr != 0UL)
- printk(KERN_INFO "Ignoring memory below %luMB\n", min_addr >> 20);
+ printk(KERN_INFO "Ignoring memory below %luMB\n",
+ min_addr >> 20);
if (max_addr != ~0UL)
- printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20);
+ printk(KERN_INFO "Ignoring memory above %luMB\n",
+ max_addr >> 20);
efi.systab = __va(ia64_boot_param->efi_systab);
@@ -444,9 +464,9 @@ efi_init (void)
* Verify the EFI Table
*/
if (efi.systab == NULL)
- panic("Woah! Can't find EFI system table.\n");
+ panic("Whoa! Can't find EFI system table.\n");
if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
- panic("Woah! EFI system table signature incorrect\n");
+ panic("Whoa! EFI system table signature incorrect\n");
if ((efi.systab->hdr.revision >> 16) == 0)
printk(KERN_WARNING "Warning: EFI system table version "
"%d.%02d, expected 1.00 or greater\n",
@@ -464,7 +484,8 @@ efi_init (void)
}
printk(KERN_INFO "EFI v%u.%.02u by %s:",
- efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
+ efi.systab->hdr.revision >> 16,
+ efi.systab->hdr.revision & 0xffff, vendor);
efi.mps = EFI_INVALID_TABLE_ADDR;
efi.acpi = EFI_INVALID_TABLE_ADDR;
@@ -519,9 +540,12 @@ efi_init (void)
efi_memory_desc_t *md;
void *p;
- for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
+ for (i = 0, p = efi_map_start; p < efi_map_end;
+ ++i, p += efi_desc_size)
+ {
md = p;
- printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
+ printk("mem%02u: type=%u, attr=0x%lx, "
+ "range=[0x%016lx-0x%016lx) (%luMB)\n",
i, md->type, md->attribute, md->phys_addr,
md->phys_addr + efi_md_size(md),
md->num_pages >> (20 - EFI_PAGE_SHIFT));
@@ -549,8 +573,8 @@ efi_enter_virtual_mode (void)
md = p;
if (md->attribute & EFI_MEMORY_RUNTIME) {
/*
- * Some descriptors have multiple bits set, so the order of
- * the tests is relevant.
+ * Some descriptors have multiple bits set, so the
+ * order of the tests is relevant.
*/
if (md->attribute & EFI_MEMORY_WB) {
md->virt_addr = (u64) __va(md->phys_addr);
@@ -558,21 +582,26 @@ efi_enter_virtual_mode (void)
md->virt_addr = (u64) ioremap(md->phys_addr, 0);
} else if (md->attribute & EFI_MEMORY_WC) {
#if 0
- md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
- | _PAGE_D
- | _PAGE_MA_WC
- | _PAGE_PL_0
- | _PAGE_AR_RW));
+ md->virt_addr = ia64_remap(md->phys_addr,
+ (_PAGE_A |
+ _PAGE_P |
+ _PAGE_D |
+ _PAGE_MA_WC |
+ _PAGE_PL_0 |
+ _PAGE_AR_RW));
#else
printk(KERN_INFO "EFI_MEMORY_WC mapping\n");
md->virt_addr = (u64) ioremap(md->phys_addr, 0);
#endif
} else if (md->attribute & EFI_MEMORY_WT) {
#if 0
- md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
- | _PAGE_D | _PAGE_MA_WT
- | _PAGE_PL_0
- | _PAGE_AR_RW));
+ md->virt_addr = ia64_remap(md->phys_addr,
+ (_PAGE_A |
+ _PAGE_P |
+ _PAGE_D |
+ _PAGE_MA_WT |
+ _PAGE_PL_0 |
+ _PAGE_AR_RW));
#else
printk(KERN_INFO "EFI_MEMORY_WT mapping\n");
md->virt_addr = (u64) ioremap(md->phys_addr, 0);
@@ -583,16 +612,18 @@ efi_enter_virtual_mode (void)
status = efi_call_phys(__va(runtime->set_virtual_address_map),
ia64_boot_param->efi_memmap_size,
- efi_desc_size, ia64_boot_param->efi_memdesc_version,
+ efi_desc_size,
+ ia64_boot_param->efi_memdesc_version,
ia64_boot_param->efi_memmap);
if (status != EFI_SUCCESS) {
- printk(KERN_WARNING "warning: unable to switch EFI into virtual mode "
- "(status=%lu)\n", status);
+ printk(KERN_WARNING "warning: unable to switch EFI into "
+ "virtual mode (status=%lu)\n", status);
return;
}
/*
- * Now that EFI is in virtual mode, we call the EFI functions more efficiently:
+ * Now that EFI is in virtual mode, we call the EFI functions more
+ * efficiently:
*/
efi.get_time = virt_get_time;
efi.set_time = virt_set_time;
@@ -606,8 +637,8 @@ efi_enter_virtual_mode (void)
}
/*
- * Walk the EFI memory map looking for the I/O port range. There can only be one entry of
- * this type, other I/O port ranges should be described via ACPI.
+ * Walk the EFI memory map looking for the I/O port range. There can only be
+ * one entry of this type, other I/O port ranges should be described via ACPI.
*/
u64
efi_get_iobase (void)
@@ -678,7 +709,6 @@ efi_memmap_intersects (unsigned long phys_addr, unsigned long size)
for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
md = p;
-
if (md->phys_addr < end && efi_md_end(md) > phys_addr)
return 1;
}
@@ -731,7 +761,7 @@ efi_mem_attribute (unsigned long phys_addr, unsigned long size)
if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr)
return 0;
} while (md);
- return 0;
+ return 0; /* never reached */
}
u64
@@ -767,7 +797,7 @@ kern_mem_attribute (unsigned long phys_addr, unsigned long size)
if (!md || md->attribute != attr)
return 0;
} while (md);
- return 0;
+ return 0; /* never reached */
}
EXPORT_SYMBOL(kern_mem_attribute);
@@ -883,7 +913,7 @@ efi_uart_console_only(void)
return 1;
uart = 0;
}
- hdr = (struct efi_generic_dev_path *) ((u8 *) hdr + hdr->length);
+ hdr = (struct efi_generic_dev_path *)((u8 *) hdr + hdr->length);
}
printk(KERN_ERR "Malformed %s value\n", name);
return 0;
@@ -921,10 +951,12 @@ find_memmap_space (void)
if (!efi_wb(md)) {
continue;
}
- if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) {
+ if (pmd == NULL || !efi_wb(pmd) ||
+ efi_md_end(pmd) != md->phys_addr) {
contig_low = GRANULEROUNDUP(md->phys_addr);
contig_high = efi_md_end(md);
- for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) {
+ for (q = p + efi_desc_size; q < efi_map_end;
+ q += efi_desc_size) {
check_md = q;
if (!efi_wb(check_md))
break;
@@ -988,8 +1020,9 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) {
md = p;
if (!efi_wb(md)) {
- if (efi_uc(md) && (md->type == EFI_CONVENTIONAL_MEMORY ||
- md->type == EFI_BOOT_SERVICES_DATA)) {
+ if (efi_uc(md) &&
+ (md->type == EFI_CONVENTIONAL_MEMORY ||
+ md->type == EFI_BOOT_SERVICES_DATA)) {
k->attribute = EFI_MEMORY_UC;
k->start = md->phys_addr;
k->num_pages = md->num_pages;
@@ -997,10 +1030,12 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
}
continue;
}
- if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) {
+ if (pmd == NULL || !efi_wb(pmd) ||
+ efi_md_end(pmd) != md->phys_addr) {
contig_low = GRANULEROUNDUP(md->phys_addr);
contig_high = efi_md_end(md);
- for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) {
+ for (q = p + efi_desc_size; q < efi_map_end;
+ q += efi_desc_size) {
check_md = q;
if (!efi_wb(check_md))
break;
@@ -1025,13 +1060,17 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
if (md->phys_addr < contig_low) {
lim = min(efi_md_end(md), contig_low);
if (efi_uc(md)) {
- if (k > kern_memmap && (k-1)->attribute == EFI_MEMORY_UC &&
+ if (k > kern_memmap &&
+ (k-1)->attribute == EFI_MEMORY_UC &&
kmd_end(k-1) == md->phys_addr) {
- (k-1)->num_pages += (lim - md->phys_addr) >> EFI_PAGE_SHIFT;
+ (k-1)->num_pages +=
+ (lim - md->phys_addr)
+ >> EFI_PAGE_SHIFT;
} else {
k->attribute = EFI_MEMORY_UC;
k->start = md->phys_addr;
- k->num_pages = (lim - md->phys_addr) >> EFI_PAGE_SHIFT;
+ k->num_pages = (lim - md->phys_addr)
+ >> EFI_PAGE_SHIFT;
k++;
}
}
@@ -1049,7 +1088,8 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
} else {
k->attribute = EFI_MEMORY_UC;
k->start = lim;
- k->num_pages = (efi_md_end(md) - lim) >> EFI_PAGE_SHIFT;
+ k->num_pages = (efi_md_end(md) - lim)
+ >> EFI_PAGE_SHIFT;
k++;
}
}
@@ -1151,8 +1191,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
break;
}
- if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "failed to alocate resource for iomem\n");
+ if ((res = kzalloc(sizeof(struct resource),
+ GFP_KERNEL)) == NULL) {
+ printk(KERN_ERR
+ "failed to allocate resource for iomem\n");
return;
}
@@ -1187,44 +1229,44 @@ efi_initialize_iomem_resources(struct resource *code_resource,
rsvd_regions are sorted
*/
unsigned long __init
-kdump_find_rsvd_region (unsigned long size,
- struct rsvd_region *r, int n)
+kdump_find_rsvd_region (unsigned long size, struct rsvd_region *r, int n)
{
- int i;
- u64 start, end;
- u64 alignment = 1UL << _PAGE_SIZE_64M;
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t *md;
- u64 efi_desc_size;
-
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- md = p;
- if (!efi_wb(md))
- continue;
- start = ALIGN(md->phys_addr, alignment);
- end = efi_md_end(md);
- for (i = 0; i < n; i++) {
- if (__pa(r[i].start) >= start && __pa(r[i].end) < end) {
- if (__pa(r[i].start) > start + size)
- return start;
- start = ALIGN(__pa(r[i].end), alignment);
- if (i < n-1 && __pa(r[i+1].start) < start + size)
- continue;
- else
- break;
+ int i;
+ u64 start, end;
+ u64 alignment = 1UL << _PAGE_SIZE_64M;
+ void *efi_map_start, *efi_map_end, *p;
+ efi_memory_desc_t *md;
+ u64 efi_desc_size;
+
+ efi_map_start = __va(ia64_boot_param->efi_memmap);
+ efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
+ efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+ for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+ md = p;
+ if (!efi_wb(md))
+ continue;
+ start = ALIGN(md->phys_addr, alignment);
+ end = efi_md_end(md);
+ for (i = 0; i < n; i++) {
+ if (__pa(r[i].start) >= start && __pa(r[i].end) < end) {
+ if (__pa(r[i].start) > start + size)
+ return start;
+ start = ALIGN(__pa(r[i].end), alignment);
+ if (i < n-1 &&
+ __pa(r[i+1].start) < start + size)
+ continue;
+ else
+ break;
+ }
}
- }
- if (end > start + size)
- return start;
- }
-
- printk(KERN_WARNING "Cannot reserve 0x%lx byte of memory for crashdump\n",
- size);
- return ~0UL;
+ if (end > start + size)
+ return start;
+ }
+
+ printk(KERN_WARNING
+ "Cannot reserve 0x%lx byte of memory for crashdump\n", size);
+ return ~0UL;
}
#endif
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index c36f43c9460..3c331c464b4 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1573,7 +1573,7 @@ sys_call_table:
data8 sys_fchmodat
data8 sys_faccessat
data8 sys_pselect6
- data8 sys_ppoll
+ data8 sys_ppoll // 1295
data8 sys_unshare
data8 sys_splice
data8 sys_set_robust_list
@@ -1586,7 +1586,10 @@ sys_call_table:
data8 sys_epoll_pwait // 1305
data8 sys_utimensat
data8 sys_signalfd
- data8 sys_timerfd
+ data8 sys_ni_syscall
data8 sys_eventfd
+ data8 sys_timerfd_create // 1310
+ data8 sys_timerfd_settime
+ data8 sys_timerfd_gettime
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/fsyscall_gtod_data.h b/arch/ia64/kernel/fsyscall_gtod_data.h
index 490dab55fba..57d2ee6c83e 100644
--- a/arch/ia64/kernel/fsyscall_gtod_data.h
+++ b/arch/ia64/kernel/fsyscall_gtod_data.h
@@ -14,10 +14,10 @@ struct fsyscall_gtod_data_t {
u32 clk_shift;
void *clk_fsys_mmio;
cycle_t clk_cycle_last;
-} __attribute__ ((aligned (L1_CACHE_BYTES)));
+} ____cacheline_aligned;
struct itc_jitter_data_t {
int itc_jitter;
cycle_t itc_lastcycle;
-} __attribute__ ((aligned (L1_CACHE_BYTES)));
+} ____cacheline_aligned;
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
index c3b4412ccc6..8e7193d5552 100644
--- a/arch/ia64/kernel/ia64_ksyms.c
+++ b/arch/ia64/kernel/ia64_ksyms.c
@@ -12,6 +12,9 @@ EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(strlen);
+#include<asm/pgtable.h>
+EXPORT_SYMBOL_GPL(empty_zero_page);
+
#include <asm/checksum.h>
EXPORT_SYMBOL(ip_fast_csum); /* hand-coded assembly */
EXPORT_SYMBOL(csum_ipv6_magic);
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index fc4d2676264..b618487cdc8 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -381,9 +381,10 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
unsigned int i;
- i = atomic_sub_return(1, &kcb->prev_kprobe_index);
- __get_cpu_var(current_kprobe) = kcb->prev_kprobe[i].kp;
- kcb->kprobe_status = kcb->prev_kprobe[i].status;
+ i = atomic_read(&kcb->prev_kprobe_index);
+ __get_cpu_var(current_kprobe) = kcb->prev_kprobe[i-1].kp;
+ kcb->kprobe_status = kcb->prev_kprobe[i-1].status;
+ atomic_sub(1, &kcb->prev_kprobe_index);
}
static void __kprobes set_current_kprobe(struct kprobe *p,
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
index d6cd45f4c6c..0823de1f6eb 100644
--- a/arch/ia64/kernel/machine_kexec.c
+++ b/arch/ia64/kernel/machine_kexec.c
@@ -129,13 +129,14 @@ void machine_kexec(struct kimage *image)
void arch_crash_save_vmcoreinfo(void)
{
-#if defined(CONFIG_ARCH_DISCONTIGMEM_ENABLE) && defined(CONFIG_NUMA)
+#if defined(CONFIG_DISCONTIGMEM) || defined(CONFIG_SPARSEMEM)
VMCOREINFO_SYMBOL(pgdat_list);
VMCOREINFO_LENGTH(pgdat_list, MAX_NUMNODES);
-
+#endif
+#ifdef CONFIG_NUMA
VMCOREINFO_SYMBOL(node_memblk);
VMCOREINFO_LENGTH(node_memblk, NR_NODE_MEMBLKS);
- VMCOREINFO_SIZE(node_memblk_s);
+ VMCOREINFO_STRUCT_SIZE(node_memblk_s);
VMCOREINFO_OFFSET(node_memblk_s, start_paddr);
VMCOREINFO_OFFSET(node_memblk_s, size);
#endif
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 6dbf5919d2d..6e17aed5313 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -2,61 +2,69 @@
* File: mca.c
* Purpose: Generic MCA handling layer
*
- * Updated for latest kernel
* Copyright (C) 2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* Copyright (C) 2002 Dell Inc.
- * Copyright (C) Matt Domsch (Matt_Domsch@dell.com)
+ * Copyright (C) Matt Domsch <Matt_Domsch@dell.com>
*
* Copyright (C) 2002 Intel
- * Copyright (C) Jenna Hall (jenna.s.hall@intel.com)
+ * Copyright (C) Jenna Hall <jenna.s.hall@intel.com>
*
* Copyright (C) 2001 Intel
- * Copyright (C) Fred Lewis (frederick.v.lewis@intel.com)
+ * Copyright (C) Fred Lewis <frederick.v.lewis@intel.com>
*
* Copyright (C) 2000 Intel
- * Copyright (C) Chuck Fleckenstein (cfleck@co.intel.com)
+ * Copyright (C) Chuck Fleckenstein <cfleck@co.intel.com>
*
- * Copyright (C) 1999, 2004 Silicon Graphics, Inc.
- * Copyright (C) Vijay Chander(vijay@engr.sgi.com)
+ * Copyright (C) 1999, 2004-2008 Silicon Graphics, Inc.
+ * Copyright (C) Vijay Chander <vijay@engr.sgi.com>
*
- * 03/04/15 D. Mosberger Added INIT backtrace support.
- * 02/03/25 M. Domsch GUID cleanups
+ * Copyright (C) 2006 FUJITSU LIMITED
+ * Copyright (C) Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
*
- * 02/01/04 J. Hall Aligned MCA stack to 16 bytes, added platform vs. CPU
- * error flag, set SAL default return values, changed
- * error record structure to linked list, added init call
- * to sal_get_state_info_size().
+ * 2000-03-29 Chuck Fleckenstein <cfleck@co.intel.com>
+ * Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
+ * added min save state dump, added INIT handler.
*
- * 01/01/03 F. Lewis Added setup of CMCI and CPEI IRQs, logging of corrected
- * platform errors, completed code for logging of
- * corrected & uncorrected machine check errors, and
- * updated for conformance with Nov. 2000 revision of the
- * SAL 3.0 spec.
- * 00/03/29 C. Fleckenstein Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
- * added min save state dump, added INIT handler.
+ * 2001-01-03 Fred Lewis <frederick.v.lewis@intel.com>
+ * Added setup of CMCI and CPEI IRQs, logging of corrected platform
+ * errors, completed code for logging of corrected & uncorrected
+ * machine check errors, and updated for conformance with Nov. 2000
+ * revision of the SAL 3.0 spec.
+ *
+ * 2002-01-04 Jenna Hall <jenna.s.hall@intel.com>
+ * Aligned MCA stack to 16 bytes, added platform vs. CPU error flag,
+ * set SAL default return values, changed error record structure to
+ * linked list, added init call to sal_get_state_info_size().
+ *
+ * 2002-03-25 Matt Domsch <Matt_Domsch@dell.com>
+ * GUID cleanups.
+ *
+ * 2003-04-15 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Added INIT backtrace support.
*
* 2003-12-08 Keith Owens <kaos@sgi.com>
- * smp_call_function() must not be called from interrupt context (can
- * deadlock on tasklist_lock). Use keventd to call smp_call_function().
+ * smp_call_function() must not be called from interrupt context
+ * (can deadlock on tasklist_lock).
+ * Use keventd to call smp_call_function().
*
* 2004-02-01 Keith Owens <kaos@sgi.com>
- * Avoid deadlock when using printk() for MCA and INIT records.
- * Delete all record printing code, moved to salinfo_decode in user space.
- * Mark variables and functions static where possible.
- * Delete dead variables and functions.
- * Reorder to remove the need for forward declarations and to consolidate
- * related code.
+ * Avoid deadlock when using printk() for MCA and INIT records.
+ * Delete all record printing code, moved to salinfo_decode in user
+ * space. Mark variables and functions static where possible.
+ * Delete dead variables and functions. Reorder to remove the need
+ * for forward declarations and to consolidate related code.
*
* 2005-08-12 Keith Owens <kaos@sgi.com>
- * Convert MCA/INIT handlers to use per event stacks and SAL/OS state.
+ * Convert MCA/INIT handlers to use per event stacks and SAL/OS
+ * state.
*
* 2005-10-07 Keith Owens <kaos@sgi.com>
* Add notify_die() hooks.
*
* 2006-09-15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
- * Add printing support for MCA/INIT.
+ * Add printing support for MCA/INIT.
*
* 2007-04-27 Russ Anderson <rja@sgi.com>
* Support multiple cpus going through OS_MCA in the same event.
@@ -1754,11 +1762,8 @@ format_mca_init_stack(void *mca_data, unsigned long offset,
/* Caller prevents this from being called after init */
static void * __init_refok mca_bootmem(void)
{
- void *p;
-
- p = alloc_bootmem(sizeof(struct ia64_mca_cpu) * NR_CPUS +
- KERNEL_STACK_SIZE);
- return (void *)ALIGN((unsigned long)p, KERNEL_STACK_SIZE);
+ return __alloc_bootmem(sizeof(struct ia64_mca_cpu),
+ KERNEL_STACK_SIZE, 0);
}
/* Do per-CPU MCA-related initialization. */
@@ -1766,33 +1771,33 @@ void __cpuinit
ia64_mca_cpu_init(void *cpu_data)
{
void *pal_vaddr;
+ void *data;
+ long sz = sizeof(struct ia64_mca_cpu);
+ int cpu = smp_processor_id();
static int first_time = 1;
- if (first_time) {
- void *mca_data;
- int cpu;
-
- first_time = 0;
- mca_data = mca_bootmem();
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- format_mca_init_stack(mca_data,
- offsetof(struct ia64_mca_cpu, mca_stack),
- "MCA", cpu);
- format_mca_init_stack(mca_data,
- offsetof(struct ia64_mca_cpu, init_stack),
- "INIT", cpu);
- __per_cpu_mca[cpu] = __pa(mca_data);
- mca_data += sizeof(struct ia64_mca_cpu);
- }
- }
-
/*
- * The MCA info structure was allocated earlier and its
- * physical address saved in __per_cpu_mca[cpu]. Copy that
- * address * to ia64_mca_data so we can access it as a per-CPU
- * variable.
+ * Structure will already be allocated if cpu has been online,
+ * then offlined.
*/
- __get_cpu_var(ia64_mca_data) = __per_cpu_mca[smp_processor_id()];
+ if (__per_cpu_mca[cpu]) {
+ data = __va(__per_cpu_mca[cpu]);
+ } else {
+ if (first_time) {
+ data = mca_bootmem();
+ first_time = 0;
+ } else
+ data = page_address(alloc_pages_node(numa_node_id(),
+ GFP_KERNEL, get_order(sz)));
+ if (!data)
+ panic("Could not allocate MCA memory for cpu %d\n",
+ cpu);
+ }
+ format_mca_init_stack(data, offsetof(struct ia64_mca_cpu, mca_stack),
+ "MCA", cpu);
+ format_mca_init_stack(data, offsetof(struct ia64_mca_cpu, init_stack),
+ "INIT", cpu);
+ __get_cpu_var(ia64_mca_data) = __per_cpu_mca[cpu] = __pa(data);
/*
* Stash away a copy of the PTE needed to map the per-CPU page.
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 0f5965fcdf8..8bc7d259e0c 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -1,24 +1,28 @@
-//
-// assembly portion of the IA64 MCA handling
-//
-// Mods by cfleck to integrate into kernel build
-// 00/03/15 davidm Added various stop bits to get a clean compile
-//
-// 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp
-// kstack, switch modes, jump to C INIT handler
-//
-// 02/01/04 J.Hall <jenna.s.hall@intel.com>
-// Before entering virtual mode code:
-// 1. Check for TLB CPU error
-// 2. Restore current thread pointer to kr6
-// 3. Move stack ptr 16 bytes to conform to C calling convention
-//
-// 04/11/12 Russ Anderson <rja@sgi.com>
-// Added per cpu MCA/INIT stack save areas.
-//
-// 12/08/05 Keith Owens <kaos@sgi.com>
-// Use per cpu MCA/INIT stacks for all data.
-//
+/*
+ * File: mca_asm.S
+ * Purpose: assembly portion of the IA64 MCA handling
+ *
+ * Mods by cfleck to integrate into kernel build
+ *
+ * 2000-03-15 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Added various stop bits to get a clean compile
+ *
+ * 2000-03-29 Chuck Fleckenstein <cfleck@co.intel.com>
+ * Added code to save INIT handoff state in pt_regs format,
+ * switch to temp kstack, switch modes, jump to C INIT handler
+ *
+ * 2002-01-04 J.Hall <jenna.s.hall@intel.com>
+ * Before entering virtual mode code:
+ * 1. Check for TLB CPU error
+ * 2. Restore current thread pointer to kr6
+ * 3. Move stack ptr 16 bytes to conform to C calling convention
+ *
+ * 2004-11-12 Russ Anderson <rja@sgi.com>
+ * Added per cpu MCA/INIT stack save areas.
+ *
+ * 2005-12-08 Keith Owens <kaos@sgi.com>
+ * Use per cpu MCA/INIT stacks for all data.
+ */
#include <linux/threads.h>
#include <asm/asmmacro.h>
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index aba813c2c15..fab1d21a4f2 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -3,7 +3,7 @@
* Purpose: Generic MCA handling layer
*
* Copyright (C) 2004 FUJITSU LIMITED
- * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
* Copyright (C) 2005 Silicon Graphics, Inc
* Copyright (C) 2005 Keith Owens <kaos@sgi.com>
* Copyright (C) 2006 Russ Anderson <rja@sgi.com>
diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h
index 485e34d0b19..53b8ecb5b4b 100644
--- a/arch/ia64/kernel/mca_drv.h
+++ b/arch/ia64/kernel/mca_drv.h
@@ -3,7 +3,7 @@
* Purpose: Define helpers for Generic MCA handling
*
* Copyright (C) 2004 FUJITSU LIMITED
- * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
*/
/*
* Processor error section:
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
index 3bccb06c8d2..767ac2c20d1 100644
--- a/arch/ia64/kernel/mca_drv_asm.S
+++ b/arch/ia64/kernel/mca_drv_asm.S
@@ -3,7 +3,7 @@
* Purpose: Assembly portion of Generic MCA handling
*
* Copyright (C) 2004 FUJITSU LIMITED
- * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
*/
#include <linux/threads.h>
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 5ae177f557d..f6b99719f10 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -586,21 +586,6 @@ pfm_put_task(struct task_struct *task)
}
static inline void
-pfm_set_task_notify(struct task_struct *task)
-{
- struct thread_info *info;
-
- info = (struct thread_info *) ((char *) task + IA64_TASK_SIZE);
- set_bit(TIF_PERFMON_WORK, &info->flags);
-}
-
-static inline void
-pfm_clear_task_notify(void)
-{
- clear_thread_flag(TIF_PERFMON_WORK);
-}
-
-static inline void
pfm_reserve_page(unsigned long a)
{
SetPageReserved(vmalloc_to_page((void *)a));
@@ -2654,11 +2639,11 @@ pfm_get_task(pfm_context_t *ctx, pid_t pid, struct task_struct **task)
/* XXX: need to add more checks here */
if (pid < 2) return -EPERM;
- if (pid != current->pid) {
+ if (pid != task_pid_vnr(current)) {
read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
+ p = find_task_by_vpid(pid);
/* make sure task cannot go away while we operate on it */
if (p) get_task_struct(p);
@@ -3724,7 +3709,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
PFM_SET_WORK_PENDING(task, 1);
- pfm_set_task_notify(task);
+ tsk_set_notify_resume(task);
/*
* XXX: send reschedule if task runs on another CPU
@@ -5082,7 +5067,7 @@ pfm_handle_work(void)
PFM_SET_WORK_PENDING(current, 0);
- pfm_clear_task_notify();
+ tsk_clear_notify_resume(current);
regs = task_pt_regs(current);
@@ -5450,7 +5435,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str
* when coming from ctxsw, current still points to the
* previous task, therefore we must work with task and not current.
*/
- pfm_set_task_notify(task);
+ tsk_set_notify_resume(task);
}
/*
* defer until state is changed (shorten spin window). the context is locked
@@ -5795,7 +5780,7 @@ pfm_proc_show(struct seq_file *m, void *v)
return 0;
}
-struct seq_operations pfm_seq_ops = {
+const struct seq_operations pfm_seq_ops = {
.start = pfm_proc_start,
.next = pfm_proc_next,
.stop = pfm_proc_stop,
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 7377d323131..49937a383b2 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -52,7 +52,6 @@
#include "sigframe.h"
void (*ia64_mark_idle)(int);
-static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
unsigned long boot_option_idle_override = 0;
EXPORT_SYMBOL(boot_option_idle_override);
@@ -157,6 +156,17 @@ show_regs (struct pt_regs *regs)
show_stack(NULL, NULL);
}
+void tsk_clear_notify_resume(struct task_struct *tsk)
+{
+#ifdef CONFIG_PERFMON
+ if (tsk->thread.pfm_needs_checking)
+ return;
+#endif
+ if (test_ti_thread_flag(task_thread_info(tsk), TIF_RESTORE_RSE))
+ return;
+ clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME);
+}
+
void
do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall)
{
@@ -175,6 +185,10 @@ do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall
/* deal with pending signal delivery */
if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK))
ia64_do_signal(scr, in_syscall);
+
+ /* copy user rbs to kernel rbs */
+ if (unlikely(test_thread_flag(TIF_RESTORE_RSE)))
+ ia64_sync_krbs();
}
static int pal_halt = 1;
@@ -239,33 +253,23 @@ static inline void play_dead(void)
}
#endif /* CONFIG_HOTPLUG_CPU */
-void cpu_idle_wait(void)
+static void do_nothing(void *unused)
{
- unsigned int cpu, this_cpu = get_cpu();
- cpumask_t map;
- cpumask_t tmp = current->cpus_allowed;
-
- set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
- put_cpu();
-
- cpus_clear(map);
- for_each_online_cpu(cpu) {
- per_cpu(cpu_idle_state, cpu) = 1;
- cpu_set(cpu, map);
- }
-
- __get_cpu_var(cpu_idle_state) = 0;
+}
- wmb();
- do {
- ssleep(1);
- for_each_online_cpu(cpu) {
- if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
- cpu_clear(cpu, map);
- }
- cpus_and(map, map, cpu_online_map);
- } while (!cpus_empty(map));
- set_cpus_allowed(current, tmp);
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+ * pm_idle and update to new pm_idle value. Required while changing pm_idle
+ * handler on SMP systems.
+ *
+ * Caller must have changed pm_idle to the new value before the call. Old
+ * pm_idle value will not be used by any CPU after the return of this function.
+ */
+void cpu_idle_wait(void)
+{
+ smp_mb();
+ /* kick all the CPUs so that they exit out of pm_idle */
+ smp_call_function(do_nothing, NULL, 0, 1);
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
@@ -293,9 +297,6 @@ cpu_idle (void)
#ifdef CONFIG_SMP
min_xtp();
#endif
- if (__get_cpu_var(cpu_idle_state))
- __get_cpu_var(cpu_idle_state) = 0;
-
rmb();
if (mark_idle)
(*mark_idle)(1);
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 2e96f17b2f3..331d6768b5d 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -547,6 +547,129 @@ ia64_sync_user_rbs (struct task_struct *child, struct switch_stack *sw,
return 0;
}
+static long
+ia64_sync_kernel_rbs (struct task_struct *child, struct switch_stack *sw,
+ unsigned long user_rbs_start, unsigned long user_rbs_end)
+{
+ unsigned long addr, val;
+ long ret;
+
+ /* now copy word for word from user rbs to kernel rbs: */
+ for (addr = user_rbs_start; addr < user_rbs_end; addr += 8) {
+ if (access_process_vm(child, addr, &val, sizeof(val), 0)
+ != sizeof(val))
+ return -EIO;
+
+ ret = ia64_poke(child, sw, user_rbs_end, addr, val);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
+typedef long (*syncfunc_t)(struct task_struct *, struct switch_stack *,
+ unsigned long, unsigned long);
+
+static void do_sync_rbs(struct unw_frame_info *info, void *arg)
+{
+ struct pt_regs *pt;
+ unsigned long urbs_end;
+ syncfunc_t fn = arg;
+
+ if (unw_unwind_to_user(info) < 0)
+ return;
+ pt = task_pt_regs(info->task);
+ urbs_end = ia64_get_user_rbs_end(info->task, pt, NULL);
+
+ fn(info->task, info->sw, pt->ar_bspstore, urbs_end);
+}
+
+/*
+ * when a thread is stopped (ptraced), debugger might change thread's user
+ * stack (change memory directly), and we must avoid the RSE stored in kernel
+ * to override user stack (user space's RSE is newer than kernel's in the
+ * case). To workaround the issue, we copy kernel RSE to user RSE before the
+ * task is stopped, so user RSE has updated data. we then copy user RSE to
+ * kernel after the task is resummed from traced stop and kernel will use the
+ * newer RSE to return to user. TIF_RESTORE_RSE is the flag to indicate we need
+ * synchronize user RSE to kernel.
+ */
+void ia64_ptrace_stop(void)
+{
+ if (test_and_set_tsk_thread_flag(current, TIF_RESTORE_RSE))
+ return;
+ tsk_set_notify_resume(current);
+ unw_init_running(do_sync_rbs, ia64_sync_user_rbs);
+}
+
+/*
+ * This is called to read back the register backing store.
+ */
+void ia64_sync_krbs(void)
+{
+ clear_tsk_thread_flag(current, TIF_RESTORE_RSE);
+ tsk_clear_notify_resume(current);
+
+ unw_init_running(do_sync_rbs, ia64_sync_kernel_rbs);
+}
+
+/*
+ * After PTRACE_ATTACH, a thread's register backing store area in user
+ * space is assumed to contain correct data whenever the thread is
+ * stopped. arch_ptrace_stop takes care of this on tracing stops.
+ * But if the child was already stopped for job control when we attach
+ * to it, then it might not ever get into ptrace_stop by the time we
+ * want to examine the user memory containing the RBS.
+ */
+void
+ptrace_attach_sync_user_rbs (struct task_struct *child)
+{
+ int stopped = 0;
+ struct unw_frame_info info;
+
+ /*
+ * If the child is in TASK_STOPPED, we need to change that to
+ * TASK_TRACED momentarily while we operate on it. This ensures
+ * that the child won't be woken up and return to user mode while
+ * we are doing the sync. (It can only be woken up for SIGKILL.)
+ */
+
+ read_lock(&tasklist_lock);
+ if (child->signal) {
+ spin_lock_irq(&child->sighand->siglock);
+ if (child->state == TASK_STOPPED &&
+ !test_and_set_tsk_thread_flag(child, TIF_RESTORE_RSE)) {
+ tsk_set_notify_resume(child);
+
+ child->state = TASK_TRACED;
+ stopped = 1;
+ }
+ spin_unlock_irq(&child->sighand->siglock);
+ }
+ read_unlock(&tasklist_lock);
+
+ if (!stopped)
+ return;
+
+ unw_init_from_blocked_task(&info, child);
+ do_sync_rbs(&info, ia64_sync_user_rbs);
+
+ /*
+ * Now move the child back into TASK_STOPPED if it should be in a
+ * job control stop, so that SIGCONT can be used to wake it up.
+ */
+ read_lock(&tasklist_lock);
+ if (child->signal) {
+ spin_lock_irq(&child->sighand->siglock);
+ if (child->state == TASK_TRACED &&
+ (child->signal->flags & SIGNAL_STOP_STOPPED)) {
+ child->state = TASK_STOPPED;
+ }
+ spin_unlock_irq(&child->sighand->siglock);
+ }
+ read_unlock(&tasklist_lock);
+}
+
static inline int
thread_matches (struct task_struct *thread, unsigned long addr)
{
@@ -1422,6 +1545,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
struct task_struct *child;
struct switch_stack *sw;
long ret;
+ struct unw_frame_info info;
lock_kernel();
ret = -EPERM;
@@ -1453,6 +1577,8 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
+ if (!ret)
+ arch_ptrace_attach(child);
goto out_tsk;
}
@@ -1481,6 +1607,11 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
/* write the word at location addr */
urbs_end = ia64_get_user_rbs_end(child, pt, NULL);
ret = ia64_poke(child, sw, urbs_end, addr, data);
+
+ /* Make sure user RBS has the latest data */
+ unw_init_from_blocked_task(&info, child);
+ do_sync_rbs(&info, ia64_sync_user_rbs);
+
goto out_tsk;
case PTRACE_PEEKUSR:
@@ -1634,6 +1765,10 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
&& (current->ptrace & PT_PTRACED))
syscall_trace();
+ /* copy user rbs to kernel rbs */
+ if (test_thread_flag(TIF_RESTORE_RSE))
+ ia64_sync_krbs();
+
if (unlikely(current->audit_context)) {
long syscall;
int arch;
@@ -1671,4 +1806,8 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
|| test_thread_flag(TIF_SINGLESTEP))
&& (current->ptrace & PT_PTRACED))
syscall_trace();
+
+ /* copy user rbs to kernel rbs */
+ if (test_thread_flag(TIF_RESTORE_RSE))
+ ia64_sync_krbs();
}
diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
index 27c2ef445a5..f44fe841216 100644
--- a/arch/ia64/kernel/sal.c
+++ b/arch/ia64/kernel/sal.c
@@ -284,6 +284,7 @@ ia64_sal_cache_flush (u64 cache_type)
SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0);
return isrv.status;
}
+EXPORT_SYMBOL_GPL(ia64_sal_cache_flush);
void __init
ia64_sal_init (struct ia64_sal_systab *systab)
@@ -372,3 +373,16 @@ ia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc,
return 0;
}
EXPORT_SYMBOL(ia64_sal_oemcall_reentrant);
+
+long
+ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second,
+ unsigned long *drift_info)
+{
+ struct ia64_sal_retval isrv;
+
+ SAL_CALL(isrv, SAL_FREQ_BASE, which, 0, 0, 0, 0, 0, 0);
+ *ticks_per_second = isrv.v0;
+ *drift_info = isrv.v1;
+ return isrv.status;
+}
+EXPORT_SYMBOL_GPL(ia64_sal_freq_base);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 86028c69861..ebd1a09f320 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -654,7 +654,7 @@ c_stop (struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index f0fc4d8465a..32ee5979a04 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -120,7 +120,6 @@ static volatile unsigned long go[SLAVE + 1];
#define DEBUG_ITC_SYNC 0
-extern void __devinit calibrate_delay (void);
extern void start_ap (void);
extern unsigned long ia64_iobase;
@@ -477,7 +476,7 @@ start_secondary (void *unused)
return 0;
}
-struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
+struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
{
return NULL;
}
@@ -767,17 +766,6 @@ void __cpu_die(unsigned int cpu)
}
printk(KERN_ERR "CPU %u didn't die...\n", cpu);
}
-#else /* !CONFIG_HOTPLUG_CPU */
-int __cpu_disable(void)
-{
- return -ENOSYS;
-}
-
-void __cpu_die(unsigned int cpu)
-{
- /* We said "no" in __cpu_disable */
- BUG();
-}
#endif /* CONFIG_HOTPLUG_CPU */
void
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 3ab04272097..17fda5293c6 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -49,13 +49,13 @@ EXPORT_SYMBOL(last_cli_ip);
#endif
static struct clocksource clocksource_itc = {
- .name = "itc",
- .rating = 350,
- .read = itc_get_cycles,
- .mask = CLOCKSOURCE_MASK(64),
- .mult = 0, /*to be caluclated*/
- .shift = 16,
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .name = "itc",
+ .rating = 350,
+ .read = itc_get_cycles,
+ .mask = CLOCKSOURCE_MASK(64),
+ .mult = 0, /*to be calculated*/
+ .shift = 16,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static struct clocksource *itc_clocksource;
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index 78d65cb947d..f0cda765e68 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -35,7 +35,7 @@ trap_init (void)
fpswa_interface = __va(ia64_boot_param->fpswa);
}
-void
+int
die (const char *str, struct pt_regs *regs, long err)
{
static struct {
@@ -62,8 +62,11 @@ die (const char *str, struct pt_regs *regs, long err)
if (++die.lock_owner_depth < 3) {
printk("%s[%d]: %s %ld [%d]\n",
current->comm, task_pid_nr(current), str, err, ++die_counter);
- (void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
- show_regs(regs);
+ if (notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV)
+ != NOTIFY_STOP)
+ show_regs(regs);
+ else
+ regs = NULL;
} else
printk(KERN_ERR "Recursive die() failure, output suppressed\n");
@@ -72,17 +75,22 @@ die (const char *str, struct pt_regs *regs, long err)
add_taint(TAINT_DIE);
spin_unlock_irq(&die.lock);
+ if (!regs)
+ return 1;
+
if (panic_on_oops)
panic("Fatal exception");
do_exit(SIGSEGV);
+ return 0;
}
-void
+int
die_if_kernel (char *str, struct pt_regs *regs, long err)
{
if (!user_mode(regs))
- die(str, regs, err);
+ return die(str, regs, err);
+ return 0;
}
void
@@ -102,7 +110,8 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP)
== NOTIFY_STOP)
return;
- die_if_kernel("bugcheck!", regs, break_num);
+ if (die_if_kernel("bugcheck!", regs, break_num))
+ return;
sig = SIGILL; code = ILL_ILLOPC;
break;
@@ -155,8 +164,9 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
break;
default:
- if (break_num < 0x40000 || break_num > 0x100000)
- die_if_kernel("Bad break", regs, break_num);
+ if ((break_num < 0x40000 || break_num > 0x100000)
+ && die_if_kernel("Bad break", regs, break_num))
+ return;
if (break_num < 0x80000) {
sig = SIGILL; code = __ILL_BREAK;
@@ -402,14 +412,15 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
#endif
sprintf(buf, "IA-64 Illegal operation fault");
- die_if_kernel(buf, &regs, 0);
+ rv.fkt = 0;
+ if (die_if_kernel(buf, &regs, 0))
+ return rv;
memset(&si, 0, sizeof(si));
si.si_signo = SIGILL;
si.si_code = ILL_ILLOPC;
si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(&regs)->ri);
force_sig_info(SIGILL, &si, current);
- rv.fkt = 0;
return rv;
}
@@ -644,6 +655,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
sprintf(buf, "Fault %lu", vector);
break;
}
- die_if_kernel(buf, &regs, error);
- force_sig(SIGILL, current);
+ if (!die_if_kernel(buf, &regs, error))
+ force_sig(SIGILL, current);
}
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
index f6a1aeb742b..52f70bbc192 100644
--- a/arch/ia64/kernel/unaligned.c
+++ b/arch/ia64/kernel/unaligned.c
@@ -23,7 +23,7 @@
#include <asm/uaccess.h>
#include <asm/unaligned.h>
-extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
+extern int die_if_kernel(char *str, struct pt_regs *regs, long err);
#undef DEBUG_UNALIGNED_TRAP
@@ -675,8 +675,9 @@ emulate_load_updates (update_t type, load_store_t ld, struct pt_regs *regs, unsi
*/
if (ld.x6_op == 1 || ld.x6_op == 3) {
printk(KERN_ERR "%s: register update on speculative load, error\n", __FUNCTION__);
- die_if_kernel("unaligned reference on speculative load with register update\n",
- regs, 30);
+ if (die_if_kernel("unaligned reference on speculative load with register update\n",
+ regs, 30))
+ return;
}
@@ -1317,7 +1318,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
if (ia64_psr(regs)->be) {
/* we don't support big-endian accesses */
- die_if_kernel("big-endian unaligned accesses are not supported", regs, 0);
+ if (die_if_kernel("big-endian unaligned accesses are not supported", regs, 0))
+ return;
goto force_sigbus;
}
@@ -1534,7 +1536,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
ia64_handle_exception(regs, eh);
goto done;
}
- die_if_kernel("error during unaligned kernel access\n", regs, ret);
+ if (die_if_kernel("error during unaligned kernel access\n", regs, ret))
+ return;
/* NOT_REACHED */
}
force_sigbus:
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 7e9c275ea14..344f64eca7a 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -218,7 +218,7 @@ find_memory (void)
/* Free all available memory, then mark bootmem-map as being in use. */
efi_memmap_walk(filter_rsvd_memory, free_bootmem);
- reserve_bootmem(bootmap_start, bootmap_size);
+ reserve_bootmem(bootmap_start, bootmap_size, BOOTMEM_DEFAULT);
find_initrd();
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 0b567398f38..ee5e68b2af9 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -299,12 +299,12 @@ static void __init reserve_pernode_space(void)
pages = bdp->node_low_pfn - (bdp->node_boot_start>>PAGE_SHIFT);
size = bootmem_bootmap_pages(pages) << PAGE_SHIFT;
base = __pa(bdp->node_bootmem_map);
- reserve_bootmem_node(pdp, base, size);
+ reserve_bootmem_node(pdp, base, size, BOOTMEM_DEFAULT);
/* Now the per-node space */
size = mem_data[node].pernode_size;
base = __pa(mem_data[node].pernode_addr);
- reserve_bootmem_node(pdp, base, size);
+ reserve_bootmem_node(pdp, base, size, BOOTMEM_DEFAULT);
}
}
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 7571076a16a..3e69881648a 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -16,7 +16,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-extern void die (char *, struct pt_regs *, long);
+extern int die(char *, struct pt_regs *, long);
#ifdef CONFIG_KPROBES
static inline int notify_page_fault(struct pt_regs *regs, int trap)
@@ -267,9 +267,11 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
else
printk(KERN_ALERT "Unable to handle kernel paging request at "
"virtual address %016lx\n", address);
- die("Oops", regs, isr);
+ if (die("Oops", regs, isr))
+ regs = NULL;
bust_spinlocks(0);
- do_exit(SIGKILL);
+ if (regs)
+ do_exit(SIGKILL);
return;
out_of_memory:
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 488e48a5dee..8fd7e825192 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -43,8 +43,7 @@
#define PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg) \
(((u64) seg << 28) | (bus << 20) | (devfn << 12) | (reg))
-static int
-pci_sal_read (unsigned int seg, unsigned int bus, unsigned int devfn,
+int raw_pci_read(unsigned int seg, unsigned int bus, unsigned int devfn,
int reg, int len, u32 *value)
{
u64 addr, data = 0;
@@ -68,8 +67,7 @@ pci_sal_read (unsigned int seg, unsigned int bus, unsigned int devfn,
return 0;
}
-static int
-pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn,
+int raw_pci_write(unsigned int seg, unsigned int bus, unsigned int devfn,
int reg, int len, u32 value)
{
u64 addr;
@@ -91,24 +89,17 @@ pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn,
return 0;
}
-static struct pci_raw_ops pci_sal_ops = {
- .read = pci_sal_read,
- .write = pci_sal_write
-};
-
-struct pci_raw_ops *raw_pci_ops = &pci_sal_ops;
-
-static int
-pci_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 *value)
{
- return raw_pci_ops->read(pci_domain_nr(bus), bus->number,
+ return raw_pci_read(pci_domain_nr(bus), bus->number,
devfn, where, size, value);
}
-static int
-pci_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 value)
{
- return raw_pci_ops->write(pci_domain_nr(bus), bus->number,
+ return raw_pci_write(pci_domain_nr(bus), bus->number,
devfn, where, size, value);
}
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index f3c69329e14..dfc6bf1c7b4 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -523,7 +523,7 @@ static ssize_t sn2_ptc_proc_write(struct file *file, const char __user *user, si
return count;
}
-static struct seq_operations sn2_ptc_seq_ops = {
+static const struct seq_operations sn2_ptc_seq_ops = {
.start = sn2_ptc_seq_start,
.next = sn2_ptc_seq_next,
.stop = sn2_ptc_seq_stop,
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 1a8e49607f1..4b0d1538e7e 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -33,6 +33,7 @@
#include <linux/smp_lock.h>
#include <linux/nodemask.h>
#include <linux/smp.h>
+#include <linux/mutex.h>
#include <asm/processor.h>
#include <asm/topology.h>
@@ -50,7 +51,7 @@ static void *sn_hwperf_salheap = NULL;
static int sn_hwperf_obj_cnt = 0;
static nasid_t sn_hwperf_master_nasid = INVALID_NASID;
static int sn_hwperf_init(void);
-static DECLARE_MUTEX(sn_hwperf_init_mutex);
+static DEFINE_MUTEX(sn_hwperf_init_mutex);
#define cnode_possible(n) ((n) < num_cnodes)
@@ -577,7 +578,7 @@ static void sn_topology_stop(struct seq_file *m, void *v)
/*
* /proc/sgi_sn/sn_topology, read-only using seq_file
*/
-static struct seq_operations sn_topology_seq_ops = {
+static const struct seq_operations sn_topology_seq_ops = {
.start = sn_topology_start,
.next = sn_topology_next,
.stop = sn_topology_stop,
@@ -884,10 +885,10 @@ static int sn_hwperf_init(void)
int e = 0;
/* single threaded, once-only initialization */
- down(&sn_hwperf_init_mutex);
+ mutex_lock(&sn_hwperf_init_mutex);
if (sn_hwperf_salheap) {
- up(&sn_hwperf_init_mutex);
+ mutex_unlock(&sn_hwperf_init_mutex);
return e;
}
@@ -936,7 +937,7 @@ out:
sn_hwperf_salheap = NULL;
sn_hwperf_obj_cnt = 0;
}
- up(&sn_hwperf_init_mutex);
+ mutex_unlock(&sn_hwperf_init_mutex);
return e;
}
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index ab3eaf85fe4..2c676cc0541 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -100,11 +100,11 @@ u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus)
static irqreturn_t
pcibr_error_intr_handler(int irq, void *arg)
{
- struct pcibus_info *soft = (struct pcibus_info *)arg;
+ struct pcibus_info *soft = arg;
- if (sal_pcibr_error_interrupt(soft) < 0) {
+ if (sal_pcibr_error_interrupt(soft) < 0)
panic("pcibr_error_intr_handler(): Fatal Bridge Error");
- }
+
return IRQ_HANDLED;
}
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index e1a3e19d3d9..999f14f986e 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -752,13 +752,13 @@ tioce_kern_init(struct tioce_common *tioce_common)
* Determine the secondary bus number of the port2 logical PPB.
* This is used to decide whether a given pci device resides on
* port1 or port2. Note: We don't have enough plumbing set up
- * here to use pci_read_config_xxx() so use the raw_pci_ops vector.
+ * here to use pci_read_config_xxx() so use raw_pci_read().
*/
seg = tioce_common->ce_pcibus.bs_persist_segment;
bus = tioce_common->ce_pcibus.bs_persist_busnum;
- raw_pci_ops->read(seg, bus, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1,&tmp);
+ raw_pci_read(seg, bus, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1,&tmp);
tioce_kern->ce_port1_secondary = (u8) tmp;
/*
@@ -799,11 +799,11 @@ tioce_kern_init(struct tioce_common *tioce_common)
/* mem base/limit */
- raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+ raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
PCI_MEMORY_BASE, 2, &tmp);
base = (u64)tmp << 16;
- raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+ raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
PCI_MEMORY_LIMIT, 2, &tmp);
limit = (u64)tmp << 16;
limit |= 0xfffffUL;
@@ -817,21 +817,21 @@ tioce_kern_init(struct tioce_common *tioce_common)
* attributes.
*/
- raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+ raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
PCI_PREF_MEMORY_BASE, 2, &tmp);
base = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16;
- raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+ raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
PCI_PREF_BASE_UPPER32, 4, &tmp);
base |= (u64)tmp << 32;
- raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+ raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
PCI_PREF_MEMORY_LIMIT, 2, &tmp);
limit = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16;
limit |= 0xfffffUL;
- raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+ raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
PCI_PREF_LIMIT_UPPER32, 4, &tmp);
limit |= (u64)tmp << 32;
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 795180b8fd8..de153de2ea9 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -8,6 +8,7 @@ mainmenu "Linux/M32R Kernel Configuration"
config M32R
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
config SBUS
@@ -35,6 +36,13 @@ config NO_IOPORT
config NO_DMA
def_bool y
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
+config HZ
+ int
+ default 100
+
source "init/Kconfig"
diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c
index ee3c8be12fa..01d877c6868 100644
--- a/arch/m32r/boot/compressed/m32r_sio.c
+++ b/arch/m32r/boot/compressed/m32r_sio.c
@@ -17,7 +17,7 @@ static int puts(const char *s)
return 0;
}
-#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT)
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT)
#include <asm/m32r.h>
#include <asm/io.h>
@@ -52,7 +52,7 @@ static void putc(char c)
}
*BOOT_SIO0TXB = c;
}
-#else /* !(CONFIG_PLAT_M32700UT_Alpha) && !(CONFIG_PLAT_M32700UT) */
+#else /* !(CONFIG_PLAT_M32700UT) */
#if defined(CONFIG_PLAT_MAPPI2)
#define SIO0STS (volatile unsigned short *)(0xa0efd000 + 14)
#define SIO0TXB (volatile unsigned short *)(0xa0efd000 + 30)
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index d64814385d7..0392112a5d7 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -177,25 +177,28 @@ static unsigned long __init setup_memory(void)
*/
reserve_bootmem(CONFIG_MEMORY_START + PAGE_SIZE,
(PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE - 1)
- - CONFIG_MEMORY_START);
+ - CONFIG_MEMORY_START,
+ BOOTMEM_DEFAULT);
/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
* enabling clean reboots, SMP operation, laptop functions.
*/
- reserve_bootmem(CONFIG_MEMORY_START, PAGE_SIZE);
+ reserve_bootmem(CONFIG_MEMORY_START, PAGE_SIZE, BOOTMEM_DEFAULT);
/*
* reserve memory hole
*/
#ifdef CONFIG_MEMHOLE
- reserve_bootmem(CONFIG_MEMHOLE_START, CONFIG_MEMHOLE_SIZE);
+ reserve_bootmem(CONFIG_MEMHOLE_START, CONFIG_MEMHOLE_SIZE,
+ BOOTMEM_DEFAULT);
#endif
#ifdef CONFIG_BLK_DEV_INITRD
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
- reserve_bootmem(INITRD_START, INITRD_SIZE);
+ reserve_bootmem(INITRD_START, INITRD_SIZE,
+ BOOTMEM_DEFAULT);
initrd_start = INITRD_START + PAGE_OFFSET;
initrd_end = initrd_start + INITRD_SIZE;
printk("initrd:start[%08lx],size[%08lx]\n",
@@ -366,7 +369,7 @@ static void c_stop(struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index 0e383da158e..2c03ac1d005 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -43,6 +43,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/sched.h>
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/bootmem.h>
diff --git a/arch/m32r/kernel/syscall_table.S b/arch/m32r/kernel/syscall_table.S
index 95aa7987484..aa3bf4cfab3 100644
--- a/arch/m32r/kernel/syscall_table.S
+++ b/arch/m32r/kernel/syscall_table.S
@@ -321,6 +321,6 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate
diff --git a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c
index c7efdb0aefc..07c1af7dc0e 100644
--- a/arch/m32r/mm/discontig.c
+++ b/arch/m32r/mm/discontig.c
@@ -91,7 +91,8 @@ unsigned long __init setup_memory(void)
PFN_PHYS(mp->pages));
reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(mp->start_pfn),
- PFN_PHYS(mp->free_pfn - mp->start_pfn) + bootmap_size);
+ PFN_PHYS(mp->free_pfn - mp->start_pfn) + bootmap_size,
+ BOOTMEM_DEFAULT);
if (max_low_pfn < max_pfn)
max_low_pfn = max_pfn;
@@ -104,7 +105,7 @@ unsigned long __init setup_memory(void)
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= PFN_PHYS(max_low_pfn)) {
reserve_bootmem_node(NODE_DATA(0), INITRD_START,
- INITRD_SIZE);
+ INITRD_SIZE, BOOTMEM_DEFAULT);
initrd_start = INITRD_START + PAGE_OFFSET;
initrd_end = initrd_start + INITRD_SIZE;
printk("initrd:start[%08lx],size[%08lx]\n",
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 8236e42ef71..65db2261b9e 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -5,6 +5,7 @@
config M68K
bool
default y
+ select HAVE_IDE
config MMU
bool
@@ -52,6 +53,13 @@ config NO_IOPORT
config NO_DMA
def_bool SUN3
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
+config HZ
+ int
+ default 100
+
mainmenu "Linux/68k Kernel Configuration"
source "init/Kconfig"
@@ -577,20 +585,6 @@ config MAC_HID
depends on INPUT_ADBHID
default y
-config MAC_ADBKEYCODES
- bool "Support for ADB raw keycodes"
- depends on INPUT_ADBHID
- help
- This provides support for sending raw ADB keycodes to console
- devices. This is the default up to 2.4.0, but in future this may be
- phased out in favor of generic Linux keycodes. If you say Y here,
- you can dynamically switch via the
- /proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes
- sysctl and with the "keyboard_sends_linux_keycodes=" kernel
- argument.
-
- If unsure, say Y here.
-
config ADB_KEYBOARD
bool "Support for ADB keyboard (old driver)"
depends on MAC && !INPUT_ADBHID
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index 4a1bd44ff16..2cba605cb59 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -13,16 +13,15 @@
# Copyright (C) 1994 by Hamish Macdonald
#
-# test for cross compiling
-COMPILE_ARCH = $(shell uname -m)
-
# override top level makefile
AS += -m68020
LDFLAGS := -m m68kelf
LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
-ifneq ($(COMPILE_ARCH),$(ARCH))
- # prefix for cross-compiling binaries
- CROSS_COMPILE = m68k-linux-gnu-
+ifneq ($(SUBARCH),$(ARCH))
+ ifeq ($(CROSS_COMPILE),)
+ CROSS_COMPILE := $(call cc-cross-prefix, \
+ m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
+ endif
endif
ifdef CONFIG_SUN3
diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile
index 8b415651ede..6a0d7650f98 100644
--- a/arch/m68k/amiga/Makefile
+++ b/arch/m68k/amiga/Makefile
@@ -2,6 +2,6 @@
# Makefile for Linux arch/m68k/amiga source directory
#
-obj-y := config.o amiints.o cia.o chipram.o amisound.o amiga_ksyms.o
+obj-y := config.o amiints.o cia.o chipram.o amisound.o
obj-$(CONFIG_AMIGA_PCMCIA) += pcmcia.o
diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c
deleted file mode 100644
index 7fdcf6bf3ad..00000000000
--- a/arch/m68k/amiga/amiga_ksyms.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/ptrace.h>
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#include <asm/amipcmcia.h>
-
-extern volatile u_short amiga_audio_min_period;
-extern u_short amiga_audio_period;
-
-/*
- * Add things here when you find the need for it.
- */
-EXPORT_SYMBOL(amiga_model);
-EXPORT_SYMBOL(amiga_chipset);
-EXPORT_SYMBOL(amiga_hw_present);
-EXPORT_SYMBOL(amiga_eclock);
-EXPORT_SYMBOL(amiga_colorclock);
-EXPORT_SYMBOL(amiga_chip_alloc);
-EXPORT_SYMBOL(amiga_chip_free);
-EXPORT_SYMBOL(amiga_chip_avail);
-EXPORT_SYMBOL(amiga_chip_size);
-EXPORT_SYMBOL(amiga_audio_period);
-EXPORT_SYMBOL(amiga_audio_min_period);
-
-#ifdef CONFIG_AMIGA_PCMCIA
- EXPORT_SYMBOL(pcmcia_reset);
- EXPORT_SYMBOL(pcmcia_copy_tuple);
- EXPORT_SYMBOL(pcmcia_program_voltage);
- EXPORT_SYMBOL(pcmcia_access_speed);
- EXPORT_SYMBOL(pcmcia_write_enable);
- EXPORT_SYMBOL(pcmcia_write_disable);
-#endif
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index 1f5bfb58429..61e5c54625a 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -12,6 +12,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/amigahw.h>
@@ -21,7 +22,7 @@ static const signed char sine_data[] = {
0, 39, 75, 103, 121, 127, 121, 103, 75, 39,
0, -39, -75, -103, -121, -127, -121, -103, -75, -39
};
-#define DATA_SIZE (sizeof(sine_data)/sizeof(sine_data[0]))
+#define DATA_SIZE ARRAY_SIZE(sine_data)
#define custom amiga_custom
@@ -31,6 +32,7 @@ static const signed char sine_data[] = {
*/
volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
+EXPORT_SYMBOL(amiga_audio_min_period);
#define MAX_PERIOD (65535)
@@ -40,6 +42,7 @@ volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
*/
unsigned short amiga_audio_period = MAX_PERIOD;
+EXPORT_SYMBOL(amiga_audio_period);
static unsigned long clock_constant;
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index fa015d80161..cbe36538af4 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -13,10 +13,13 @@
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/module.h>
+
#include <asm/page.h>
#include <asm/amigahw.h>
unsigned long amiga_chip_size;
+EXPORT_SYMBOL(amiga_chip_size);
static struct resource chipram_res = {
.name = "Chip RAM", .start = CHIP_PHYSADDR
@@ -29,12 +32,10 @@ void __init amiga_chip_init(void)
if (!AMIGAHW_PRESENT(CHIP_RAM))
return;
-#ifndef CONFIG_APUS_FAST_EXCEPT
/*
* Remove the first 4 pages where PPC exception handlers will be located
*/
amiga_chip_size -= 0x4000;
-#endif
chipram_res.end = amiga_chip_size-1;
request_resource(&iomem_resource, &chipram_res);
@@ -67,6 +68,7 @@ void *amiga_chip_alloc(unsigned long size, const char *name)
#endif
return (void *)ZTWO_VADDR(res->start);
}
+EXPORT_SYMBOL(amiga_chip_alloc);
/*
@@ -120,6 +122,7 @@ void amiga_chip_free(void *ptr)
}
printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr);
}
+EXPORT_SYMBOL(amiga_chip_free);
unsigned long amiga_chip_avail(void)
@@ -129,3 +132,5 @@ unsigned long amiga_chip_avail(void)
#endif
return chipavail;
}
+EXPORT_SYMBOL(amiga_chip_avail);
+
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index c4a4ffd45bc..343fab49bd9 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -84,7 +84,7 @@ unsigned char cia_able_irq(struct ciabase *base, unsigned char mask)
static irqreturn_t cia_handler(int irq, void *dev_id)
{
- struct ciabase *base = (struct ciabase *)dev_id;
+ struct ciabase *base = dev_id;
int mach_irq;
unsigned char ints;
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 35748531327..50f5daab46b 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/zorro.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/setup.h>
@@ -36,13 +37,24 @@
#include <asm/io.h>
unsigned long amiga_model;
+EXPORT_SYMBOL(amiga_model);
+
unsigned long amiga_eclock;
+EXPORT_SYMBOL(amiga_eclock);
+
unsigned long amiga_masterclock;
+
unsigned long amiga_colorclock;
+EXPORT_SYMBOL(amiga_colorclock);
+
unsigned long amiga_chipset;
+EXPORT_SYMBOL(amiga_chipset);
+
unsigned char amiga_vblank;
unsigned char amiga_psfreq;
+
struct amiga_hw_present amiga_hw_present;
+EXPORT_SYMBOL(amiga_hw_present);
static char s_a500[] __initdata = "A500";
static char s_a500p[] __initdata = "A500+";
diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c
index 186662ca1a8..7106f0c3639 100644
--- a/arch/m68k/amiga/pcmcia.c
+++ b/arch/m68k/amiga/pcmcia.c
@@ -15,6 +15,8 @@
#include <linux/types.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
+#include <linux/module.h>
+
#include <asm/amigayle.h>
#include <asm/amipcmcia.h>
@@ -30,6 +32,7 @@ void pcmcia_reset(void)
while (time_before(jiffies, reset_start_time + 1*HZ/100));
b = gayle_reset;
}
+EXPORT_SYMBOL(pcmcia_reset);
/* copy a tuple, including tuple header. return nb bytes copied */
@@ -61,6 +64,7 @@ int pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len)
return 0;
}
+EXPORT_SYMBOL(pcmcia_copy_tuple);
void pcmcia_program_voltage(int voltage)
{
@@ -84,6 +88,7 @@ void pcmcia_program_voltage(int voltage)
gayle.config = cfg_byte;
}
+EXPORT_SYMBOL(pcmcia_program_voltage);
void pcmcia_access_speed(int speed)
{
@@ -101,13 +106,17 @@ void pcmcia_access_speed(int speed)
cfg_byte = (cfg_byte & 0xf3) | s;
gayle.config = cfg_byte;
}
+EXPORT_SYMBOL(pcmcia_access_speed);
void pcmcia_write_enable(void)
{
gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA;
}
+EXPORT_SYMBOL(pcmcia_write_enable);
void pcmcia_write_disable(void)
{
gayle.cardstatus = 0;
}
+EXPORT_SYMBOL(pcmcia_write_disable);
+
diff --git a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile
index 2cb86191f0a..2cd905efe63 100644
--- a/arch/m68k/atari/Makefile
+++ b/arch/m68k/atari/Makefile
@@ -3,7 +3,7 @@
#
obj-y := config.o time.o debug.o ataints.o stdma.o \
- atasound.o stram.o atari_ksyms.o
+ atasound.o stram.o
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_HADES) += hades-pci.o
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index b85ca22024c..b45593a60bd 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -40,6 +40,7 @@
#include <linux/kernel_stat.h>
#include <linux/init.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/traps.h>
@@ -446,6 +447,7 @@ unsigned long atari_register_vme_int(void)
free_vme_vec_bitmap |= 1 << i;
return VME_SOURCE_BASE + i;
}
+EXPORT_SYMBOL(atari_register_vme_int);
void atari_unregister_vme_int(unsigned long irq)
@@ -455,5 +457,6 @@ void atari_unregister_vme_int(unsigned long irq)
free_vme_vec_bitmap &= ~(1 << irq);
}
}
+EXPORT_SYMBOL(atari_unregister_vme_int);
diff --git a/arch/m68k/atari/atari_ksyms.c b/arch/m68k/atari/atari_ksyms.c
deleted file mode 100644
index a0475715153..00000000000
--- a/arch/m68k/atari/atari_ksyms.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <linux/module.h>
-
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atarikb.h>
-#include <asm/atari_joystick.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-
-extern void atari_microwire_cmd( int cmd );
-extern int atari_MFP_init_done;
-extern int atari_SCC_init_done;
-extern int atari_SCC_reset_done;
-
-EXPORT_SYMBOL(atari_mch_cookie);
-EXPORT_SYMBOL(atari_mch_type);
-EXPORT_SYMBOL(atari_hw_present);
-EXPORT_SYMBOL(atari_switches);
-EXPORT_SYMBOL(atari_dont_touch_floppy_select);
-EXPORT_SYMBOL(atari_register_vme_int);
-EXPORT_SYMBOL(atari_unregister_vme_int);
-EXPORT_SYMBOL(stdma_lock);
-EXPORT_SYMBOL(stdma_release);
-EXPORT_SYMBOL(stdma_others_waiting);
-EXPORT_SYMBOL(stdma_islocked);
-EXPORT_SYMBOL(atari_stram_alloc);
-EXPORT_SYMBOL(atari_stram_free);
-
-EXPORT_SYMBOL(atari_MFP_init_done);
-EXPORT_SYMBOL(atari_SCC_init_done);
-EXPORT_SYMBOL(atari_SCC_reset_done);
-
-EXPORT_SYMBOL(atari_microwire_cmd);
diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c
index ee04250eb56..d266fe89c12 100644
--- a/arch/m68k/atari/atasound.c
+++ b/arch/m68k/atari/atasound.c
@@ -22,6 +22,7 @@
#include <linux/fcntl.h>
#include <linux/errno.h>
#include <linux/mm.h>
+#include <linux/module.h>
#include <asm/atarihw.h>
#include <asm/system.h>
@@ -43,6 +44,7 @@ void atari_microwire_cmd (int cmd)
while( tt_microwire.mask != 0x7ff)
;
}
+EXPORT_SYMBOL(atari_microwire_cmd);
/* PSG base frequency */
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index e40e5dcaa34..5945e150555 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -31,6 +31,7 @@
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/vt_kern.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/setup.h>
@@ -43,10 +44,20 @@
#include <asm/io.h>
u_long atari_mch_cookie;
+EXPORT_SYMBOL(atari_mch_cookie);
+
u_long atari_mch_type;
+EXPORT_SYMBOL(atari_mch_type);
+
struct atari_hw_present atari_hw_present;
+EXPORT_SYMBOL(atari_hw_present);
+
u_long atari_switches;
+EXPORT_SYMBOL(atari_switches);
+
int atari_dont_touch_floppy_select;
+EXPORT_SYMBOL(atari_dont_touch_floppy_select);
+
int atari_rtc_year_offset;
/* local function prototypes */
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
index fbeed8c8ecb..043ddbc61c7 100644
--- a/arch/m68k/atari/debug.c
+++ b/arch/m68k/atari/debug.c
@@ -15,17 +15,23 @@
#include <linux/console.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <asm/atarihw.h>
#include <asm/atariints.h>
/* Flag that Modem1 port is already initialized and used */
int atari_MFP_init_done;
+EXPORT_SYMBOL(atari_MFP_init_done);
+
/* Flag that Modem1 port is already initialized and used */
int atari_SCC_init_done;
+EXPORT_SYMBOL(atari_SCC_init_done);
+
/* Can be set somewhere, if a SCC master reset has already be done and should
* not be repeated; used by kgdb */
int atari_SCC_reset_done;
+EXPORT_SYMBOL(atari_SCC_reset_done);
static struct console atari_console_driver = {
.name = "debug",
diff --git a/arch/m68k/atari/hades-pci.c b/arch/m68k/atari/hades-pci.c
index bee2b1443e3..2bbabc00870 100644
--- a/arch/m68k/atari/hades-pci.c
+++ b/arch/m68k/atari/hades-pci.c
@@ -376,8 +376,8 @@ struct pci_bus_info * __init init_hades_pci(void)
*/
bus = kzalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
- if (!bus)
- return NULL;
+ if (unlikely(!bus))
+ goto iounmap_base_virt;
/*
* Claim resources. The m68k has no separate I/O space, both
@@ -385,43 +385,25 @@ struct pci_bus_info * __init init_hades_pci(void)
* the I/O resources are requested in memory space as well.
*/
- if (request_resource(&iomem_resource, &config_space) != 0)
- {
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&iomem_resource, &config_space) != 0))
+ goto free_bus;
- if (request_resource(&iomem_resource, &io_space) != 0)
- {
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&iomem_resource, &io_space) != 0))
+ goto release_config_space;
bus->mem_space.start = HADES_MEM_BASE;
bus->mem_space.end = HADES_MEM_BASE + HADES_MEM_SIZE - 1;
bus->mem_space.name = pci_mem_name;
#if 1
- if (request_resource(&iomem_resource, &bus->mem_space) != 0)
- {
- release_resource(&io_space);
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&iomem_resource, &bus->mem_space) != 0))
+ goto release_io_space;
#endif
bus->io_space.start = pci_io_base_virt;
bus->io_space.end = pci_io_base_virt + HADES_VIRT_IO_SIZE - 1;
bus->io_space.name = pci_io_name;
#if 1
- if (request_resource(&ioport_resource, &bus->io_space) != 0)
- {
- release_resource(&bus->mem_space);
- release_resource(&io_space);
- release_resource(&config_space);
- kfree(bus);
- return NULL;
- }
+ if (unlikely(request_resource(&ioport_resource, &bus->io_space) != 0))
+ goto release_bus_mem_space;
#endif
/*
* Set hardware dependent functions.
@@ -438,5 +420,21 @@ struct pci_bus_info * __init init_hades_pci(void)
tt_mfp.active_edge &= ~0x27;
return bus;
+
+release_bus_mem_space:
+ release_resource(&bus->mem_space);
+release_io_space:
+ release_resource(&io_space);
+release_config_space:
+ release_resource(&config_space);
+free_bus:
+ kfree(bus);
+iounmap_base_virt:
+ iounmap((void *)pci_io_base_virt);
+
+ for (i = 0; i < N_SLOTS; i++)
+ iounmap((void *)pci_conf_base_virt[i]);
+
+ return NULL;
}
#endif
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index ab3fd5202b2..d1bd029a34a 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
+#include <linux/module.h>
#include <asm/atari_stdma.h>
#include <asm/atariints.h>
@@ -91,6 +92,7 @@ void stdma_lock(irq_handler_t handler, void *data)
stdma_isr_data = data;
local_irq_restore(flags);
}
+EXPORT_SYMBOL(stdma_lock);
/*
@@ -117,6 +119,7 @@ void stdma_release(void)
local_irq_restore(flags);
}
+EXPORT_SYMBOL(stdma_release);
/*
@@ -134,6 +137,7 @@ int stdma_others_waiting(void)
{
return waitqueue_active(&stdma_wait);
}
+EXPORT_SYMBOL(stdma_others_waiting);
/*
@@ -155,6 +159,7 @@ int stdma_islocked(void)
{
return stdma_locked;
}
+EXPORT_SYMBOL(stdma_islocked);
/*
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index bf4588cbe37..0055a6c06f7 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -20,6 +20,7 @@
#include <linux/bootmem.h>
#include <linux/mount.h>
#include <linux/blkdev.h>
+#include <linux/module.h>
#include <asm/setup.h>
#include <asm/machdep.h>
@@ -153,7 +154,7 @@ void __init atari_stram_reserve_pages(void *start_mem)
/* always reserve first page of ST-RAM, the first 2 kB are
* supervisor-only! */
if (!kernel_in_stram)
- reserve_bootmem (0, PAGE_SIZE);
+ reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
}
@@ -208,6 +209,7 @@ void *atari_stram_alloc(long size, const char *owner)
}
return( addr );
}
+EXPORT_SYMBOL(atari_stram_alloc);
void atari_stram_free( void *addr )
@@ -237,6 +239,7 @@ void atari_stram_free( void *addr )
printk( KERN_ERR "atari_stram_free: cannot free block at %p "
"(called from %p)\n", addr, __builtin_return_address(0) );
}
+EXPORT_SYMBOL(atari_stram_free);
/* ------------------------------------------------------------------------ */
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 15b80abfe94..ff9dffa5b86 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -678,7 +678,6 @@ CONFIG_LOGO_MAC_CLUT224=y
#
CONFIG_MAC_SCC=y
CONFIG_MAC_HID=y
-CONFIG_MAC_ADBKEYCODES=y
CONFIG_SERIAL_CONSOLE=y
#
diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile
index 288b9c67c9b..96d4244c82f 100644
--- a/arch/m68k/hp300/Makefile
+++ b/arch/m68k/hp300/Makefile
@@ -2,4 +2,4 @@
# Makefile for Linux arch/m68k/hp300 source directory
#
-obj-y := ksyms.o config.o time.o reboot.o
+obj-y := config.o time.o reboot.o
diff --git a/arch/m68k/hp300/ksyms.c b/arch/m68k/hp300/ksyms.c
deleted file mode 100644
index 8202830763d..00000000000
--- a/arch/m68k/hp300/ksyms.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * linux/arch/m68k/hp300/ksyms.c
- *
- * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
- *
- * This file contains the HP300-specific kernel symbols. None yet. :-)
- */
-
-#include <linux/module.h>
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 918f5dbeaef..6dfa3b3c0e2 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -742,7 +742,7 @@ sys_call_table:
.long sys_epoll_pwait /* 315 */
.long sys_utimensat
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate /* 320 */
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index 3ee91869521..5de4e4ed76a 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -23,7 +23,6 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/reboot.h>
#include <linux/init_task.h>
#include <linux/mqueue.h>
@@ -316,53 +315,6 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
EXPORT_SYMBOL(dump_fpu);
/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
- struct switch_stack *sw;
-
-/* changed the size calculations - should hopefully work better. lbt */
- dump->magic = CMAGIC;
- dump->start_code = 0;
- dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
- dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
- dump->u_dsize = ((unsigned long) (current->mm->brk +
- (PAGE_SIZE-1))) >> PAGE_SHIFT;
- dump->u_dsize -= dump->u_tsize;
- dump->u_ssize = 0;
-
- if (dump->start_stack < TASK_SIZE)
- dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
-
- dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
- sw = ((struct switch_stack *)regs) - 1;
- dump->regs.d1 = regs->d1;
- dump->regs.d2 = regs->d2;
- dump->regs.d3 = regs->d3;
- dump->regs.d4 = regs->d4;
- dump->regs.d5 = regs->d5;
- dump->regs.d6 = sw->d6;
- dump->regs.d7 = sw->d7;
- dump->regs.a0 = regs->a0;
- dump->regs.a1 = regs->a1;
- dump->regs.a2 = regs->a2;
- dump->regs.a3 = sw->a3;
- dump->regs.a4 = sw->a4;
- dump->regs.a5 = sw->a5;
- dump->regs.a6 = sw->a6;
- dump->regs.d0 = regs->d0;
- dump->regs.orig_d0 = regs->orig_d0;
- dump->regs.stkadj = regs->stkadj;
- dump->regs.sr = regs->sr;
- dump->regs.pc = regs->pc;
- dump->regs.fmtvec = (regs->format << 12) | regs->vector;
- /* dump floating point stuff */
- dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
-}
-EXPORT_SYMBOL(dump_thread);
-
-/*
* sys_execve() executes a new program.
*/
asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp)
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index ed3a4caec62..bba650312fd 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -323,7 +323,8 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_BLK_DEV_INITRD
if (m68k_ramdisk.size) {
reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
- m68k_ramdisk.addr, m68k_ramdisk.size);
+ m68k_ramdisk.addr, m68k_ramdisk.size,
+ BOOTMEM_DEFAULT);
initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
initrd_end = initrd_start + m68k_ramdisk.size;
printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
@@ -449,7 +450,7 @@ static void *c_next(struct seq_file *m, void *v, loff_t *pos)
static void c_stop(struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 97f556fa493..fd4858e2dd6 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -23,7 +23,6 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
-#include <linux/a.out.h>
#include <linux/user.h>
#include <linux/string.h>
#include <linux/linkage.h>
diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile
index 995a09d912f..1d265ba365a 100644
--- a/arch/m68k/mac/Makefile
+++ b/arch/m68k/mac/Makefile
@@ -3,4 +3,4 @@
#
obj-y := config.o bootparse.o macints.o iop.o via.o oss.o psc.o \
- baboon.o macboing.o debug.o misc.o mac_ksyms.o
+ baboon.o macboing.o debug.o misc.o
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 01b468b9392..735a49b4b93 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -58,8 +58,6 @@ extern struct mem_info m68k_memory[NUM_MEMINFO];
extern struct mem_info m68k_ramdisk;
-extern char m68k_command_line[CL_SIZE];
-
void *mac_env; /* Loaded by the boot asm */
/* The phys. video addr. - might be bogus on some machines */
diff --git a/arch/m68k/mac/mac_ksyms.c b/arch/m68k/mac/mac_ksyms.c
deleted file mode 100644
index 6e37ceb0f3b..00000000000
--- a/arch/m68k/mac/mac_ksyms.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <linux/module.h>
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-
-/* Says whether we're using A/UX interrupts or not */
-extern int via_alt_mapping;
-
-EXPORT_SYMBOL(via_alt_mapping);
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 8df270e950f..fa485df4160 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/ide.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/macintosh.h>
@@ -41,7 +42,9 @@ volatile __u8 *via1, *via2;
/* See note in mac_via.h about how this is possibly not useful */
volatile long *via_memory_bogon=(long *)&via_memory_bogon;
#endif
-int rbv_present, via_alt_mapping;
+int rbv_present;
+int via_alt_mapping;
+EXPORT_SYMBOL(via_alt_mapping);
__u8 rbv_clear;
/*
diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile
index 950e82f2164..edb3f6e6ee6 100644
--- a/arch/m68k/mvme16x/Makefile
+++ b/arch/m68k/mvme16x/Makefile
@@ -2,4 +2,4 @@
# Makefile for Linux arch/m68k/mvme16x source directory
#
-obj-y := config.o rtc.o mvme16x_ksyms.o
+obj-y := config.o rtc.o
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index daa78516140..24cbc303045 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -25,6 +25,7 @@
#include <linux/genhd.h>
#include <linux/rtc.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
@@ -58,6 +59,7 @@ static irq_handler_t tick_handler;
unsigned short mvme16x_config;
+EXPORT_SYMBOL(mvme16x_config);
int mvme16x_parse_bootinfo(const struct bi_record *bi)
diff --git a/arch/m68k/mvme16x/mvme16x_ksyms.c b/arch/m68k/mvme16x/mvme16x_ksyms.c
deleted file mode 100644
index 4a8a3634bb4..00000000000
--- a/arch/m68k/mvme16x/mvme16x_ksyms.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/ptrace.h>
-#include <asm/mvme16xhw.h>
-
-EXPORT_SYMBOL(mvme16x_config);
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 6abbbb8aac5..07eb4c4bab8 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -8,6 +8,7 @@ mainmenu "uClinux/68k (w/o MMU) Kernel Configuration"
config M68K
bool
default y
+ select HAVE_IDE
config MMU
bool
@@ -64,6 +65,9 @@ config TIME_LOW_RES
config NO_IOPORT
def_bool y
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
source "init/Kconfig"
menu "Processor type and features"
@@ -522,6 +526,11 @@ config 4KSTACKS
running more threads on a system and also reduces the pressure
on the VM subsystem for higher order allocations.
+config HZ
+ int
+ default 1000 if CLEOPATRA
+ default 100
+
comment "RAM configuration"
config RAMBASE
diff --git a/arch/m68knommu/Kconfig.debug b/arch/m68knommu/Kconfig.debug
index 9ff47bd09ae..ed6d9a83bfd 100644
--- a/arch/m68knommu/Kconfig.debug
+++ b/arch/m68knommu/Kconfig.debug
@@ -21,13 +21,6 @@ config BOOTPARAM_STRING
default 'console=ttyS0,19200'
depends on BOOTPARAM
-config DUMPTOFLASH
- bool "Panic/Dump to FLASH"
- depends on COLDFIRE
- help
- Dump any panic of trap output into a flash memory segment
- for later analysis.
-
config NO_KERNEL_MSG
bool "Suppress Kernel BUG Messages"
help
diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig
index 5a0ecaaee3b..648113075f9 100644
--- a/arch/m68knommu/defconfig
+++ b/arch/m68knommu/defconfig
@@ -597,7 +597,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_FULLDEBUG is not set
# CONFIG_HIGHPROFILE is not set
# CONFIG_BOOTPARAM is not set
-# CONFIG_DUMPTOFLASH is not set
# CONFIG_NO_KERNEL_MSG is not set
# CONFIG_BDM_DISABLE is not set
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index f795062aba1..53fad149028 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -24,14 +24,6 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(ip_fast_csum);
@@ -46,9 +38,6 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
it's OK to leave it out of version control. */
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
-EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(__down_failed);
EXPORT_SYMBOL(__down_failed_interruptible);
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 332345d7675..d6f0200316f 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -64,9 +64,6 @@ void (*mach_power_off)(void);
#ifdef CONFIG_M68VZ328
#define CPU "MC68VZ328"
#endif
-#ifdef CONFIG_M68332
- #define CPU "MC68332"
-#endif
#ifdef CONFIG_M68360
#define CPU "MC68360"
#endif
@@ -206,7 +203,7 @@ void __init setup_arch(char **cmdline_p)
* the bootmem bitmap so we then reserve it after freeing it :-)
*/
free_bootmem(memory_start, memory_end - memory_start);
- reserve_bootmem(memory_start, bootmap_size);
+ reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
/*
* Get kmalloc into gear.
@@ -263,7 +260,7 @@ static void c_stop(struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
index 9620093514b..1b02b882006 100644
--- a/arch/m68knommu/kernel/syscalltable.S
+++ b/arch/m68knommu/kernel/syscalltable.S
@@ -336,7 +336,7 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait /* 315 */
.long sys_utimensat
.long sys_signalfd
- .long sys_timerfd
+ .long sys_ni_syscall
.long sys_eventfd
.long sys_fallocate /* 320 */
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index 89cdbcaeb45..0ccfb2ad638 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -42,14 +42,12 @@ irqreturn_t arch_timer_interrupt(int irq, void *dummy)
/* last time the cmos clock got updated */
static long last_rtc_update=0;
+ if (current->pid)
+ profile_tick(CPU_PROFILING);
+
write_seqlock(&xtime_lock);
do_timer(1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
- if (current->pid)
- profile_tick(CPU_PROFILING);
/*
* If we have an externally synchronized Linux clock, then update
@@ -67,6 +65,10 @@ irqreturn_t arch_timer_interrupt(int irq, void *dummy)
}
write_sequnlock(&xtime_lock);
+
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(get_irq_regs()));
+#endif
return(IRQ_HANDLED);
}
diff --git a/arch/m68knommu/lib/memcpy.c b/arch/m68knommu/lib/memcpy.c
index 0d5577569e4..b50dbcad474 100644
--- a/arch/m68knommu/lib/memcpy.c
+++ b/arch/m68knommu/lib/memcpy.c
@@ -1,6 +1,5 @@
#include <linux/types.h>
-#include <linux/autoconf.h>
void * memcpy(void * to, const void * from, size_t n)
{
diff --git a/arch/m68knommu/platform/5206/Makefile b/arch/m68knommu/platform/5206/Makefile
index c7bb0cef31a..a439d9ab3f2 100644
--- a/arch/m68knommu/platform/5206/Makefile
+++ b/arch/m68knommu/platform/5206/Makefile
@@ -12,9 +12,7 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-y := config.o
diff --git a/arch/m68knommu/platform/5206e/Makefile b/arch/m68knommu/platform/5206e/Makefile
index c7bb0cef31a..a439d9ab3f2 100644
--- a/arch/m68knommu/platform/5206e/Makefile
+++ b/arch/m68knommu/platform/5206e/Makefile
@@ -12,9 +12,7 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-y := config.o
diff --git a/arch/m68knommu/platform/520x/Makefile b/arch/m68knommu/platform/520x/Makefile
index 31b4eb51739..a50e76acc8f 100644
--- a/arch/m68knommu/platform/520x/Makefile
+++ b/arch/m68knommu/platform/520x/Makefile
@@ -12,8 +12,6 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-y := config.o
diff --git a/arch/m68knommu/platform/523x/Makefile b/arch/m68knommu/platform/523x/Makefile
index ac9fbece8a4..5694d593f02 100644
--- a/arch/m68knommu/platform/523x/Makefile
+++ b/arch/m68knommu/platform/523x/Makefile
@@ -12,8 +12,6 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-y := config.o
diff --git a/arch/m68knommu/platform/5249/Makefile b/arch/m68knommu/platform/5249/Makefile
index c7bb0cef31a..a439d9ab3f2 100644
--- a/arch/m68knommu/platform/5249/Makefile
+++ b/arch/m68knommu/platform/5249/Makefile
@@ -12,9 +12,7 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-y := config.o
diff --git a/arch/m68knommu/platform/5272/Makefile b/arch/m68knommu/platform/5272/Makefile
index 7475c38c3b4..26135d92b34 100644
--- a/arch/m68knommu/platform/5272/Makefile
+++ b/arch/m68knommu/platform/5272/Makefile
@@ -12,9 +12,7 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-y := config.o
diff --git a/arch/m68knommu/platform/527x/Makefile b/arch/m68knommu/platform/527x/Makefile
index 7475c38c3b4..26135d92b34 100644
--- a/arch/m68knommu/platform/527x/Makefile
+++ b/arch/m68knommu/platform/527x/Makefile
@@ -12,9 +12,7 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-y := config.o
diff --git a/arch/m68knommu/platform/528x/Makefile b/arch/m68knommu/platform/528x/Makefile
index 7475c38c3b4..26135d92b34 100644
--- a/arch/m68knommu/platform/528x/Makefile
+++ b/arch/m68knommu/platform/528x/Makefile
@@ -12,9 +12,7 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-y := config.o
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile
index 580fd6658d7..cfd586860fd 100644
--- a/arch/m68knommu/platform/5307/Makefile
+++ b/arch/m68knommu/platform/5307/Makefile
@@ -12,9 +12,7 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-y += config.o
diff --git a/arch/m68knommu/platform/532x/Makefile b/arch/m68knommu/platform/532x/Makefile
index 475b92866a9..e431912f562 100644
--- a/arch/m68knommu/platform/532x/Makefile
+++ b/arch/m68knommu/platform/532x/Makefile
@@ -12,9 +12,7 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
#obj-y := config.o usb-mcf532x.o spi-mcf532x.o
obj-y := config.o
diff --git a/arch/m68knommu/platform/5407/Makefile b/arch/m68knommu/platform/5407/Makefile
index 68633b27df5..e6035e7a2d3 100644
--- a/arch/m68knommu/platform/5407/Makefile
+++ b/arch/m68knommu/platform/5407/Makefile
@@ -12,9 +12,7 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-y := config.o
diff --git a/arch/m68knommu/platform/coldfire/Makefile b/arch/m68knommu/platform/coldfire/Makefile
index e5fff297ae0..40cf20be1b9 100644
--- a/arch/m68knommu/platform/coldfire/Makefile
+++ b/arch/m68knommu/platform/coldfire/Makefile
@@ -12,9 +12,7 @@
# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
#
-ifdef CONFIG_FULLDEBUG
-AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
-endif
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-$(CONFIG_COLDFIRE) += dma.o entry.o vectors.o
obj-$(CONFIG_M5206) += timers.o
diff --git a/arch/m68knommu/platform/coldfire/entry.S b/arch/m68knommu/platform/coldfire/entry.S
index b333731b875..111b66dc737 100644
--- a/arch/m68knommu/platform/coldfire/entry.S
+++ b/arch/m68knommu/platform/coldfire/entry.S
@@ -197,14 +197,13 @@ ENTRY(fasthandler)
RESTORE_LOCAL
ENTRY(ret_from_interrupt)
- jeq 2f
-1:
- RESTORE_ALL
-2:
moveb %sp@(PT_SR),%d0
andl #0x7,%d0
- jhi 1b
+ jeq 1f
+ RESTORE_ALL
+
+1:
/* check if we need to do software interrupts */
movel irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0
jeq ret_from_exception
diff --git a/arch/m68knommu/platform/coldfire/timers.c b/arch/m68knommu/platform/coldfire/timers.c
index a60213e877e..ba5a9f32ebd 100644
--- a/arch/m68knommu/platform/coldfire/timers.c
+++ b/arch/m68knommu/platform/coldfire/timers.c
@@ -148,25 +148,32 @@ irqreturn_t coldfire_profile_tick(int irq, void *dummy)
/* Reset ColdFire timer2 */
__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER));
if (current->pid)
- profile_tick(CPU_PROFILING, regs);
+ profile_tick(CPU_PROFILING);
return IRQ_HANDLED;
}
/***************************************************************************/
+static struct irqaction coldfire_profile_irq = {
+ .name = "profile timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = coldfire_profile_tick,
+};
+
void coldfire_profile_init(void)
{
- printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ);
+ printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n",
+ PROFILEHZ);
+
+ setup_irq(mcf_profilevector, &coldfire_profile_irq);
/* Set up TIMER 2 as high speed profile clock */
__raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR));
- __raw_writetrr(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR));
+ __raw_writetrr(((MCF_BUSCLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR));
__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR));
- request_irq(mcf_profilevector, coldfire_profile_tick,
- (IRQF_DISABLED | IRQ_FLG_FAST), "profile timer", NULL);
mcf_settimericr(2, 7);
}
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ec78a5762e9..ade230d445d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1,6 +1,7 @@
config MIPS
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
# Horrible source of confusion. Die, die, die ...
select EMBEDDED
diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c
index 8527856aec4..0b658f1db4c 100644
--- a/arch/mips/au1000/common/gpio.c
+++ b/arch/mips/au1000/common/gpio.c
@@ -27,7 +27,6 @@
* others have a second one : GPIO2
*/
-#include <linux/autoconf.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/types.h>
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 197d7977de3..413bd1d37f5 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -338,8 +338,10 @@ void __init init_i8259_irqs(void)
init_8259A(0);
- for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++)
+ for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++) {
set_irq_chip_and_handler(i, &i8259A_chip, handle_level_irq);
+ set_irq_probe(i);
+ }
setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
}
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index 7852c7cdf29..290d8e3a664 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -591,9 +591,9 @@ static void irix_map_prda_page(void)
return;
pp = (struct prda *) v;
- pp->prda_sys.t_pid = current->pid;
+ pp->prda_sys.t_pid = task_pid_vnr(current);
pp->prda_sys.t_prid = read_c0_prid();
- pp->prda_sys.t_rpid = current->pid;
+ pp->prda_sys.t_rpid = task_pid_vnr(current);
/* We leave the rest set to zero */
}
@@ -1170,11 +1170,11 @@ static int irix_core_dump(long signr, struct pt_regs *regs, struct file *file, u
prstatus.pr_info.si_signo = prstatus.pr_cursig = signr;
prstatus.pr_sigpend = current->pending.signal.sig[0];
prstatus.pr_sighold = current->blocked.sig[0];
- psinfo.pr_pid = prstatus.pr_pid = current->pid;
- psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid;
- psinfo.pr_pgrp = prstatus.pr_pgrp = task_pgrp_nr(current);
- psinfo.pr_sid = prstatus.pr_sid = task_session_nr(current);
- if (current->pid == current->tgid) {
+ psinfo.pr_pid = prstatus.pr_pid = task_pid_vnr(current);
+ psinfo.pr_ppid = prstatus.pr_ppid = task_pid_vnr(current->parent);
+ psinfo.pr_pgrp = prstatus.pr_pgrp = task_pgrp_vnr(current);
+ psinfo.pr_sid = prstatus.pr_sid = task_session_vnr(current);
+ if (thread_group_leader(current)) {
/*
* This is the record for the group leader. Add in the
* cumulative times of previous dead threads. This total
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 5b10ac133ec..0215c805a59 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -578,10 +578,11 @@ out:
#define W_MASK (W_EXITED | W_TRAPPED | W_STOPPED | W_CONT | W_NOHANG)
-asmlinkage int irix_waitsys(int type, int pid,
+asmlinkage int irix_waitsys(int type, int upid,
struct irix5_siginfo __user *info, int options,
struct rusage __user *ru)
{
+ struct pid *pid = NULL;
int flag, retval;
DECLARE_WAITQUEUE(wait, current);
struct task_struct *tsk;
@@ -604,6 +605,8 @@ asmlinkage int irix_waitsys(int type, int pid,
if (type != IRIX_P_PID && type != IRIX_P_PGID && type != IRIX_P_ALL)
return -EINVAL;
+ if (type != IRIX_P_ALL)
+ pid = find_get_pid(upid);
add_wait_queue(&current->signal->wait_chldexit, &wait);
repeat:
flag = 0;
@@ -612,9 +615,9 @@ repeat:
tsk = current;
list_for_each(_p, &tsk->children) {
p = list_entry(_p, struct task_struct, sibling);
- if ((type == IRIX_P_PID) && p->pid != pid)
+ if ((type == IRIX_P_PID) && task_pid(p) != pid)
continue;
- if ((type == IRIX_P_PGID) && task_pgrp_nr(p) != pid)
+ if ((type == IRIX_P_PGID) && task_pgrp(p) != pid)
continue;
if ((p->exit_signal != SIGCHLD))
continue;
@@ -639,7 +642,7 @@ repeat:
retval = __put_user(SIGCHLD, &info->sig);
retval |= __put_user(0, &info->code);
- retval |= __put_user(p->pid, &info->stuff.procinfo.pid);
+ retval |= __put_user(task_pid_vnr(p), &info->stuff.procinfo.pid);
retval |= __put_user((p->exit_code >> 8) & 0xff,
&info->stuff.procinfo.procdata.child.status);
retval |= __put_user(p->utime, &info->stuff.procinfo.procdata.child.utime);
@@ -657,7 +660,7 @@ repeat:
getrusage(p, RUSAGE_BOTH, ru);
retval = __put_user(SIGCHLD, &info->sig);
retval |= __put_user(1, &info->code); /* CLD_EXITED */
- retval |= __put_user(p->pid, &info->stuff.procinfo.pid);
+ retval |= __put_user(task_pid_vnr(p), &info->stuff.procinfo.pid);
retval |= __put_user((p->exit_code >> 8) & 0xff,
&info->stuff.procinfo.procdata.child.status);
retval |= __put_user(p->utime,
@@ -665,7 +668,7 @@ repeat:
retval |= __put_user(p->stime,
&info->stuff.procinfo.procdata.child.stime);
if (retval)
- return retval;
+ goto end_waitsys;
if (p->real_parent != p->parent) {
write_lock_irq(&tasklist_lock);
@@ -698,6 +701,7 @@ repeat:
end_waitsys:
current->state = TASK_RUNNING;
remove_wait_queue(&current->signal->wait_chldexit, &wait);
+ put_pid(pid);
return retval;
}
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index d06e9c9af79..e3309ff9ece 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -145,6 +145,11 @@ __setup("nokgdb", nokgdb);
void __init init_IRQ(void)
{
+ int i;
+
+ for (i = 0; i < NR_IRQS; i++)
+ set_irq_noprobe(i);
+
arch_init_irq();
#ifdef CONFIG_KGDB
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 82480a1717d..f798139e888 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -660,7 +660,7 @@ einval: li v0, -EINVAL
sys sys_ioprio_get 2 /* 4315 */
sys sys_utimensat 4
sys sys_signalfd 3
- sys sys_timerfd 4
+ sys sys_ni_syscall 0
sys sys_eventfd 1
sys sys_fallocate 6 /* 4320 */
.endm
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index c2c10876da2..a626be6baea 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -475,7 +475,7 @@ sys_call_table:
PTR sys_ioprio_get
PTR sys_utimensat /* 5275 */
PTR sys_signalfd
- PTR sys_timerfd
+ PTR sys_ni_syscall
PTR sys_eventfd
PTR sys_fallocate
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 01993ec3368..9d5bcaf1b38 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -401,7 +401,7 @@ EXPORT(sysn32_call_table)
PTR sys_ioprio_get
PTR compat_sys_utimensat
PTR compat_sys_signalfd /* 5280 */
- PTR compat_sys_timerfd
+ PTR sys_ni_syscall
PTR sys_eventfd
PTR sys_fallocate
.size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index dd68afce7da..fd2019c1ec2 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -523,7 +523,7 @@ sys_call_table:
PTR sys_ioprio_get /* 4315 */
PTR compat_sys_utimensat
PTR compat_sys_signalfd
- PTR compat_sys_timerfd
+ PTR sys_ni_syscall
PTR sys_eventfd
PTR sys32_fallocate /* 4320 */
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index c032409cba9..39f3dfe134f 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -232,7 +232,7 @@ static void __init finalize_initrd(void)
goto disable;
}
- reserve_bootmem(__pa(initrd_start), size);
+ reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT);
initrd_below_start_ok = 1;
printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n",
@@ -413,7 +413,7 @@ static void __init bootmem_init(void)
/*
* Reserve the bootmap memory.
*/
- reserve_bootmem(PFN_PHYS(mapstart), bootmap_size);
+ reserve_bootmem(PFN_PHYS(mapstart), bootmap_size, BOOTMEM_DEFAULT);
/*
* Reserve initrd memory if needed.
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 1e5dfc28294..9d41dab90a8 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -52,7 +52,6 @@ int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */
EXPORT_SYMBOL(phys_cpu_present_map);
EXPORT_SYMBOL(cpu_online_map);
-extern void __init calibrate_delay(void);
extern void cpu_idle(void);
/* Number of TCs (or siblings in Intel speak) per CPU core */
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 4c477c7ff74..672fba84b2c 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -356,7 +356,7 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
retval = NGROUPS_MAX;
goto out;
case 5:
- retval = NR_OPEN;
+ retval = sysctl_nr_open;
goto out;
case 6:
retval = 1;
@@ -582,8 +582,8 @@ out:
asmlinkage int irix_getpid(struct pt_regs *regs)
{
- regs->regs[3] = current->real_parent->pid;
- return current->pid;
+ regs->regs[3] = task_pid_vnr(current->real_parent);
+ return task_pid_vnr(current);
}
asmlinkage int irix_getuid(struct pt_regs *regs)
@@ -694,7 +694,7 @@ asmlinkage int irix_statfs(const char __user *path,
if (error)
goto out;
- error = vfs_statfs(nd.dentry, &kbuf);
+ error = vfs_statfs(nd.path.dentry, &kbuf);
if (error)
goto dput_and_out;
@@ -711,7 +711,7 @@ asmlinkage int irix_statfs(const char __user *path,
}
dput_and_out:
- path_release(&nd);
+ path_put(&nd.path);
out:
return error;
}
@@ -763,11 +763,11 @@ asmlinkage int irix_setpgrp(int flags)
printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags);
#endif
if(!flags)
- error = task_pgrp_nr(current);
+ error = task_pgrp_vnr(current);
else
error = sys_setsid();
#ifdef DEBUG_PROCGRPS
- printk("returning %d\n", task_pgrp_nr(current));
+ printk("returning %d\n", error);
#endif
return error;
@@ -1093,10 +1093,10 @@ asmlinkage int irix_BSDsetpgrp(int pid, int pgrp)
pid, pgrp);
#endif
if(!pid)
- pid = current->pid;
+ pid = task_pid_vnr(current);
/* Wheee, weird sysv thing... */
- if ((pgrp == 0) && (pid == current->pid))
+ if ((pgrp == 0) && (pid == task_pid_vnr(current)))
error = sys_setsid();
else
error = sys_setpgid(pid, pgrp);
@@ -1360,7 +1360,7 @@ asmlinkage int irix_statvfs(char __user *fname, struct irix_statvfs __user *buf)
error = user_path_walk(fname, &nd);
if (error)
goto out;
- error = vfs_statfs(nd.dentry, &kbuf);
+ error = vfs_statfs(nd.path.dentry, &kbuf);
if (error)
goto dput_and_out;
@@ -1385,7 +1385,7 @@ asmlinkage int irix_statvfs(char __user *fname, struct irix_statvfs __user *buf)
error |= __put_user(0, &buf->f_fstr[i]);
dput_and_out:
- path_release(&nd);
+ path_put(&nd.path);
out:
return error;
}
@@ -1611,7 +1611,7 @@ asmlinkage int irix_statvfs64(char __user *fname, struct irix_statvfs64 __user *
error = user_path_walk(fname, &nd);
if (error)
goto out;
- error = vfs_statfs(nd.dentry, &kbuf);
+ error = vfs_statfs(nd.path.dentry, &kbuf);
if (error)
goto dput_and_out;
@@ -1636,7 +1636,7 @@ asmlinkage int irix_statvfs64(char __user *fname, struct irix_statvfs64 __user *
error |= __put_user(0, &buf->f_fstr[i]);
dput_and_out:
- path_release(&nd);
+ path_put(&nd.path);
out:
return error;
}
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index e5e023f50a0..bf438d02366 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -465,7 +465,8 @@ static void __init node_mem_init(cnodeid_t node)
free_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT,
(slot_lastpfn - slot_firstpfn) << PAGE_SHIFT);
reserve_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT,
- ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size);
+ ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size,
+ BOOTMEM_DEFAULT);
}
/*
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
new file mode 100644
index 00000000000..eedc3a5e0d9
--- /dev/null
+++ b/arch/mn10300/Kconfig
@@ -0,0 +1,381 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+mainmenu "Linux Kernel Configuration"
+
+config MN10300
+ def_bool y
+
+config AM33
+ def_bool y
+
+config MMU
+ def_bool y
+
+config HIGHMEM
+ def_bool n
+
+config NUMA
+ def_bool n
+
+config UID16
+ def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+ def_bool y
+
+config RWSEM_XCHGADD_ALGORITHM
+ bool
+
+config GENERIC_HARDIRQS_NO__DO_IRQ
+ def_bool y
+
+config GENERIC_CALIBRATE_DELAY
+ def_bool y
+
+config GENERIC_FIND_NEXT_BIT
+ def_bool y
+
+config GENERIC_HWEIGHT
+ def_bool y
+
+config GENERIC_TIME
+ def_bool y
+
+config GENERIC_BUG
+ def_bool y
+
+config QUICKLIST
+ def_bool y
+
+config ARCH_HAS_ILOG2_U32
+ def_bool y
+
+config ARCH_SUPPORTS_AOUT
+ def_bool n
+
+# Use the generic interrupt handling code in kernel/irq/
+config GENERIC_HARDIRQS
+ def_bool y
+
+config HOTPLUG_CPU
+ def_bool n
+
+mainmenu "Matsushita MN10300/AM33 Kernel Configuration"
+
+source "init/Kconfig"
+
+
+menu "Matsushita MN10300 system setup"
+
+choice
+ prompt "Unit type"
+ default MN10300_UNIT_ASB2303
+ help
+ This option specifies board for which the kernel will be
+ compiled. It affects the external peripherals catered for.
+
+config MN10300_UNIT_ASB2303
+ bool "ASB2303"
+
+config MN10300_UNIT_ASB2305
+ bool "ASB2305"
+
+endchoice
+
+choice
+ prompt "Processor support"
+ default MN10300_PROC_MN103E010
+ help
+ This option specifies the processor for which the kernel will be
+ compiled. It affects the on-chip peripherals catered for.
+
+config MN10300_PROC_MN103E010
+ bool "MN103E010"
+ depends on MN10300_UNIT_ASB2303 || MN10300_UNIT_ASB2305
+ select MN10300_PROC_HAS_TTYSM0
+ select MN10300_PROC_HAS_TTYSM1
+ select MN10300_PROC_HAS_TTYSM2
+
+endchoice
+
+choice
+ prompt "Processor core support"
+ default MN10300_CPU_AM33V2
+ help
+ This option specifies the processor core for which the kernel will be
+ compiled. It affects the instruction set used.
+
+config MN10300_CPU_AM33V2
+ bool "AM33v2"
+
+endchoice
+
+config FPU
+ bool "FPU present"
+ default y
+ depends on MN10300_PROC_MN103E010
+
+choice
+ prompt "CPU Caching mode"
+ default MN10300_CACHE_WBACK
+ help
+ This option determines the caching mode for the kernel.
+
+ Write-Back caching mode involves the all reads and writes causing
+ the affected cacheline to be read into the cache first before being
+ operated upon. Memory is not then updated by a write until the cache
+ is filled and a cacheline needs to be displaced from the cache to
+ make room. Only at that point is it written back.
+
+ Write-Through caching only fetches cachelines from memory on a
+ read. Writes always get written directly to memory. If the affected
+ cacheline is also in cache, it will be updated too.
+
+ The final option is to turn of caching entirely.
+
+config MN10300_CACHE_WBACK
+ bool "Write-Back"
+
+config MN10300_CACHE_WTHRU
+ bool "Write-Through"
+
+config MN10300_CACHE_DISABLED
+ bool "Disabled"
+
+endchoice
+
+menu "Memory layout options"
+
+config KERNEL_RAM_BASE_ADDRESS
+ hex "Base address of kernel RAM"
+ default "0x90000000"
+
+config INTERRUPT_VECTOR_BASE
+ hex "Base address of vector table"
+ default "0x90000000"
+ help
+ The base address of the vector table will be programmed into
+ the TBR register. It must be on 16MiB address boundary.
+
+config KERNEL_TEXT_ADDRESS
+ hex "Base address of kernel"
+ default "0x90001000"
+
+config KERNEL_ZIMAGE_BASE_ADDRESS
+ hex "Base address of compressed vmlinux image"
+ default "0x90700000"
+
+endmenu
+
+config PREEMPT
+ bool "Preemptible Kernel"
+ help
+ This option reduces the latency of the kernel when reacting to
+ real-time or interactive events by allowing a low priority process to
+ be preempted even if it is in kernel mode executing a system call.
+ This allows applications to run more reliably even when the system is
+ under load.
+
+ Say Y here if you are building a kernel for a desktop, embedded
+ or real-time system. Say N if you are unsure.
+
+config PREEMPT_BKL
+ bool "Preempt The Big Kernel Lock"
+ depends on PREEMPT
+ default y
+ help
+ This option reduces the latency of the kernel by making the
+ big kernel lock preemptible.
+
+ Say Y here if you are building a kernel for a desktop system.
+ Say N if you are unsure.
+
+config MN10300_CURRENT_IN_E2
+ bool "Hold current task address in E2 register"
+ default y
+ help
+ This option removes the E2/R2 register from the set available to gcc
+ for normal use and instead uses it to store the address of the
+ current process's task_struct whilst in the kernel.
+
+ This means the kernel doesn't need to calculate the address each time
+ "current" is used (take SP, AND with mask and dereference pointer
+ just to get the address), and instead can just use E2+offset
+ addressing each time.
+
+ This has no effect on userspace.
+
+config MN10300_USING_JTAG
+ bool "Using JTAG to debug kernel"
+ default y
+ help
+ This options indicates that JTAG will be used to debug the kernel. It
+ suppresses the use of certain hardware debugging features, such as
+ single-stepping, which are taken over completely by the JTAG unit.
+
+config MN10300_RTC
+ bool "Using MN10300 RTC"
+ depends on MN10300_PROC_MN103E010
+ default n
+ help
+
+ This option enables support for the RTC, thus enabling time to be
+ tracked, even when system is powered down. This is available on-chip
+ on the MN103E010.
+
+config MN10300_WD_TIMER
+ bool "Using MN10300 watchdog timer"
+ default y
+ help
+ This options indicates that the watchdog timer will be used.
+
+config PCI
+ bool "Use PCI"
+ depends on MN10300_UNIT_ASB2305
+ default y
+ help
+ Some systems (such as the ASB2305) have PCI onboard. If you have one
+ of these boards and you wish to use the PCI facilities, say Y here.
+
+ The PCI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, contains valuable
+ information about which PCI hardware does work under Linux and which
+ doesn't.
+
+source "drivers/pci/Kconfig"
+
+source "drivers/pcmcia/Kconfig"
+
+menu "MN10300 internal serial options"
+
+config MN10300_PROC_HAS_TTYSM0
+ bool
+ default n
+
+config MN10300_PROC_HAS_TTYSM1
+ bool
+ default n
+
+config MN10300_PROC_HAS_TTYSM2
+ bool
+ default n
+
+config MN10300_TTYSM
+ bool "Support for ttySM serial ports"
+ depends on MN10300
+ default y
+ select SERIAL_CORE
+ help
+ This option enables support for the on-chip serial ports that the
+ MN10300 has available.
+
+config MN10300_TTYSM_CONSOLE
+ bool "Support for console on ttySM serial ports"
+ depends on MN10300_TTYSM
+ select SERIAL_CORE_CONSOLE
+ help
+ This option enables support for a console on the on-chip serial ports
+ that the MN10300 has available.
+
+#
+# /dev/ttySM0
+#
+config MN10300_TTYSM0
+ bool "Enable SIF0 (/dev/ttySM0)"
+ depends on MN10300_TTYSM && MN10300_PROC_HAS_TTYSM0
+ help
+ Enable access to SIF0 through /dev/ttySM0 or gdb-stub
+
+choice
+ prompt "Select the timer to supply the clock for SIF0"
+ default MN10300_TTYSM0_TIMER8
+ depends on MN10300_TTYSM0
+
+config MN10300_TTYSM0_TIMER8
+ bool "Use timer 8 (16-bit)"
+
+config MN10300_TTYSM0_TIMER2
+ bool "Use timer 2 (8-bit)"
+
+endchoice
+
+#
+# /dev/ttySM1
+#
+config MN10300_TTYSM1
+ bool "Enable SIF1 (/dev/ttySM1)"
+ depends on MN10300_TTYSM && MN10300_PROC_HAS_TTYSM1
+ help
+ Enable access to SIF1 through /dev/ttySM1 or gdb-stub
+
+choice
+ prompt "Select the timer to supply the clock for SIF1"
+ default MN10300_TTYSM0_TIMER9
+ depends on MN10300_TTYSM1
+
+config MN10300_TTYSM1_TIMER9
+ bool "Use timer 9 (16-bit)"
+
+config MN10300_TTYSM1_TIMER3
+ bool "Use timer 3 (8-bit)"
+
+endchoice
+
+#
+# /dev/ttySM2
+#
+config MN10300_TTYSM2
+ bool "Enable SIF2 (/dev/ttySM2)"
+ depends on MN10300_TTYSM && MN10300_PROC_HAS_TTYSM2
+ help
+ Enable access to SIF2 through /dev/ttySM2 or gdb-stub
+
+choice
+ prompt "Select the timer to supply the clock for SIF2"
+ default MN10300_TTYSM0_TIMER10
+ depends on MN10300_TTYSM2
+
+config MN10300_TTYSM2_TIMER10
+ bool "Use timer 10 (16-bit)"
+
+endchoice
+
+config MN10300_TTYSM2_CTS
+ bool "Enable the use of the CTS line /dev/ttySM2"
+ depends on MN10300_TTYSM2
+
+endmenu
+
+source "mm/Kconfig"
+
+menu "Power management options"
+source kernel/power/Kconfig
+endmenu
+
+endmenu
+
+
+menu "Executable formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/mn10300/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
+source "arch/mn10300/oprofile/Kconfig"
diff --git a/arch/mn10300/Kconfig.debug b/arch/mn10300/Kconfig.debug
new file mode 100644
index 00000000000..524e33819f3
--- /dev/null
+++ b/arch/mn10300/Kconfig.debug
@@ -0,0 +1,135 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_STACKOVERFLOW
+ bool "Check for stack overflows"
+ depends on DEBUG_KERNEL
+
+config DEBUG_DECOMPRESS_KERNEL
+ bool "Using serial port during decompressing kernel"
+ depends on DEBUG_KERNEL
+ default n
+ help
+ If you say Y here you will confirm the start and the end of
+ decompressing Linux seeing "Uncompressing Linux... " and
+ "Ok, booting the kernel.\n" on console.
+
+config KPROBES
+ bool "Kprobes"
+ depends on DEBUG_KERNEL
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+
+config GDBSTUB
+ bool "Remote GDB kernel debugging"
+ depends on DEBUG_KERNEL
+ select DEBUG_INFO
+ select FRAME_POINTER
+ help
+ If you say Y here, it will be possible to remotely debug the kernel
+ using gdb. This enlarges your kernel ELF image disk size by several
+ megabytes and requires a machine with more than 16 MB, better 32 MB
+ RAM to avoid excessive linking time. This is only useful for kernel
+ hackers. If unsure, say N.
+
+config GDBSTUB_IMMEDIATE
+ bool "Break into GDB stub immediately"
+ depends on GDBSTUB
+ help
+ If you say Y here, GDB stub will break into the program as soon as
+ possible, leaving the program counter at the beginning of
+ start_kernel() in init/main.c.
+
+config GDB_CONSOLE
+ bool "Console output to GDB"
+ depends on GDBSTUB
+ help
+ If you are using GDB for remote debugging over a serial port and
+ would like kernel messages to be formatted into GDB $O packets so
+ that GDB prints them as program output, say 'Y'.
+
+config GDBSTUB_DEBUGGING
+ bool "Debug GDB stub by messages to serial port"
+ depends on GDBSTUB
+ help
+ This causes debugging messages to be displayed at various points
+ during execution of the GDB stub routines. Such messages will be
+ displayed on ttyS0 if that isn't the GDB stub's port, or ttySM0
+ otherwise.
+
+config GDBSTUB_DEBUG_ENTRY
+ bool "Debug GDB stub entry"
+ depends on GDBSTUB_DEBUGGING
+ help
+ This option causes information to be displayed about entry to or exit
+ from the main GDB stub routine.
+
+config GDBSTUB_DEBUG_PROTOCOL
+ bool "Debug GDB stub protocol"
+ depends on GDBSTUB_DEBUGGING
+ help
+ This option causes information to be displayed about the GDB remote
+ protocol messages generated exchanged with GDB.
+
+config GDBSTUB_DEBUG_IO
+ bool "Debug GDB stub I/O"
+ depends on GDBSTUB_DEBUGGING
+ help
+ This option causes information to be displayed about GDB stub's
+ low-level I/O.
+
+config GDBSTUB_DEBUG_BREAKPOINT
+ bool "Debug GDB stub breakpoint management"
+ depends on GDBSTUB_DEBUGGING
+ help
+ This option causes information to be displayed about GDB stub's
+ breakpoint management.
+
+choice
+ prompt "GDB stub port"
+ default GDBSTUB_TTYSM0
+ depends on GDBSTUB
+ help
+ Select the serial port used for GDB-stub.
+
+config GDBSTUB_ON_TTYSM0
+ bool "/dev/ttySM0 [SIF0]"
+ depends on MN10300_TTYSM0
+ select GDBSTUB_ON_TTYSMx
+
+config GDBSTUB_ON_TTYSM1
+ bool "/dev/ttySM1 [SIF1]"
+ depends on MN10300_TTYSM1
+ select GDBSTUB_ON_TTYSMx
+
+config GDBSTUB_ON_TTYSM2
+ bool "/dev/ttySM2 [SIF2]"
+ depends on MN10300_TTYSM2
+ select GDBSTUB_ON_TTYSMx
+
+config GDBSTUB_ON_TTYS0
+ bool "/dev/ttyS0"
+ select GDBSTUB_ON_TTYSx
+
+config GDBSTUB_ON_TTYS1
+ bool "/dev/ttyS1"
+ select GDBSTUB_ON_TTYSx
+
+endchoice
+
+config GDBSTUB_ON_TTYSMx
+ bool
+ depends on GDBSTUB_ON_TTYSM0 || GDBSTUB_ON_TTYSM1 || GDBSTUB_ON_TTYSM2
+ default y
+
+config GDBSTUB_ON_TTYSx
+ bool
+ depends on GDBSTUB_ON_TTYS0 || GDBSTUB_ON_TTYS1
+ default y
+
+endmenu
diff --git a/arch/mn10300/Makefile b/arch/mn10300/Makefile
new file mode 100644
index 00000000000..6673a28ec07
--- /dev/null
+++ b/arch/mn10300/Makefile
@@ -0,0 +1,135 @@
+###############################################################################
+#
+# MN10300 Kernel makefile system specifications
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Modified by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+
+KBUILD_DEFCONFIG := asb2303_defconfig
+
+CCSPECS := $(shell $(CC) -v 2>&1 | grep "^Reading specs from " | head -1 | cut -c20-)
+CCDIR := $(strip $(patsubst %/specs,%,$(CCSPECS)))
+KBUILD_CPPFLAGS += -nostdinc -I$(CCDIR)/include
+
+LDFLAGS :=
+OBJCOPYFLAGS := -O binary -R .note -R .comment -S
+#LDFLAGS_vmlinux := -Map linkmap.txt
+CHECKFLAGS +=
+
+PROCESSOR := unset
+UNIT := unset
+
+KBUILD_CFLAGS += -mam33 -mmem-funcs -DCPU=AM33
+KBUILD_AFLAGS += -mam33 -DCPU=AM33
+
+ifeq ($(CONFIG_MN10300_CURRENT_IN_E2),y)
+KBUILD_CFLAGS += -ffixed-e2 -fcall-saved-e5
+endif
+
+ifeq ($(CONFIG_MN10300_PROC_MN103E010),y)
+PROCESSOR := mn103e010
+endif
+
+ifeq ($(CONFIG_MN10300_UNIT_ASB2303),y)
+UNIT := asb2303
+endif
+ifeq ($(CONFIG_MN10300_UNIT_ASB2305),y)
+UNIT := asb2305
+endif
+
+
+head-y := arch/mn10300/kernel/head.o arch/mn10300/kernel/init_task.o
+
+core-y += arch/mn10300/kernel/ arch/mn10300/mm/
+
+ifneq ($(PROCESSOR),unset)
+core-y += arch/mn10300/proc-$(PROCESSOR)/
+endif
+ifneq ($(UNIT),unset)
+core-y += arch/mn10300/unit-$(UNIT)/
+endif
+libs-y += arch/mn10300/lib/
+
+drivers-$(CONFIG_OPROFILE) += arch/mn10300/oprofile/
+
+boot := arch/mn10300/boot
+
+.PHONY: zImage
+
+KBUILD_IMAGE := $(boot)/zImage
+CLEAN_FILES += $(boot)/zImage
+CLEAN_FILES += $(boot)/compressed/vmlinux
+CLEAN_FILES += $(boot)/compressed/vmlinux.bin
+CLEAN_FILES += $(boot)/compressed/vmlinux.bin.gz
+
+zImage: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+all: zImage
+
+bootstrap:
+ $(Q)$(MAKEBOOT) bootstrap
+
+archclean:
+ $(Q)$(MAKE) $(clean)=arch/mn10300/proc-mn103e010
+ $(Q)$(MAKE) $(clean)=arch/mn10300/unit-asb2303
+ $(Q)$(MAKE) $(clean)=arch/mn10300/unit-asb2305
+
+define archhelp
+ echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
+endef
+
+# If you make sure the .S files get compiled with debug info,
+# uncomment the following to disable optimisations
+# that are unhelpful whilst debugging.
+ifdef CONFIG_DEBUG_INFO
+#KBUILD_CFLAGS += -O1
+KBUILD_AFLAGS += -Wa,--gdwarf2
+endif
+
+###################################################################################################
+#
+# juggle some symlinks in the MN10300 asm include dir
+#
+# Update machine proc and unit symlinks if something which affects
+# them changed. We use .proc / .unit to indicate when they were
+# updated last, otherwise make uses the target directory mtime.
+#
+###################################################################################################
+
+# processor specific definitions
+include/asm-mn10300/.proc: $(wildcard include/config/proc/*.h) include/config/auto.conf
+ @echo ' SYMLINK include/asm-mn10300/proc -> include/asm-mn10300/proc-$(PROCESSOR)'
+ifneq ($(KBUILD_SRC),)
+ $(Q)mkdir -p include/asm-mn10300
+ $(Q)ln -fsn $(srctree)/include/asm-mn10300/proc-$(PROCESSOR) include/asm-mn10300/proc
+else
+ $(Q)ln -fsn proc-$(PROCESSOR) include/asm-mn10300/proc
+endif
+ @touch $@
+
+CLEAN_FILES += include/asm-mn10300/proc include/asm-mn10300/.proc
+
+prepare: include/asm-mn10300/.proc
+
+# unit specific definitions
+include/asm-mn10300/.unit: $(wildcard include/config/unit/*.h) include/config/auto.conf
+ @echo ' SYMLINK include/asm-mn10300/unit -> include/asm-mn10300/unit-$(UNIT)'
+ifneq ($(KBUILD_SRC),)
+ $(Q)mkdir -p include/asm-mn10300
+ $(Q)ln -fsn $(srctree)/include/asm-mn10300/unit-$(UNIT) include/asm-mn10300/unit
+else
+ $(Q)ln -fsn unit-$(UNIT) include/asm-mn10300/unit
+endif
+ @touch $@
+
+CLEAN_FILES += include/asm-mn10300/unit include/asm-mn10300/.unit
+
+prepare: include/asm-mn10300/.unit
diff --git a/arch/mn10300/boot/.gitignore b/arch/mn10300/boot/.gitignore
new file mode 100644
index 00000000000..b6718de2369
--- /dev/null
+++ b/arch/mn10300/boot/.gitignore
@@ -0,0 +1 @@
+zImage
diff --git a/arch/mn10300/boot/Makefile b/arch/mn10300/boot/Makefile
new file mode 100644
index 00000000000..36c9caf8ea0
--- /dev/null
+++ b/arch/mn10300/boot/Makefile
@@ -0,0 +1,28 @@
+# MN10300 kernel compressor and wrapper
+#
+# Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+
+targets := vmlinux.bin zImage
+
+subdir- := compressed
+
+# ---------------------------------------------------------------------------
+
+
+$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+ $(call if_changed,objcopy)
+ @echo 'Kernel: $@ is ready'
+
+$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
+ $(call if_changed,objcopy)
+
+$(obj)/compressed/vmlinux: FORCE
+ $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
diff --git a/arch/mn10300/boot/compressed/Makefile b/arch/mn10300/boot/compressed/Makefile
new file mode 100644
index 00000000000..08a95e17168
--- /dev/null
+++ b/arch/mn10300/boot/compressed/Makefile
@@ -0,0 +1,22 @@
+#
+# Create a compressed vmlinux image from the original vmlinux
+#
+
+targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
+
+LDFLAGS_vmlinux := -Ttext $(CONFIG_KERNEL_ZIMAGE_BASE_ADDRESS) -e startup_32
+
+$(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
+ $(call if_changed,ld)
+ @:
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+ $(call if_changed,gzip)
+
+LDFLAGS_piggy.o := -r --format binary --oformat elf32-am33lin -T
+
+$(obj)/piggy.o: $(obj)/vmlinux.lds $(obj)/vmlinux.bin.gz FORCE
+ $(call if_changed,ld)
diff --git a/arch/mn10300/boot/compressed/head.S b/arch/mn10300/boot/compressed/head.S
new file mode 100644
index 00000000000..502e1eb5670
--- /dev/null
+++ b/arch/mn10300/boot/compressed/head.S
@@ -0,0 +1,86 @@
+/* Boot entry point for a compressed MN10300 kernel
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+ .section .text
+
+#define DEBUG
+
+#include <linux/linkage.h>
+#include <asm/cpu-regs.h>
+
+ .globl startup_32
+startup_32:
+ # first save off parameters from bootloader
+ mov param_save_area,a0
+ mov d0,(a0)
+ mov d1,(4,a0)
+ mov d2,(8,a0)
+
+ mov sp,a3
+ mov decomp_stack+0x2000-4,a0
+ mov a0,sp
+
+ # invalidate and enable both of the caches
+ mov CHCTR,a0
+ clr d0
+ movhu d0,(a0) # turn off first
+ mov CHCTR_ICINV|CHCTR_DCINV,d0
+ movhu d0,(a0)
+ setlb
+ mov (a0),d0
+ btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy
+ lne
+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD,d0 # writethru dcache
+ movhu d0,(a0) # enable
+
+ # clear the BSS area
+ mov __bss_start,a0
+ mov _end,a1
+ clr d0
+bssclear:
+ cmp a1,a0
+ bge bssclear_end
+ movbu d0,(a0)
+ inc a0
+ bra bssclear
+bssclear_end:
+
+ # decompress the kernel
+ call decompress_kernel[],0
+
+ # disable caches again
+ mov CHCTR,a0
+ clr d0
+ movhu d0,(a0)
+ setlb
+ mov (a0),d0
+ btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy
+ lne
+
+ mov param_save_area,a0
+ mov (a0),d0
+ mov (4,a0),d1
+ mov (8,a0),d2
+
+ mov a3,sp
+ mov CONFIG_KERNEL_TEXT_ADDRESS,a0
+ jmp (a0)
+
+ .data
+ .align 4
+param_save_area:
+ .rept 3
+ .word 0
+ .endr
+
+ .section .bss
+ .align 4
+decomp_stack:
+ .space 0x2000
diff --git a/arch/mn10300/boot/compressed/misc.c b/arch/mn10300/boot/compressed/misc.c
new file mode 100644
index 00000000000..ded207efc97
--- /dev/null
+++ b/arch/mn10300/boot/compressed/misc.c
@@ -0,0 +1,429 @@
+/* MN10300 Miscellaneous helper routines for kernel decompressor
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ * - Derived from arch/x86/boot/compressed/misc_32.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/compiler.h>
+#include <asm/serial-regs.h>
+#include "misc.h"
+
+#ifndef CONFIG_GDBSTUB_ON_TTYSx
+/* display 'Uncompressing Linux... ' messages on ttyS0 or ttyS1 */
+#if 1 /* ttyS0 */
+#define CYG_DEV_BASE 0xA6FB0000
+#else /* ttyS1 */
+#define CYG_DEV_BASE 0xA6FC0000
+#endif
+
+#define CYG_DEV_THR (*((volatile __u8*)(CYG_DEV_BASE + 0x00)))
+#define CYG_DEV_MCR (*((volatile __u8*)(CYG_DEV_BASE + 0x10)))
+#define SIO_MCR_DTR 0x01
+#define SIO_MCR_RTS 0x02
+#define CYG_DEV_LSR (*((volatile __u8*)(CYG_DEV_BASE + 0x14)))
+#define SIO_LSR_THRE 0x20 /* transmitter holding register empty */
+#define SIO_LSR_TEMT 0x40 /* transmitter register empty */
+#define CYG_DEV_MSR (*((volatile __u8*)(CYG_DEV_BASE + 0x18)))
+#define SIO_MSR_CTS 0x10 /* clear to send */
+#define SIO_MSR_DSR 0x20 /* data set ready */
+
+#define LSR_WAIT_FOR(STATE) \
+ do { while (!(CYG_DEV_LSR & SIO_LSR_##STATE)) {} } while (0)
+#define FLOWCTL_QUERY(LINE) \
+ ({ CYG_DEV_MSR & SIO_MSR_##LINE; })
+#define FLOWCTL_WAIT_FOR(LINE) \
+ do { while (!(CYG_DEV_MSR & SIO_MSR_##LINE)) {} } while (0)
+#define FLOWCTL_CLEAR(LINE) \
+ do { CYG_DEV_MCR &= ~SIO_MCR_##LINE; } while (0)
+#define FLOWCTL_SET(LINE) \
+ do { CYG_DEV_MCR |= SIO_MCR_##LINE; } while (0)
+#endif
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args) args
+#define STATIC static
+
+#undef memset
+#undef memcpy
+
+static inline void *memset(const void *s, int c, size_t n)
+{
+ int i;
+ char *ss = (char *) s;
+
+ for (i = 0; i < n; i++)
+ ss[i] = c;
+ return (void *)s;
+}
+
+#define memzero(s, n) memset((s), 0, (n))
+
+static inline void *memcpy(void *__dest, const void *__src, size_t __n)
+{
+ int i;
+ const char *s = __src;
+ char *d = __dest;
+
+ for (i = 0; i < __n; i++)
+ d[i] = s[i];
+ return __dest;
+}
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+#define WSIZE 0x8000 /* Window size must be at least 32k, and a power of
+ * two */
+
+static uch *inbuf; /* input buffer */
+static uch window[WSIZE]; /* sliding window buffer */
+
+static unsigned insize; /* valid bytes in inbuf */
+static unsigned inptr; /* index of next byte to be processed in inbuf */
+static unsigned outcnt; /* bytes in output buffer */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
+#define RESERVED 0xC0 /* bit 6,7: reserved */
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# define Assert(cond, msg) { if (!(cond)) error(msg); }
+# define Trace(x) fprintf x
+# define Tracev(x) { if (verbose) fprintf x ; }
+# define Tracevv(x) { if (verbose > 1) fprintf x ; }
+# define Tracec(c, x) { if (verbose && (c)) fprintf x ; }
+# define Tracecv(c, x) { if (verbose > 1 && (c)) fprintf x ; }
+#else
+# define Assert(cond, msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c, x)
+# define Tracecv(c, x)
+#endif
+
+static int fill_inbuf(void);
+static void flush_window(void);
+static void error(const char *) __attribute__((noreturn));
+static void kputs(const char *);
+
+static inline unsigned char get_byte(void)
+{
+ unsigned char ch = inptr < insize ? inbuf[inptr++] : fill_inbuf();
+
+#if 0
+ char hex[3];
+ hex[0] = ((ch & 0x0f) > 9) ?
+ ((ch & 0x0f) + 'A' - 0xa) : ((ch & 0x0f) + '0');
+ hex[1] = ((ch >> 4) > 9) ?
+ ((ch >> 4) + 'A' - 0xa) : ((ch >> 4) + '0');
+ hex[2] = 0;
+ kputs(hex);
+#endif
+ return ch;
+}
+
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+#define EXT_MEM_K (*(unsigned short *)0x90002)
+#ifndef STANDARD_MEMORY_BIOS_CALL
+#define ALT_MEM_K (*(unsigned long *) 0x901e0)
+#endif
+#define SCREEN_INFO (*(struct screen_info *)0x90000)
+
+static long bytes_out;
+static uch *output_data;
+static unsigned long output_ptr;
+
+
+static void *malloc(int size);
+
+static inline void free(void *where)
+{ /* Don't care */
+}
+
+static unsigned long free_mem_ptr = (unsigned long) &end;
+static unsigned long free_mem_end_ptr = (unsigned long) &end + 0x90000;
+
+static inline void gzip_mark(void **ptr)
+{
+ kputs(".");
+ *ptr = (void *) free_mem_ptr;
+}
+
+static inline void gzip_release(void **ptr)
+{
+ free_mem_ptr = (unsigned long) *ptr;
+}
+
+#define INPLACE_MOVE_ROUTINE 0x1000
+#define LOW_BUFFER_START 0x2000
+#define LOW_BUFFER_END 0x90000
+#define LOW_BUFFER_SIZE (LOW_BUFFER_END - LOW_BUFFER_START)
+#define HEAP_SIZE 0x3000
+static int high_loaded;
+static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
+
+static char *vidmem = (char *)0xb8000;
+static int lines, cols;
+
+#include "../../../../lib/inflate.c"
+
+static void *malloc(int size)
+{
+ void *p;
+
+ if (size < 0)
+ error("Malloc error\n");
+ if (!free_mem_ptr)
+ error("Memory error\n");
+
+ free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
+
+ p = (void *) free_mem_ptr;
+ free_mem_ptr += size;
+
+ if (free_mem_ptr >= free_mem_end_ptr)
+ error("\nOut of memory\n");
+
+ return p;
+}
+
+static inline void scroll(void)
+{
+ int i;
+
+ memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
+ for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
+ vidmem[i] = ' ';
+}
+
+static inline void kputchar(unsigned char ch)
+{
+#ifdef CONFIG_MN10300_UNIT_ASB2305
+ while (SC0STR & SC01STR_TBF)
+ continue;
+
+ if (ch == 0x0a) {
+ SC0TXB = 0x0d;
+ while (SC0STR & SC01STR_TBF)
+ continue;
+ }
+
+ SC0TXB = ch;
+
+#else
+ while (SC1STR & SC01STR_TBF)
+ continue;
+
+ if (ch == 0x0a) {
+ SC1TXB = 0x0d;
+ while (SC1STR & SC01STR_TBF)
+ continue;
+ }
+
+ SC1TXB = ch;
+
+#endif
+}
+
+static void kputs(const char *s)
+{
+#ifdef CONFIG_DEBUG_DECOMPRESS_KERNEL
+#ifndef CONFIG_GDBSTUB_ON_TTYSx
+ char ch;
+
+ FLOWCTL_SET(DTR);
+
+ while (*s) {
+ LSR_WAIT_FOR(THRE);
+
+ ch = *s++;
+ if (ch == 0x0a) {
+ CYG_DEV_THR = 0x0d;
+ LSR_WAIT_FOR(THRE);
+ }
+ CYG_DEV_THR = ch;
+ }
+
+ FLOWCTL_CLEAR(DTR);
+#else
+
+ for (; *s; s++)
+ kputchar(*s);
+
+#endif
+#endif /* CONFIG_DEBUG_DECOMPRESS_KERNEL */
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf()
+{
+ if (insize != 0)
+ error("ran out of input data\n");
+
+ inbuf = input_data;
+ insize = input_len;
+ inptr = 1;
+ return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window_low(void)
+{
+ ulg c = crc; /* temporary variable */
+ unsigned n;
+ uch *in, *out, ch;
+
+ in = window;
+ out = &output_data[output_ptr];
+ for (n = 0; n < outcnt; n++) {
+ ch = *out++ = *in++;
+ c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+ }
+ crc = c;
+ bytes_out += (ulg)outcnt;
+ output_ptr += (ulg)outcnt;
+ outcnt = 0;
+}
+
+static void flush_window_high(void)
+{
+ ulg c = crc; /* temporary variable */
+ unsigned n;
+ uch *in, ch;
+ in = window;
+ for (n = 0; n < outcnt; n++) {
+ ch = *output_data++ = *in++;
+ if ((ulg) output_data == LOW_BUFFER_END)
+ output_data = high_buffer_start;
+ c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+ }
+ crc = c;
+ bytes_out += (ulg)outcnt;
+ outcnt = 0;
+}
+
+static void flush_window(void)
+{
+ if (high_loaded)
+ flush_window_high();
+ else
+ flush_window_low();
+}
+
+static void error(const char *x)
+{
+ kputs("\n\n");
+ kputs(x);
+ kputs("\n\n -- System halted");
+
+ while (1)
+ /* Halt */;
+}
+
+#define STACK_SIZE (4096)
+
+long user_stack[STACK_SIZE];
+
+struct {
+ long *a;
+ short b;
+} stack_start = { &user_stack[STACK_SIZE], 0 };
+
+void setup_normal_output_buffer(void)
+{
+#ifdef STANDARD_MEMORY_BIOS_CALL
+ if (EXT_MEM_K < 1024)
+ error("Less than 2MB of memory.\n");
+#else
+ if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024)
+ error("Less than 2MB of memory.\n");
+#endif
+ output_data = (char *) 0x100000; /* Points to 1M */
+}
+
+struct moveparams {
+ uch *low_buffer_start;
+ int lcount;
+ uch *high_buffer_start;
+ int hcount;
+};
+
+void setup_output_buffer_if_we_run_high(struct moveparams *mv)
+{
+ high_buffer_start = (uch *)(((ulg) &end) + HEAP_SIZE);
+#ifdef STANDARD_MEMORY_BIOS_CALL
+ if (EXT_MEM_K < (3 * 1024))
+ error("Less than 4MB of memory.\n");
+#else
+ if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3 * 1024))
+ error("Less than 4MB of memory.\n");
+#endif
+ mv->low_buffer_start = output_data = (char *) LOW_BUFFER_START;
+ high_loaded = 1;
+ free_mem_end_ptr = (long) high_buffer_start;
+ if (0x100000 + LOW_BUFFER_SIZE > (ulg) high_buffer_start) {
+ high_buffer_start = (uch *)(0x100000 + LOW_BUFFER_SIZE);
+ mv->hcount = 0; /* say: we need not to move high_buffer */
+ } else {
+ mv->hcount = -1;
+ }
+ mv->high_buffer_start = high_buffer_start;
+}
+
+void close_output_buffer_if_we_run_high(struct moveparams *mv)
+{
+ mv->lcount = bytes_out;
+ if (bytes_out > LOW_BUFFER_SIZE) {
+ mv->lcount = LOW_BUFFER_SIZE;
+ if (mv->hcount)
+ mv->hcount = bytes_out - LOW_BUFFER_SIZE;
+ } else {
+ mv->hcount = 0;
+ }
+}
+
+#undef DEBUGFLAG
+#ifdef DEBUGFLAG
+int debugflag;
+#endif
+
+int decompress_kernel(struct moveparams *mv)
+{
+#ifdef DEBUGFLAG
+ while (!debugflag)
+ barrier();
+#endif
+
+ output_data = (char *) CONFIG_KERNEL_TEXT_ADDRESS;
+
+ makecrc();
+ kputs("Uncompressing Linux... ");
+ gunzip();
+ kputs("Ok, booting the kernel.\n");
+ return 0;
+}
diff --git a/arch/mn10300/boot/compressed/misc.h b/arch/mn10300/boot/compressed/misc.h
new file mode 100644
index 00000000000..da921cd172f
--- /dev/null
+++ b/arch/mn10300/boot/compressed/misc.h
@@ -0,0 +1,18 @@
+/* Internal definitions for the MN10300 kernel decompressor
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+extern int end;
+
+/*
+ * vmlinux.lds
+ */
+extern char input_data[];
+extern int input_len;
diff --git a/arch/mn10300/boot/compressed/vmlinux.lds b/arch/mn10300/boot/compressed/vmlinux.lds
new file mode 100644
index 00000000000..a084903603f
--- /dev/null
+++ b/arch/mn10300/boot/compressed/vmlinux.lds
@@ -0,0 +1,9 @@
+SECTIONS
+{
+ .data : {
+ input_len = .;
+ LONG(input_data_end - input_data) input_data = .;
+ *(.data)
+ input_data_end = .;
+ }
+}
diff --git a/arch/mn10300/boot/install.sh b/arch/mn10300/boot/install.sh
new file mode 100644
index 00000000000..072951c8397
--- /dev/null
+++ b/arch/mn10300/boot/install.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+#
+# arch/mn10300/boot/install -c.sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# Licence. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+#
+# "make install -c" script for i386 architecture
+#
+# Arguments:
+# $1 - kernel version
+# $2 - kernel image file
+# $3 - kernel map file
+# $4 - default install -c path (blank if root directory)
+# $5 - boot rom file
+#
+
+# User may have a custom install -c script
+
+rm -fr $4/../usr/include/linux $4/../usr/include/asm
+install -c -m 0755 $2 $4/vmlinuz
+install -c -m 0755 $5 $4/boot.rom
+install -c -m 0755 -d $4/../usr/include/linux
+cd $TOPDIR/include/linux
+for i in `find . -maxdepth 1 -name '*.h' -print`; do
+ install -c -m 0644 $i $4/../usr/include/linux
+done
+install -c -m 0755 -d $4/../usr/include/linux/byteorder
+cd $TOPDIR/include/linux/byteorder
+for i in `find . -name '*.h' -print`; do
+ install -c -m 0644 $i $4/../usr/include/linux/byteorder
+done
+install -c -m 0755 -d $4/../usr/include/linux/lockd
+cd $TOPDIR/include/linux/lockd
+for i in `find . -name '*.h' -print`; do
+ install -c -m 0644 $i $4/../usr/include/linux/lockd
+done
+install -c -m 0755 -d $4/../usr/include/linux/netfilter_ipv4
+cd $TOPDIR/include/linux/netfilter_ipv4
+for i in `find . -name '*.h' -print`; do
+ install -c -m 0644 $i $4/../usr/include/linux/netfilter_ipv4
+done
+install -c -m 0755 -d $4/../usr/include/linux/nfsd
+cd $TOPDIR/include/linux/nfsd
+for i in `find . -name '*.h' -print`; do
+ install -c -m 0644 $i $4/../usr/include/linux/nfsd/$i
+done
+install -c -m 0755 -d $4/../usr/include/linux/raid
+cd $TOPDIR/include/linux/raid
+for i in `find . -name '*.h' -print`; do
+ install -c -m 0644 $i $4/../usr/include/linux/raid
+done
+install -c -m 0755 -d $4/../usr/include/linux/sunrpc
+cd $TOPDIR/include/linux/sunrpc
+for i in `find . -name '*.h' -print`; do
+ install -c -m 0644 $i $4/../usr/include/linux/sunrpc
+done
+install -c -m 0755 -d $4/../usr/include/asm
+cd $TOPDIR/include/asm
+for i in `find . -name '*.h' -print`; do
+ install -c -m 0644 $i $4/../usr/include/asm
+done
diff --git a/arch/mn10300/boot/tools/build.c b/arch/mn10300/boot/tools/build.c
new file mode 100644
index 00000000000..4f552ead0f8
--- /dev/null
+++ b/arch/mn10300/boot/tools/build.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1997 Martin Mares
+ */
+
+/*
+ * This file builds a disk-image from three different files:
+ *
+ * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
+ * - setup: 8086 machine code, sets up system parm
+ * - system: 80386 code for actual system
+ *
+ * It does some checking that all files are of the correct type, and
+ * just writes the result to stdout, removing headers and padding to
+ * the right amount. It also writes some system data to stderr.
+ */
+
+/*
+ * Changes by tytso to allow root device specification
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ * Cross compiling fixes by Gertjan van Wingerde, July 1996
+ * Rewritten by Martin Mares, April 1997
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <asm/boot.h>
+
+#define DEFAULT_MAJOR_ROOT 0
+#define DEFAULT_MINOR_ROOT 0
+
+/* Minimal number of setup sectors (see also bootsect.S) */
+#define SETUP_SECTS 4
+
+uint8_t buf[1024];
+int fd;
+int is_big_kernel;
+
+__attribute__((noreturn))
+void die(const char *str, ...)
+{
+ va_list args;
+ va_start(args, str);
+ vfprintf(stderr, str, args);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+void file_open(const char *name)
+{
+ fd = open(name, O_RDONLY, 0);
+ if (fd < 0)
+ die("Unable to open `%s': %m", name);
+}
+
+__attribute__((noreturn))
+void usage(void)
+{
+ die("Usage: build [-b] bootsect setup system [rootdev] [> image]");
+}
+
+int main(int argc, char **argv)
+{
+ unsigned int i, c, sz, setup_sectors;
+ uint32_t sys_size;
+ uint8_t major_root, minor_root;
+ struct stat sb;
+
+ if (argc > 2 && !strcmp(argv[1], "-b")) {
+ is_big_kernel = 1;
+ argc--, argv++;
+ }
+ if ((argc < 4) || (argc > 5))
+ usage();
+ if (argc > 4) {
+ if (!strcmp(argv[4], "CURRENT")) {
+ if (stat("/", &sb)) {
+ perror("/");
+ die("Couldn't stat /");
+ }
+ major_root = major(sb.st_dev);
+ minor_root = minor(sb.st_dev);
+ } else if (strcmp(argv[4], "FLOPPY")) {
+ if (stat(argv[4], &sb)) {
+ perror(argv[4]);
+ die("Couldn't stat root device.");
+ }
+ major_root = major(sb.st_rdev);
+ minor_root = minor(sb.st_rdev);
+ } else {
+ major_root = 0;
+ minor_root = 0;
+ }
+ } else {
+ major_root = DEFAULT_MAJOR_ROOT;
+ minor_root = DEFAULT_MINOR_ROOT;
+ }
+ fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
+
+ file_open(argv[1]);
+ i = read(fd, buf, sizeof(buf));
+ fprintf(stderr, "Boot sector %d bytes.\n", i);
+ if (i != 512)
+ die("Boot block must be exactly 512 bytes");
+ if (buf[510] != 0x55 || buf[511] != 0xaa)
+ die("Boot block hasn't got boot flag (0xAA55)");
+ buf[508] = minor_root;
+ buf[509] = major_root;
+ if (write(1, buf, 512) != 512)
+ die("Write call failed");
+ close(fd);
+
+ /* Copy the setup code */
+ file_open(argv[2]);
+ for (i = 0; (c = read(fd, buf, sizeof(buf))) > 0; i += c)
+ if (write(1, buf, c) != c)
+ die("Write call failed");
+ if (c != 0)
+ die("read-error on `setup'");
+ close(fd);
+
+ /* Pad unused space with zeros */
+ setup_sectors = (i + 511) / 512;
+ /* for compatibility with ancient versions of LILO. */
+ if (setup_sectors < SETUP_SECTS)
+ setup_sectors = SETUP_SECTS;
+ fprintf(stderr, "Setup is %d bytes.\n", i);
+ memset(buf, 0, sizeof(buf));
+ while (i < setup_sectors * 512) {
+ c = setup_sectors * 512 - i;
+ if (c > sizeof(buf))
+ c = sizeof(buf);
+ if (write(1, buf, c) != c)
+ die("Write call failed");
+ i += c;
+ }
+
+ file_open(argv[3]);
+ if (fstat(fd, &sb))
+ die("Unable to stat `%s': %m", argv[3]);
+ sz = sb.st_size;
+ fprintf(stderr, "System is %d kB\n", sz / 1024);
+ sys_size = (sz + 15) / 16;
+ /* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */
+ if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE))
+ die("System is too big. Try using %smodules.",
+ is_big_kernel ? "" : "bzImage or ");
+ if (sys_size > 0xffff)
+ fprintf(stderr,
+ "warning: kernel is too big for standalone boot "
+ "from floppy\n");
+ while (sz > 0) {
+ int l, n;
+
+ l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
+ n = read(fd, buf, l);
+ if (n != l) {
+ if (n < 0)
+ die("Error reading %s: %m", argv[3]);
+ else
+ die("%s: Unexpected EOF", argv[3]);
+ }
+ if (write(1, buf, l) != l)
+ die("Write failed");
+ sz -= l;
+ }
+ close(fd);
+
+ /* Write sizes to the bootsector */
+ if (lseek(1, 497, SEEK_SET) != 497)
+ die("Output: seek failed");
+ buf[0] = setup_sectors;
+ if (write(1, buf, 1) != 1)
+ die("Write of setup sector count failed");
+ if (lseek(1, 500, SEEK_SET) != 500)
+ die("Output: seek failed");
+ buf[0] = (sys_size & 0xff);
+ buf[1] = ((sys_size >> 8) & 0xff);
+ if (write(1, buf, 2) != 2)
+ die("Write of image length failed");
+
+ return 0;
+}
diff --git a/arch/mn10300/configs/asb2303_defconfig b/arch/mn10300/configs/asb2303_defconfig
new file mode 100644
index 00000000000..ca9876a111d
--- /dev/null
+++ b/arch/mn10300/configs/asb2303_defconfig
@@ -0,0 +1,558 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.24-rc2
+# Fri Nov 16 13:36:38 2007
+#
+CONFIG_MN10300=y
+CONFIG_AM33=y
+CONFIG_MMU=y
+# CONFIG_HIGHMEM is not set
+# CONFIG_NUMA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_BUG=y
+CONFIG_QUICKLIST=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+# CONFIG_ARCH_SUPPORTS_AOUT is not set
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_FAIR_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+# CONFIG_BLOCK is not set
+
+#
+# Matsushita MN10300 system setup
+#
+CONFIG_MN10300_UNIT_ASB2303=y
+# CONFIG_MN10300_UNIT_ASB2305 is not set
+CONFIG_MN10300_PROC_MN103E010=y
+CONFIG_MN10300_CPU_AM33V2=y
+CONFIG_FPU=y
+CONFIG_MN10300_CACHE_WBACK=y
+# CONFIG_MN10300_CACHE_WTHRU is not set
+# CONFIG_MN10300_CACHE_DISABLED is not set
+
+#
+# Memory layout options
+#
+CONFIG_KERNEL_RAM_BASE_ADDRESS=0x90000000
+CONFIG_INTERRUPT_VECTOR_BASE=0x90000000
+CONFIG_KERNEL_TEXT_ADDRESS=0x90001000
+CONFIG_KERNEL_ZIMAGE_BASE_ADDRESS=0x90700000
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+CONFIG_MN10300_CURRENT_IN_E2=y
+CONFIG_MN10300_USING_JTAG=y
+CONFIG_MN10300_RTC=y
+CONFIG_MN10300_WD_TIMER=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# MN10300 internal serial options
+#
+CONFIG_MN10300_PROC_HAS_TTYSM0=y
+CONFIG_MN10300_PROC_HAS_TTYSM1=y
+CONFIG_MN10300_PROC_HAS_TTYSM2=y
+CONFIG_MN10300_TTYSM=y
+CONFIG_MN10300_TTYSM_CONSOLE=y
+CONFIG_MN10300_TTYSM0=y
+CONFIG_MN10300_TTYSM0_TIMER8=y
+# CONFIG_MN10300_TTYSM0_TIMER2 is not set
+CONFIG_MN10300_TTYSM1=y
+CONFIG_MN10300_TTYSM1_TIMER9=y
+# CONFIG_MN10300_TTYSM1_TIMER3 is not set
+# CONFIG_MN10300_TTYSM2 is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=1
+CONFIG_VIRT_TO_BUS=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Executable formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=0
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI_I4=y
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_RTC=y
+# CONFIG_R3964 is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_RTC_CLASS is not set
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
new file mode 100644
index 00000000000..ef07c956170
--- /dev/null
+++ b/arch/mn10300/kernel/Makefile
@@ -0,0 +1,27 @@
+#
+# Makefile for the MN10300-specific core kernel code
+#
+extra-y := head.o init_task.o vmlinux.lds
+
+obj-y := process.o semaphore.o signal.o entry.o fpu.o traps.o irq.o \
+ ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
+ switch_to.o mn10300_ksyms.o kernel_execve.o
+
+obj-$(CONFIG_MN10300_WD_TIMER) += mn10300-watchdog.o mn10300-watchdog-low.o
+
+obj-$(CONFIG_FPU) += fpu-low.o
+
+obj-$(CONFIG_MN10300_TTYSM) += mn10300-serial.o mn10300-serial-low.o \
+ mn10300-debug.o
+obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o
+obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o
+obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o
+
+ifneq ($(CONFIG_MN10300_CACHE_DISABLED),y)
+obj-$(CONFIG_GDBSTUB) += gdb-cache.o
+endif
+
+obj-$(CONFIG_MN10300_RTC) += rtc.o
+obj-$(CONFIG_PROFILE) += profile.o profile-low.o
+obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_KPROBES) += kprobes.o
diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c
new file mode 100644
index 00000000000..ee2d9f8af5a
--- /dev/null
+++ b/arch/mn10300/kernel/asm-offsets.c
@@ -0,0 +1,108 @@
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed
+ * to extract and format the required data.
+ */
+
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/personality.h>
+#include <asm/ucontext.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
+#include <asm/ptrace.h>
+#include "sigframe.h"
+#include "mn10300-serial.h"
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->")
+
+#define OFFSET(sym, str, mem) \
+ DEFINE(sym, offsetof(struct str, mem));
+
+void foo(void)
+{
+ OFFSET(SIGCONTEXT_d0, sigcontext, d0);
+ OFFSET(SIGCONTEXT_d1, sigcontext, d1);
+ BLANK();
+
+ OFFSET(TI_task, thread_info, task);
+ OFFSET(TI_exec_domain, thread_info, exec_domain);
+ OFFSET(TI_flags, thread_info, flags);
+ OFFSET(TI_cpu, thread_info, cpu);
+ OFFSET(TI_preempt_count, thread_info, preempt_count);
+ OFFSET(TI_addr_limit, thread_info, addr_limit);
+ OFFSET(TI_restart_block, thread_info, restart_block);
+ BLANK();
+
+ OFFSET(REG_D0, pt_regs, d0);
+ OFFSET(REG_D1, pt_regs, d1);
+ OFFSET(REG_D2, pt_regs, d2);
+ OFFSET(REG_D3, pt_regs, d3);
+ OFFSET(REG_A0, pt_regs, a0);
+ OFFSET(REG_A1, pt_regs, a1);
+ OFFSET(REG_A2, pt_regs, a2);
+ OFFSET(REG_A3, pt_regs, a3);
+ OFFSET(REG_E0, pt_regs, e0);
+ OFFSET(REG_E1, pt_regs, e1);
+ OFFSET(REG_E2, pt_regs, e2);
+ OFFSET(REG_E3, pt_regs, e3);
+ OFFSET(REG_E4, pt_regs, e4);
+ OFFSET(REG_E5, pt_regs, e5);
+ OFFSET(REG_E6, pt_regs, e6);
+ OFFSET(REG_E7, pt_regs, e7);
+ OFFSET(REG_SP, pt_regs, sp);
+ OFFSET(REG_EPSW, pt_regs, epsw);
+ OFFSET(REG_PC, pt_regs, pc);
+ OFFSET(REG_LAR, pt_regs, lar);
+ OFFSET(REG_LIR, pt_regs, lir);
+ OFFSET(REG_MDR, pt_regs, mdr);
+ OFFSET(REG_MCVF, pt_regs, mcvf);
+ OFFSET(REG_MCRL, pt_regs, mcrl);
+ OFFSET(REG_MCRH, pt_regs, mcrh);
+ OFFSET(REG_MDRQ, pt_regs, mdrq);
+ OFFSET(REG_ORIG_D0, pt_regs, orig_d0);
+ OFFSET(REG_NEXT, pt_regs, next);
+ DEFINE(REG__END, sizeof(struct pt_regs));
+ BLANK();
+
+ OFFSET(THREAD_UREGS, thread_struct, uregs);
+ OFFSET(THREAD_PC, thread_struct, pc);
+ OFFSET(THREAD_SP, thread_struct, sp);
+ OFFSET(THREAD_A3, thread_struct, a3);
+ OFFSET(THREAD_USP, thread_struct, usp);
+ OFFSET(THREAD_FRAME, thread_struct, __frame);
+ BLANK();
+
+ DEFINE(CLONE_VM_asm, CLONE_VM);
+ DEFINE(CLONE_FS_asm, CLONE_FS);
+ DEFINE(CLONE_FILES_asm, CLONE_FILES);
+ DEFINE(CLONE_SIGHAND_asm, CLONE_SIGHAND);
+ DEFINE(CLONE_UNTRACED_asm, CLONE_UNTRACED);
+ DEFINE(SIGCHLD_asm, SIGCHLD);
+ BLANK();
+
+ OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
+ OFFSET(RT_SIGFRAME_sigcontext, rt_sigframe, uc.uc_mcontext);
+
+ DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
+
+ OFFSET(__rx_buffer, mn10300_serial_port, rx_buffer);
+ OFFSET(__rx_inp, mn10300_serial_port, rx_inp);
+ OFFSET(__rx_outp, mn10300_serial_port, rx_outp);
+ OFFSET(__tx_info_buffer, mn10300_serial_port, uart.info);
+ OFFSET(__tx_xchar, mn10300_serial_port, tx_xchar);
+ OFFSET(__tx_break, mn10300_serial_port, tx_break);
+ OFFSET(__intr_flags, mn10300_serial_port, intr_flags);
+ OFFSET(__rx_icr, mn10300_serial_port, rx_icr);
+ OFFSET(__tx_icr, mn10300_serial_port, tx_icr);
+ OFFSET(__tm_icr, mn10300_serial_port, _tmicr);
+ OFFSET(__iobase, mn10300_serial_port, _iobase);
+
+ DEFINE(__UART_XMIT_SIZE, UART_XMIT_SIZE);
+ OFFSET(__xmit_buffer, uart_info, xmit.buf);
+ OFFSET(__xmit_head, uart_info, xmit.head);
+ OFFSET(__xmit_tail, uart_info, xmit.tail);
+}
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
new file mode 100644
index 00000000000..11de3606eee
--- /dev/null
+++ b/arch/mn10300/kernel/entry.S
@@ -0,0 +1,721 @@
+###############################################################################
+#
+# MN10300 Exception and interrupt entry points
+#
+# Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Modified by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/thread_info.h>
+#include <asm/intctl-regs.h>
+#include <asm/busctl-regs.h>
+#include <asm/timer-regs.h>
+#include <asm/unit/leds.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/errno.h>
+#include <asm/asm-offsets.h>
+#include <asm/frame.inc>
+
+#ifdef CONFIG_PREEMPT
+#define preempt_stop __cli
+#else
+#define preempt_stop
+#define resume_kernel restore_all
+#endif
+
+ .macro __cli
+ and ~EPSW_IM,epsw
+ or EPSW_IE|MN10300_CLI_LEVEL,epsw
+ nop
+ nop
+ nop
+ .endm
+ .macro __sti
+ or EPSW_IE|EPSW_IM_7,epsw
+ .endm
+
+
+ .am33_2
+
+###############################################################################
+#
+# the return path for a forked child
+# - on entry, D0 holds the address of the previous task to run
+#
+###############################################################################
+ENTRY(ret_from_fork)
+ call schedule_tail[],0
+ GET_THREAD_INFO a2
+
+ # return 0 to indicate child process
+ clr d0
+ mov d0,(REG_D0,fp)
+ jmp syscall_exit
+
+###############################################################################
+#
+# system call handler
+#
+###############################################################################
+ENTRY(system_call)
+ add -4,sp
+ SAVE_ALL
+ mov d0,(REG_ORIG_D0,fp)
+ GET_THREAD_INFO a2
+ cmp nr_syscalls,d0
+ bcc syscall_badsys
+ btst _TIF_SYSCALL_TRACE,(TI_flags,a2)
+ bne syscall_trace_entry
+syscall_call:
+ add d0,d0,a1
+ add a1,a1
+ mov (REG_A0,fp),d0
+ mov (sys_call_table,a1),a0
+ calls (a0)
+ mov d0,(REG_D0,fp)
+syscall_exit:
+ # make sure we don't miss an interrupt setting need_resched or
+ # sigpending between sampling and the rti
+ __cli
+ mov (TI_flags,a2),d2
+ btst _TIF_ALLWORK_MASK,d2
+ bne syscall_exit_work
+restore_all:
+ RESTORE_ALL
+
+###############################################################################
+#
+# perform work that needs to be done immediately before resumption and syscall
+# tracing
+#
+###############################################################################
+ ALIGN
+syscall_exit_work:
+ btst _TIF_SYSCALL_TRACE,d2
+ beq work_pending
+ __sti # could let do_syscall_trace() call
+ # schedule() instead
+ mov fp,d0
+ mov 1,d1
+ call do_syscall_trace[],0 # do_syscall_trace(regs,entryexit)
+ jmp resume_userspace
+
+ ALIGN
+work_pending:
+ btst _TIF_NEED_RESCHED,d2
+ beq work_notifysig
+
+work_resched:
+ call schedule[],0
+
+ # make sure we don't miss an interrupt setting need_resched or
+ # sigpending between sampling and the rti
+ __cli
+
+ # is there any work to be done other than syscall tracing?
+ mov (TI_flags,a2),d2
+ btst _TIF_WORK_MASK,d2
+ beq restore_all
+ btst _TIF_NEED_RESCHED,d2
+ bne work_resched
+
+ # deal with pending signals and notify-resume requests
+work_notifysig:
+ mov fp,d0
+ mov d2,d1
+ call do_notify_resume[],0
+ jmp resume_userspace
+
+ # perform syscall entry tracing
+syscall_trace_entry:
+ mov -ENOSYS,d0
+ mov d0,(REG_D0,fp)
+ mov fp,d0
+ clr d1
+ call do_syscall_trace[],0
+ mov (REG_ORIG_D0,fp),d0
+ mov (REG_D1,fp),d1
+ cmp nr_syscalls,d0
+ bcs syscall_call
+ jmp syscall_exit
+
+syscall_badsys:
+ mov -ENOSYS,d0
+ mov d0,(REG_D0,fp)
+ jmp resume_userspace
+
+ # userspace resumption stub bypassing syscall exit tracing
+ .globl ret_from_exception, ret_from_intr
+ ALIGN
+ret_from_exception:
+ preempt_stop
+ret_from_intr:
+ GET_THREAD_INFO a2
+ mov (REG_EPSW,fp),d0 # need to deliver signals before
+ # returning to userspace
+ and EPSW_nSL,d0
+ beq resume_kernel # returning to supervisor mode
+
+ENTRY(resume_userspace)
+ # make sure we don't miss an interrupt setting need_resched or
+ # sigpending between sampling and the rti
+ __cli
+
+ # is there any work to be done on int/exception return?
+ mov (TI_flags,a2),d2
+ btst _TIF_WORK_MASK,d2
+ bne work_pending
+ jmp restore_all
+
+#ifdef CONFIG_PREEMPT
+ENTRY(resume_kernel)
+ mov (TI_preempt_count,a2),d0 # non-zero preempt_count ?
+ cmp 0,d0
+ bne restore_all
+
+need_resched:
+ btst _TIF_NEED_RESCHED,(TI_flags,a2)
+ beq restore_all
+ mov (REG_EPSW,fp),d0
+ and EPSW_IM,d0
+ cmp EPSW_IM_7,d0 # interrupts off (exception path) ?
+ beq restore_all
+ call preempt_schedule_irq[],0
+ jmp need_resched
+#endif
+
+
+###############################################################################
+#
+# IRQ handler entry point
+# - intended to be entered at multiple priorities
+#
+###############################################################################
+ENTRY(irq_handler)
+ add -4,sp
+ SAVE_ALL
+
+ # it's not a syscall
+ mov 0xffffffff,d0
+ mov d0,(REG_ORIG_D0,fp)
+
+ mov fp,d0
+ call do_IRQ[],0 # do_IRQ(regs)
+
+ jmp ret_from_intr
+
+###############################################################################
+#
+# Monitor Signal handler entry point
+#
+###############################################################################
+ENTRY(monitor_signal)
+ movbu (0xae000001),d1
+ cmp 1,d1
+ beq monsignal
+ ret [],0
+
+monsignal:
+ or EPSW_NMID,epsw
+ mov d0,a0
+ mov a0,sp
+ mov (REG_EPSW,fp),d1
+ and ~EPSW_nSL,d1
+ mov d1,(REG_EPSW,fp)
+ movm (sp),[d2,d3,a2,a3,exreg0,exreg1,exother]
+ mov (sp),a1
+ mov a1,usp
+ movm (sp),[other]
+ add 4,sp
+here: jmp 0x8e000008-here+0x8e000008
+
+###############################################################################
+#
+# Double Fault handler entry point
+# - note that there will not be a stack, D0/A0 will hold EPSW/PC as were
+#
+###############################################################################
+ .section .bss
+ .balign THREAD_SIZE
+ .space THREAD_SIZE
+__df_stack:
+ .previous
+
+ENTRY(double_fault)
+ mov a0,(__df_stack-4) # PC as was
+ mov d0,(__df_stack-8) # EPSW as was
+ mn10300_set_dbfleds # display 'db-f' on the LEDs
+ mov 0xaa55aa55,d0
+ mov d0,(__df_stack-12) # no ORIG_D0
+ mov sp,a0 # save corrupted SP
+ mov __df_stack-12,sp # emergency supervisor stack
+ SAVE_ALL
+ mov a0,(REG_A0,fp) # save corrupted SP as A0 (which got
+ # clobbered by the CPU)
+ mov fp,d0
+ calls do_double_fault
+double_fault_loop:
+ bra double_fault_loop
+
+###############################################################################
+#
+# Bus Error handler entry point
+# - handle external (async) bus errors separately
+#
+###############################################################################
+ENTRY(raw_bus_error)
+ add -4,sp
+ mov d0,(sp)
+ mov (BCBERR),d0 # what
+ btst BCBERR_BEMR_DMA,d0 # see if it was an external bus error
+ beq __common_exception_aux # it wasn't
+
+ SAVE_ALL
+ mov (BCBEAR),d1 # destination of erroneous access
+
+ mov (REG_ORIG_D0,fp),d2
+ mov d2,(REG_D0,fp)
+ mov -1,d2
+ mov d2,(REG_ORIG_D0,fp)
+
+ add -4,sp
+ mov fp,(12,sp) # frame pointer
+ call io_bus_error[],0
+ jmp restore_all
+
+###############################################################################
+#
+# Miscellaneous exception entry points
+#
+###############################################################################
+ENTRY(nmi_handler)
+ add -4,sp
+ mov d0,(sp)
+ mov (TBR),d0
+ bra __common_exception_nonmi
+
+ENTRY(__common_exception)
+ add -4,sp
+ mov d0,(sp)
+
+__common_exception_aux:
+ mov (TBR),d0
+ and ~EPSW_NMID,epsw # turn NMIs back on if not NMI
+ or EPSW_IE,epsw
+
+__common_exception_nonmi:
+ and 0x0000FFFF,d0 # turn the exception code into a vector
+ # table index
+
+ btst 0x00000007,d0
+ bne 1f
+ cmp 0x00000400,d0
+ bge 1f
+
+ SAVE_ALL # build the stack frame
+
+ mov (REG_D0,fp),a2 # get the exception number
+ mov (REG_ORIG_D0,fp),d0
+ mov d0,(REG_D0,fp)
+ mov -1,d0
+ mov d0,(REG_ORIG_D0,fp)
+
+#ifdef CONFIG_GDBSTUB
+ btst 0x01,(gdbstub_busy)
+ beq 2f
+ and ~EPSW_IE,epsw
+ mov fp,d0
+ mov a2,d1
+ call gdbstub_exception[],0 # gdbstub itself caused an exception
+ bra restore_all
+2:
+#endif
+
+ mov fp,d0 # arg 0: stacked register file
+ mov a2,d1 # arg 1: exception number
+ lsr 1,a2
+
+ mov (exception_table,a2),a2
+ calls (a2)
+ jmp ret_from_exception
+
+1: pi # BUG() equivalent
+
+###############################################################################
+#
+# Exception handler functions table
+#
+###############################################################################
+ .data
+ENTRY(exception_table)
+ .rept 0x400>>1
+ .long uninitialised_exception
+ .endr
+ .previous
+
+###############################################################################
+#
+# Change an entry in the exception table
+# - D0 exception code, D1 handler
+#
+###############################################################################
+ENTRY(set_excp_vector)
+ lsr 1,d0
+ add exception_table,d0
+ mov d1,(d0)
+ mov 4,d1
+#if defined(CONFIG_MN10300_CACHE_WBACK)
+ jmp mn10300_dcache_flush_inv_range2
+#else
+ ret [],0
+#endif
+
+###############################################################################
+#
+# System call table
+#
+###############################################################################
+ .data
+ENTRY(sys_call_table)
+ .long sys_restart_syscall /* 0 */
+ .long sys_exit
+ .long sys_fork
+ .long sys_read
+ .long sys_write
+ .long sys_open /* 5 */
+ .long sys_close
+ .long sys_waitpid
+ .long sys_creat
+ .long sys_link
+ .long sys_unlink /* 10 */
+ .long sys_execve
+ .long sys_chdir
+ .long sys_time
+ .long sys_mknod
+ .long sys_chmod /* 15 */
+ .long sys_lchown16
+ .long sys_ni_syscall /* old break syscall holder */
+ .long sys_stat
+ .long sys_lseek
+ .long sys_getpid /* 20 */
+ .long sys_mount
+ .long sys_oldumount
+ .long sys_setuid16
+ .long sys_getuid16
+ .long sys_stime /* 25 */
+ .long sys_ptrace
+ .long sys_alarm
+ .long sys_fstat
+ .long sys_pause
+ .long sys_utime /* 30 */
+ .long sys_ni_syscall /* old stty syscall holder */
+ .long sys_ni_syscall /* old gtty syscall holder */
+ .long sys_access
+ .long sys_nice
+ .long sys_ni_syscall /* 35 - old ftime syscall holder */
+ .long sys_sync
+ .long sys_kill
+ .long sys_rename
+ .long sys_mkdir
+ .long sys_rmdir /* 40 */
+ .long sys_dup
+ .long sys_pipe
+ .long sys_times
+ .long sys_ni_syscall /* old prof syscall holder */
+ .long sys_brk /* 45 */
+ .long sys_setgid16
+ .long sys_getgid16
+ .long sys_signal
+ .long sys_geteuid16
+ .long sys_getegid16 /* 50 */
+ .long sys_acct
+ .long sys_umount /* recycled never used phys() */
+ .long sys_ni_syscall /* old lock syscall holder */
+ .long sys_ioctl
+ .long sys_fcntl /* 55 */
+ .long sys_ni_syscall /* old mpx syscall holder */
+ .long sys_setpgid
+ .long sys_ni_syscall /* old ulimit syscall holder */
+ .long sys_ni_syscall /* old sys_olduname */
+ .long sys_umask /* 60 */
+ .long sys_chroot
+ .long sys_ustat
+ .long sys_dup2
+ .long sys_getppid
+ .long sys_getpgrp /* 65 */
+ .long sys_setsid
+ .long sys_sigaction
+ .long sys_sgetmask
+ .long sys_ssetmask
+ .long sys_setreuid16 /* 70 */
+ .long sys_setregid16
+ .long sys_sigsuspend
+ .long sys_sigpending
+ .long sys_sethostname
+ .long sys_setrlimit /* 75 */
+ .long sys_old_getrlimit
+ .long sys_getrusage
+ .long sys_gettimeofday
+ .long sys_settimeofday
+ .long sys_getgroups16 /* 80 */
+ .long sys_setgroups16
+ .long old_select
+ .long sys_symlink
+ .long sys_lstat
+ .long sys_readlink /* 85 */
+ .long sys_uselib
+ .long sys_swapon
+ .long sys_reboot
+ .long old_readdir
+ .long old_mmap /* 90 */
+ .long sys_munmap
+ .long sys_truncate
+ .long sys_ftruncate
+ .long sys_fchmod
+ .long sys_fchown16 /* 95 */
+ .long sys_getpriority
+ .long sys_setpriority
+ .long sys_ni_syscall /* old profil syscall holder */
+ .long sys_statfs
+ .long sys_fstatfs /* 100 */
+ .long sys_ni_syscall /* ioperm */
+ .long sys_socketcall
+ .long sys_syslog
+ .long sys_setitimer
+ .long sys_getitimer /* 105 */
+ .long sys_newstat
+ .long sys_newlstat
+ .long sys_newfstat
+ .long sys_ni_syscall /* old sys_uname */
+ .long sys_ni_syscall /* 110 - iopl */
+ .long sys_vhangup
+ .long sys_ni_syscall /* old "idle" system call */
+ .long sys_ni_syscall /* vm86old */
+ .long sys_wait4
+ .long sys_swapoff /* 115 */
+ .long sys_sysinfo
+ .long sys_ipc
+ .long sys_fsync
+ .long sys_sigreturn
+ .long sys_clone /* 120 */
+ .long sys_setdomainname
+ .long sys_newuname
+ .long sys_ni_syscall /* modify_ldt */
+ .long sys_adjtimex
+ .long sys_mprotect /* 125 */
+ .long sys_sigprocmask
+ .long sys_ni_syscall /* old "create_module" */
+ .long sys_init_module
+ .long sys_delete_module
+ .long sys_ni_syscall /* 130: old "get_kernel_syms" */
+ .long sys_quotactl
+ .long sys_getpgid
+ .long sys_fchdir
+ .long sys_bdflush
+ .long sys_sysfs /* 135 */
+ .long sys_personality
+ .long sys_ni_syscall /* reserved for afs_syscall */
+ .long sys_setfsuid16
+ .long sys_setfsgid16
+ .long sys_llseek /* 140 */
+ .long sys_getdents
+ .long sys_select
+ .long sys_flock
+ .long sys_msync
+ .long sys_readv /* 145 */
+ .long sys_writev
+ .long sys_getsid
+ .long sys_fdatasync
+ .long sys_sysctl
+ .long sys_mlock /* 150 */
+ .long sys_munlock
+ .long sys_mlockall
+ .long sys_munlockall
+ .long sys_sched_setparam
+ .long sys_sched_getparam /* 155 */
+ .long sys_sched_setscheduler
+ .long sys_sched_getscheduler
+ .long sys_sched_yield
+ .long sys_sched_get_priority_max
+ .long sys_sched_get_priority_min /* 160 */
+ .long sys_sched_rr_get_interval
+ .long sys_nanosleep
+ .long sys_mremap
+ .long sys_setresuid16
+ .long sys_getresuid16 /* 165 */
+ .long sys_ni_syscall /* vm86 */
+ .long sys_ni_syscall /* Old sys_query_module */
+ .long sys_poll
+ .long sys_nfsservctl
+ .long sys_setresgid16 /* 170 */
+ .long sys_getresgid16
+ .long sys_prctl
+ .long sys_rt_sigreturn
+ .long sys_rt_sigaction
+ .long sys_rt_sigprocmask /* 175 */
+ .long sys_rt_sigpending
+ .long sys_rt_sigtimedwait
+ .long sys_rt_sigqueueinfo
+ .long sys_rt_sigsuspend
+ .long sys_pread64 /* 180 */
+ .long sys_pwrite64
+ .long sys_chown16
+ .long sys_getcwd
+ .long sys_capget
+ .long sys_capset /* 185 */
+ .long sys_sigaltstack
+ .long sys_sendfile
+ .long sys_ni_syscall /* reserved for streams1 */
+ .long sys_ni_syscall /* reserved for streams2 */
+ .long sys_vfork /* 190 */
+ .long sys_getrlimit
+ .long sys_mmap2
+ .long sys_truncate64
+ .long sys_ftruncate64
+ .long sys_stat64 /* 195 */
+ .long sys_lstat64
+ .long sys_fstat64
+ .long sys_lchown
+ .long sys_getuid
+ .long sys_getgid /* 200 */
+ .long sys_geteuid
+ .long sys_getegid
+ .long sys_setreuid
+ .long sys_setregid
+ .long sys_getgroups /* 205 */
+ .long sys_setgroups
+ .long sys_fchown
+ .long sys_setresuid
+ .long sys_getresuid
+ .long sys_setresgid /* 210 */
+ .long sys_getresgid
+ .long sys_chown
+ .long sys_setuid
+ .long sys_setgid
+ .long sys_setfsuid /* 215 */
+ .long sys_setfsgid
+ .long sys_pivot_root
+ .long sys_mincore
+ .long sys_madvise
+ .long sys_getdents64 /* 220 */
+ .long sys_fcntl64
+ .long sys_ni_syscall /* reserved for TUX */
+ .long sys_ni_syscall
+ .long sys_gettid
+ .long sys_readahead /* 225 */
+ .long sys_setxattr
+ .long sys_lsetxattr
+ .long sys_fsetxattr
+ .long sys_getxattr
+ .long sys_lgetxattr /* 230 */
+ .long sys_fgetxattr
+ .long sys_listxattr
+ .long sys_llistxattr
+ .long sys_flistxattr
+ .long sys_removexattr /* 235 */
+ .long sys_lremovexattr
+ .long sys_fremovexattr
+ .long sys_tkill
+ .long sys_sendfile64
+ .long sys_futex /* 240 */
+ .long sys_sched_setaffinity
+ .long sys_sched_getaffinity
+ .long sys_ni_syscall /* sys_set_thread_area */
+ .long sys_ni_syscall /* sys_get_thread_area */
+ .long sys_io_setup /* 245 */
+ .long sys_io_destroy
+ .long sys_io_getevents
+ .long sys_io_submit
+ .long sys_io_cancel
+ .long sys_fadvise64 /* 250 */
+ .long sys_ni_syscall
+ .long sys_exit_group
+ .long sys_lookup_dcookie
+ .long sys_epoll_create
+ .long sys_epoll_ctl /* 255 */
+ .long sys_epoll_wait
+ .long sys_remap_file_pages
+ .long sys_set_tid_address
+ .long sys_timer_create
+ .long sys_timer_settime /* 260 */
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun
+ .long sys_timer_delete
+ .long sys_clock_settime
+ .long sys_clock_gettime /* 265 */
+ .long sys_clock_getres
+ .long sys_clock_nanosleep
+ .long sys_statfs64
+ .long sys_fstatfs64
+ .long sys_tgkill /* 270 */
+ .long sys_utimes
+ .long sys_fadvise64_64
+ .long sys_ni_syscall /* sys_vserver */
+ .long sys_mbind
+ .long sys_get_mempolicy /* 275 */
+ .long sys_set_mempolicy
+ .long sys_mq_open
+ .long sys_mq_unlink
+ .long sys_mq_timedsend
+ .long sys_mq_timedreceive /* 280 */
+ .long sys_mq_notify
+ .long sys_mq_getsetattr
+ .long sys_kexec_load
+ .long sys_waitid
+ .long sys_ni_syscall /* 285 */ /* available */
+ .long sys_add_key
+ .long sys_request_key
+ .long sys_keyctl
+ .long sys_cacheflush
+ .long sys_ioprio_set /* 290 */
+ .long sys_ioprio_get
+ .long sys_inotify_init
+ .long sys_inotify_add_watch
+ .long sys_inotify_rm_watch
+ .long sys_migrate_pages /* 295 */
+ .long sys_openat
+ .long sys_mkdirat
+ .long sys_mknodat
+ .long sys_fchownat
+ .long sys_futimesat /* 300 */
+ .long sys_fstatat64
+ .long sys_unlinkat
+ .long sys_renameat
+ .long sys_linkat
+ .long sys_symlinkat /* 305 */
+ .long sys_readlinkat
+ .long sys_fchmodat
+ .long sys_faccessat
+ .long sys_pselect6
+ .long sys_ppoll /* 310 */
+ .long sys_unshare
+ .long sys_set_robust_list
+ .long sys_get_robust_list
+ .long sys_splice
+ .long sys_sync_file_range /* 315 */
+ .long sys_tee
+ .long sys_vmsplice
+ .long sys_move_pages
+ .long sys_getcpu
+ .long sys_epoll_pwait /* 320 */
+ .long sys_utimensat
+ .long sys_signalfd
+ .long sys_timerfd_create
+ .long sys_eventfd
+ .long sys_fallocate /* 325 */
+ .long sys_timerfd_settime
+ .long sys_timerfd_gettime
+
+
+nr_syscalls=(.-sys_call_table)/4
diff --git a/arch/mn10300/kernel/fpu-low.S b/arch/mn10300/kernel/fpu-low.S
new file mode 100644
index 00000000000..96cfd47e68d
--- /dev/null
+++ b/arch/mn10300/kernel/fpu-low.S
@@ -0,0 +1,197 @@
+/* MN10300 Low level FPU management operations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cpu-regs.h>
+
+###############################################################################
+#
+# void fpu_init_state(void)
+# - initialise the FPU
+#
+###############################################################################
+ .globl fpu_init_state
+ .type fpu_init_state,@function
+fpu_init_state:
+ mov epsw,d0
+ or EPSW_FE,epsw
+
+#ifdef CONFIG_MN10300_PROC_MN103E010
+ nop
+ nop
+ nop
+#endif
+ fmov 0,fs0
+ fmov fs0,fs1
+ fmov fs0,fs2
+ fmov fs0,fs3
+ fmov fs0,fs4
+ fmov fs0,fs5
+ fmov fs0,fs6
+ fmov fs0,fs7
+ fmov fs0,fs8
+ fmov fs0,fs9
+ fmov fs0,fs10
+ fmov fs0,fs11
+ fmov fs0,fs12
+ fmov fs0,fs13
+ fmov fs0,fs14
+ fmov fs0,fs15
+ fmov fs0,fs16
+ fmov fs0,fs17
+ fmov fs0,fs18
+ fmov fs0,fs19
+ fmov fs0,fs20
+ fmov fs0,fs21
+ fmov fs0,fs22
+ fmov fs0,fs23
+ fmov fs0,fs24
+ fmov fs0,fs25
+ fmov fs0,fs26
+ fmov fs0,fs27
+ fmov fs0,fs28
+ fmov fs0,fs29
+ fmov fs0,fs30
+ fmov fs0,fs31
+ fmov FPCR_INIT,fpcr
+
+#ifdef CONFIG_MN10300_PROC_MN103E010
+ nop
+ nop
+ nop
+#endif
+ mov d0,epsw
+ ret [],0
+
+ .size fpu_init_state,.-fpu_init_state
+
+###############################################################################
+#
+# void fpu_save(struct fpu_state_struct *)
+# - save the fpu state
+# - note that an FPU Operational exception might occur during this process
+#
+###############################################################################
+ .globl fpu_save
+ .type fpu_save,@function
+fpu_save:
+ mov epsw,d1
+ or EPSW_FE,epsw /* enable the FPU so we can access it */
+
+#ifdef CONFIG_MN10300_PROC_MN103E010
+ nop
+ nop
+#endif
+ mov d0,a0
+ fmov fs0,(a0+)
+ fmov fs1,(a0+)
+ fmov fs2,(a0+)
+ fmov fs3,(a0+)
+ fmov fs4,(a0+)
+ fmov fs5,(a0+)
+ fmov fs6,(a0+)
+ fmov fs7,(a0+)
+ fmov fs8,(a0+)
+ fmov fs9,(a0+)
+ fmov fs10,(a0+)
+ fmov fs11,(a0+)
+ fmov fs12,(a0+)
+ fmov fs13,(a0+)
+ fmov fs14,(a0+)
+ fmov fs15,(a0+)
+ fmov fs16,(a0+)
+ fmov fs17,(a0+)
+ fmov fs18,(a0+)
+ fmov fs19,(a0+)
+ fmov fs20,(a0+)
+ fmov fs21,(a0+)
+ fmov fs22,(a0+)
+ fmov fs23,(a0+)
+ fmov fs24,(a0+)
+ fmov fs25,(a0+)
+ fmov fs26,(a0+)
+ fmov fs27,(a0+)
+ fmov fs28,(a0+)
+ fmov fs29,(a0+)
+ fmov fs30,(a0+)
+ fmov fs31,(a0+)
+ fmov fpcr,d0
+ mov d0,(a0)
+#ifdef CONFIG_MN10300_PROC_MN103E010
+ nop
+ nop
+#endif
+
+ mov d1,epsw
+ ret [],0
+
+ .size fpu_save,.-fpu_save
+
+###############################################################################
+#
+# void fpu_restore(struct fpu_state_struct *)
+# - restore the fpu state
+# - note that an FPU Operational exception might occur during this process
+#
+###############################################################################
+ .globl fpu_restore
+ .type fpu_restore,@function
+fpu_restore:
+ mov epsw,d1
+ or EPSW_FE,epsw /* enable the FPU so we can access it */
+
+#ifdef CONFIG_MN10300_PROC_MN103E010
+ nop
+ nop
+#endif
+ mov d0,a0
+ fmov (a0+),fs0
+ fmov (a0+),fs1
+ fmov (a0+),fs2
+ fmov (a0+),fs3
+ fmov (a0+),fs4
+ fmov (a0+),fs5
+ fmov (a0+),fs6
+ fmov (a0+),fs7
+ fmov (a0+),fs8
+ fmov (a0+),fs9
+ fmov (a0+),fs10
+ fmov (a0+),fs11
+ fmov (a0+),fs12
+ fmov (a0+),fs13
+ fmov (a0+),fs14
+ fmov (a0+),fs15
+ fmov (a0+),fs16
+ fmov (a0+),fs17
+ fmov (a0+),fs18
+ fmov (a0+),fs19
+ fmov (a0+),fs20
+ fmov (a0+),fs21
+ fmov (a0+),fs22
+ fmov (a0+),fs23
+ fmov (a0+),fs24
+ fmov (a0+),fs25
+ fmov (a0+),fs26
+ fmov (a0+),fs27
+ fmov (a0+),fs28
+ fmov (a0+),fs29
+ fmov (a0+),fs30
+ fmov (a0+),fs31
+ mov (a0),d0
+ fmov d0,fpcr
+#ifdef CONFIG_MN10300_PROC_MN103E010
+ nop
+ nop
+ nop
+#endif
+
+ mov d1,epsw
+ ret [],0
+
+ .size fpu_restore,.-fpu_restore
diff --git a/arch/mn10300/kernel/fpu.c b/arch/mn10300/kernel/fpu.c
new file mode 100644
index 00000000000..e705f25ad5f
--- /dev/null
+++ b/arch/mn10300/kernel/fpu.c
@@ -0,0 +1,223 @@
+/* MN10300 FPU management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/uaccess.h>
+#include <asm/fpu.h>
+#include <asm/elf.h>
+#include <asm/exceptions.h>
+
+struct task_struct *fpu_state_owner;
+
+/*
+ * handle an exception due to the FPU being disabled
+ */
+asmlinkage void fpu_disabled(struct pt_regs *regs, enum exception_code code)
+{
+ struct task_struct *tsk = current;
+
+ if (!user_mode(regs))
+ die_if_no_fixup("An FPU Disabled exception happened in"
+ " kernel space\n",
+ regs, code);
+
+#ifdef CONFIG_FPU
+ preempt_disable();
+
+ /* transfer the last process's FPU state to memory */
+ if (fpu_state_owner) {
+ fpu_save(&fpu_state_owner->thread.fpu_state);
+ fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
+ }
+
+ /* the current process now owns the FPU state */
+ fpu_state_owner = tsk;
+ regs->epsw |= EPSW_FE;
+
+ /* load the FPU with the current process's FPU state or invent a new
+ * clean one if the process doesn't have one */
+ if (is_using_fpu(tsk)) {
+ fpu_restore(&tsk->thread.fpu_state);
+ } else {
+ fpu_init_state();
+ set_using_fpu(tsk);
+ }
+
+ preempt_enable();
+#else
+ {
+ siginfo_t info;
+
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_addr = (void *) tsk->thread.uregs->pc;
+ info.si_code = FPE_FLTINV;
+
+ force_sig_info(SIGFPE, &info, tsk);
+ }
+#endif /* CONFIG_FPU */
+}
+
+/*
+ * handle an FPU operational exception
+ * - there's a possibility that if the FPU is asynchronous, the signal might
+ * be meant for a process other than the current one
+ */
+asmlinkage void fpu_exception(struct pt_regs *regs, enum exception_code code)
+{
+ struct task_struct *tsk = fpu_state_owner;
+ siginfo_t info;
+
+ if (!user_mode(regs))
+ die_if_no_fixup("An FPU Operation exception happened in"
+ " kernel space\n",
+ regs, code);
+
+ if (!tsk)
+ die_if_no_fixup("An FPU Operation exception happened,"
+ " but the FPU is not in use",
+ regs, code);
+
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_addr = (void *) tsk->thread.uregs->pc;
+ info.si_code = FPE_FLTINV;
+
+#ifdef CONFIG_FPU
+ {
+ u32 fpcr;
+
+ /* get FPCR (we need to enable the FPU whilst we do this) */
+ asm volatile(" or %1,epsw \n"
+#ifdef CONFIG_MN10300_PROC_MN103E010
+ " nop \n"
+ " nop \n"
+ " nop \n"
+#endif
+ " fmov fpcr,%0 \n"
+#ifdef CONFIG_MN10300_PROC_MN103E010
+ " nop \n"
+ " nop \n"
+ " nop \n"
+#endif
+ " and %2,epsw \n"
+ : "=&d"(fpcr)
+ : "i"(EPSW_FE), "i"(~EPSW_FE)
+ );
+
+ if (fpcr & FPCR_EC_Z)
+ info.si_code = FPE_FLTDIV;
+ else if (fpcr & FPCR_EC_O)
+ info.si_code = FPE_FLTOVF;
+ else if (fpcr & FPCR_EC_U)
+ info.si_code = FPE_FLTUND;
+ else if (fpcr & FPCR_EC_I)
+ info.si_code = FPE_FLTRES;
+ }
+#endif
+
+ force_sig_info(SIGFPE, &info, tsk);
+}
+
+/*
+ * save the FPU state to a signal context
+ */
+int fpu_setup_sigcontext(struct fpucontext *fpucontext)
+{
+#ifdef CONFIG_FPU
+ struct task_struct *tsk = current;
+
+ if (!is_using_fpu(tsk))
+ return 0;
+
+ /* transfer the current FPU state to memory and cause fpu_init() to be
+ * triggered by the next attempted FPU operation by the current
+ * process.
+ */
+ preempt_disable();
+
+ if (fpu_state_owner == tsk) {
+ fpu_save(&tsk->thread.fpu_state);
+ fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
+ fpu_state_owner = NULL;
+ }
+
+ preempt_enable();
+
+ /* we no longer have a valid current FPU state */
+ clear_using_fpu(tsk);
+
+ /* transfer the saved FPU state onto the userspace stack */
+ if (copy_to_user(fpucontext,
+ &tsk->thread.fpu_state,
+ min(sizeof(struct fpu_state_struct),
+ sizeof(struct fpucontext))))
+ return -1;
+
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * kill a process's FPU state during restoration after signal handling
+ */
+void fpu_kill_state(struct task_struct *tsk)
+{
+#ifdef CONFIG_FPU
+ /* disown anything left in the FPU */
+ preempt_disable();
+
+ if (fpu_state_owner == tsk) {
+ fpu_state_owner->thread.uregs->epsw &= ~EPSW_FE;
+ fpu_state_owner = NULL;
+ }
+
+ preempt_enable();
+#endif
+ /* we no longer have a valid current FPU state */
+ clear_using_fpu(tsk);
+}
+
+/*
+ * restore the FPU state from a signal context
+ */
+int fpu_restore_sigcontext(struct fpucontext *fpucontext)
+{
+ struct task_struct *tsk = current;
+ int ret;
+
+ /* load up the old FPU state */
+ ret = copy_from_user(&tsk->thread.fpu_state,
+ fpucontext,
+ min(sizeof(struct fpu_state_struct),
+ sizeof(struct fpucontext)));
+ if (!ret)
+ set_using_fpu(tsk);
+
+ return ret;
+}
+
+/*
+ * fill in the FPU structure for a core dump
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpreg)
+{
+ struct task_struct *tsk = current;
+ int fpvalid;
+
+ fpvalid = is_using_fpu(tsk);
+ if (fpvalid) {
+ unlazy_fpu(tsk);
+ memcpy(fpreg, &tsk->thread.fpu_state, sizeof(*fpreg));
+ }
+
+ return fpvalid;
+}
diff --git a/arch/mn10300/kernel/gdb-cache.S b/arch/mn10300/kernel/gdb-cache.S
new file mode 100644
index 00000000000..1108badc3d3
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-cache.S
@@ -0,0 +1,105 @@
+###############################################################################
+#
+# MN10300 Low-level cache purging routines for gdbstub
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/cache.h>
+#include <asm/cpu-regs.h>
+#include <asm/exceptions.h>
+#include <asm/frame.inc>
+#include <asm/serial-regs.h>
+
+ .text
+
+###############################################################################
+#
+# GDB stub cache purge
+#
+###############################################################################
+ .type gdbstub_purge_cache,@function
+ENTRY(gdbstub_purge_cache)
+ #######################################################################
+ # read the addresses tagged in the cache's tag RAM and attempt to flush
+ # those addresses specifically
+ # - we rely on the hardware to filter out invalid tag entry addresses
+ mov DCACHE_TAG(0,0),a0 # dcache tag RAM access address
+ mov DCACHE_PURGE(0,0),a1 # dcache purge request address
+ mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of entries
+
+mn10300_dcache_flush_loop:
+ mov (a0),d0
+ and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
+ or L1_CACHE_TAG_VALID,d0 # retain valid entries in the
+ # cache
+ mov d0,(a1) # conditional purge
+
+mn10300_dcache_flush_skip:
+ add L1_CACHE_BYTES,a0
+ add L1_CACHE_BYTES,a1
+ add -1,d1
+ bne mn10300_dcache_flush_loop
+
+;; # unconditionally flush and invalidate the dcache
+;; mov DCACHE_PURGE(0,0),a1 # dcache purge request address
+;; mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of
+;; # entries
+;;
+;; gdbstub_purge_cache__dcache_loop:
+;; mov (a1),d0 # unconditional purge
+;;
+;; add L1_CACHE_BYTES,a1
+;; add -1,d1
+;; bne gdbstub_purge_cache__dcache_loop
+
+ #######################################################################
+ # now invalidate the icache
+ mov CHCTR,a0
+ movhu (a0),a1
+
+ mov epsw,d1
+ and ~EPSW_IE,epsw
+ nop
+ nop
+
+ # disable the icache
+ and ~CHCTR_ICEN,d0
+ movhu d0,(a0)
+
+ # and wait for it to calm down
+ setlb
+ movhu (a0),d0
+ btst CHCTR_ICBUSY,d0
+ lne
+
+ # invalidate
+ or CHCTR_ICINV,d0
+ movhu d0,(a0)
+
+ # wait for the cache to finish
+ mov CHCTR,a0
+ setlb
+ movhu (a0),d0
+ btst CHCTR_ICBUSY,d0
+ lne
+
+ # and reenable it
+ movhu a1,(a0)
+ movhu (a0),d0 # read back to flush
+ # (SIGILLs all over without this)
+
+ mov d1,epsw
+
+ ret [],0
+
+ .size gdbstub_purge_cache,.-gdbstub_purge_cache
diff --git a/arch/mn10300/kernel/gdb-io-serial-low.S b/arch/mn10300/kernel/gdb-io-serial-low.S
new file mode 100644
index 00000000000..c68dcd05220
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-serial-low.S
@@ -0,0 +1,90 @@
+###############################################################################
+#
+# 16550 serial Rx interrupt handler for gdbstub I/O
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/cpu-regs.h>
+#include <asm/thread_info.h>
+#include <asm/frame.inc>
+#include <asm/intctl-regs.h>
+#include <asm/unit/serial.h>
+
+ .text
+
+###############################################################################
+#
+# GDB stub serial receive interrupt entry point
+# - intended to run at interrupt priority 0
+#
+###############################################################################
+ .globl gdbstub_io_rx_handler
+ .type gdbstub_io_rx_handler,@function
+gdbstub_io_rx_handler:
+ movm [d2,d3,a2,a3],(sp)
+
+#if 1
+ movbu (GDBPORT_SERIAL_IIR),d2
+#endif
+
+ mov (gdbstub_rx_inp),a3
+gdbstub_io_rx_more:
+ mov a3,a2
+ add 2,a3
+ and 0x00000fff,a3
+ mov (gdbstub_rx_outp),d3
+ cmp a3,d3
+ beq gdbstub_io_rx_overflow
+
+ movbu (GDBPORT_SERIAL_LSR),d3
+ btst UART_LSR_DR,d3
+ beq gdbstub_io_rx_done
+ movbu (GDBPORT_SERIAL_RX),d2
+ movbu d3,(gdbstub_rx_buffer+1,a2)
+ movbu d2,(gdbstub_rx_buffer,a2)
+ mov a3,(gdbstub_rx_inp)
+ bra gdbstub_io_rx_more
+
+gdbstub_io_rx_done:
+ mov GxICR_DETECT,d2
+ movbu d2,(XIRQxICR(GDBPORT_SERIAL_IRQ)) # ACK the interrupt
+ movhu (XIRQxICR(GDBPORT_SERIAL_IRQ)),d2 # flush
+ movm (sp),[d2,d3,a2,a3]
+ bset 0x01,(gdbstub_busy)
+ beq gdbstub_io_rx_enter
+ rti
+
+gdbstub_io_rx_overflow:
+ bset 0x01,(gdbstub_rx_overflow)
+ bra gdbstub_io_rx_done
+
+gdbstub_io_rx_enter:
+ or EPSW_IE|EPSW_IM_1,epsw
+ add -4,sp
+ SAVE_ALL
+
+ mov 0xffffffff,d0
+ mov d0,(REG_ORIG_D0,fp)
+ mov 0x280,d1
+
+ mov fp,d0
+ call gdbstub_rx_irq[],0 # gdbstub_rx_irq(regs,excep)
+
+ and ~EPSW_IE,epsw
+ bclr 0x01,(gdbstub_busy)
+
+ .globl gdbstub_return
+gdbstub_return:
+ RESTORE_ALL
+
+ .size gdbstub_io_rx_handler,.-gdbstub_io_rx_handler
diff --git a/arch/mn10300/kernel/gdb-io-serial.c b/arch/mn10300/kernel/gdb-io-serial.c
new file mode 100644
index 00000000000..9a6d4e8ebe7
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-serial.c
@@ -0,0 +1,155 @@
+/* 16550 serial driver for gdbstub I/O
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/nmi.h>
+
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/gdb-stub.h>
+#include <asm/exceptions.h>
+#include <asm/serial-regs.h>
+#include <asm/unit/serial.h>
+
+/*
+ * initialise the GDB stub
+ */
+void gdbstub_io_init(void)
+{
+ u16 tmp;
+
+ /* set up the serial port */
+ GDBPORT_SERIAL_LCR = UART_LCR_WLEN8; /* 1N8 */
+ GDBPORT_SERIAL_FCR = (UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
+ UART_FCR_CLEAR_XMIT);
+
+ FLOWCTL_CLEAR(DTR);
+ FLOWCTL_SET(RTS);
+
+ gdbstub_io_set_baud(115200);
+
+ /* we want to get serial receive interrupts */
+ XIRQxICR(GDBPORT_SERIAL_IRQ) = 0;
+ tmp = XIRQxICR(GDBPORT_SERIAL_IRQ);
+
+ IVAR0 = EXCEP_IRQ_LEVEL0;
+ set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler);
+
+ XIRQxICR(GDBPORT_SERIAL_IRQ) &= ~GxICR_REQUEST;
+ XIRQxICR(GDBPORT_SERIAL_IRQ) = GxICR_ENABLE | GxICR_LEVEL_0;
+ tmp = XIRQxICR(GDBPORT_SERIAL_IRQ);
+
+ GDBPORT_SERIAL_IER = UART_IER_RDI | UART_IER_RLSI;
+
+ /* permit level 0 IRQs to take place */
+ asm volatile(
+ " and %0,epsw \n"
+ " or %1,epsw \n"
+ :
+ : "i"(~EPSW_IM), "i"(EPSW_IE | EPSW_IM_1)
+ );
+}
+
+/*
+ * set up the GDB stub serial port baud rate timers
+ */
+void gdbstub_io_set_baud(unsigned baud)
+{
+ unsigned value;
+ u8 lcr;
+
+ value = 18432000 / 16 / baud;
+
+ lcr = GDBPORT_SERIAL_LCR;
+ GDBPORT_SERIAL_LCR |= UART_LCR_DLAB;
+ GDBPORT_SERIAL_DLL = value & 0xff;
+ GDBPORT_SERIAL_DLM = (value >> 8) & 0xff;
+ GDBPORT_SERIAL_LCR = lcr;
+}
+
+/*
+ * wait for a character to come from the debugger
+ */
+int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
+{
+ unsigned ix;
+ u8 ch, st;
+
+ *_ch = 0xff;
+
+ if (gdbstub_rx_unget) {
+ *_ch = gdbstub_rx_unget;
+ gdbstub_rx_unget = 0;
+ return 0;
+ }
+
+ try_again:
+ /* pull chars out of the buffer */
+ ix = gdbstub_rx_outp;
+ if (ix == gdbstub_rx_inp) {
+ if (nonblock)
+ return -EAGAIN;
+#ifdef CONFIG_MN10300_WD_TIMER
+ watchdog_alert_counter = 0;
+#endif /* CONFIG_MN10300_WD_TIMER */
+ goto try_again;
+ }
+
+ ch = gdbstub_rx_buffer[ix++];
+ st = gdbstub_rx_buffer[ix++];
+ gdbstub_rx_outp = ix & 0x00000fff;
+
+ if (st & UART_LSR_BI) {
+ gdbstub_proto("### GDB Rx Break Detected ###\n");
+ return -EINTR;
+ } else if (st & (UART_LSR_FE | UART_LSR_OE | UART_LSR_PE)) {
+ gdbstub_proto("### GDB Rx Error (st=%02x) ###\n", st);
+ return -EIO;
+ } else {
+ gdbstub_proto("### GDB Rx %02x (st=%02x) ###\n", ch, st);
+ *_ch = ch & 0x7f;
+ return 0;
+ }
+}
+
+/*
+ * send a character to the debugger
+ */
+void gdbstub_io_tx_char(unsigned char ch)
+{
+ FLOWCTL_SET(DTR);
+ LSR_WAIT_FOR(THRE);
+ /* FLOWCTL_WAIT_FOR(CTS); */
+
+ if (ch == 0x0a) {
+ GDBPORT_SERIAL_TX = 0x0d;
+ LSR_WAIT_FOR(THRE);
+ /* FLOWCTL_WAIT_FOR(CTS); */
+ }
+ GDBPORT_SERIAL_TX = ch;
+
+ FLOWCTL_CLEAR(DTR);
+}
+
+/*
+ * send a character to the debugger
+ */
+void gdbstub_io_tx_flush(void)
+{
+ LSR_WAIT_FOR(TEMT);
+ LSR_WAIT_FOR(THRE);
+ FLOWCTL_CLEAR(DTR);
+}
diff --git a/arch/mn10300/kernel/gdb-io-ttysm-low.S b/arch/mn10300/kernel/gdb-io-ttysm-low.S
new file mode 100644
index 00000000000..677c7876307
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-ttysm-low.S
@@ -0,0 +1,93 @@
+###############################################################################
+#
+# MN10300 On-chip serial Rx interrupt handler for GDB stub I/O
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/thread_info.h>
+#include <asm/cpu-regs.h>
+#include <asm/frame.inc>
+#include <asm/intctl-regs.h>
+#include <asm/unit/serial.h>
+#include "mn10300-serial.h"
+
+ .text
+
+###############################################################################
+#
+# GDB stub serial receive interrupt entry point
+# - intended to run at interrupt priority 0
+#
+###############################################################################
+ .globl gdbstub_io_rx_handler
+ .type gdbstub_io_rx_handler,@function
+gdbstub_io_rx_handler:
+ movm [d2,d3,a2,a3],(sp)
+
+ mov (gdbstub_rx_inp),a3
+gdbstub_io_rx_more:
+ mov a3,a2
+ add 2,a3
+ and PAGE_SIZE_asm-1,a3
+ mov (gdbstub_rx_outp),d3
+ cmp a3,d3
+ beq gdbstub_io_rx_overflow
+
+ movbu (SCgSTR),d3
+ btst SC01STR_RBF,d3
+ beq gdbstub_io_rx_done
+ movbu (SCgRXB),d2
+ movbu d3,(gdbstub_rx_buffer+1,a2)
+ movbu d2,(gdbstub_rx_buffer,a2)
+ mov a3,(gdbstub_rx_inp)
+ bra gdbstub_io_rx_more
+
+gdbstub_io_rx_done:
+ mov GxICR_DETECT,d2
+ movbu d2,(GxICR(SCgRXIRQ)) # ACK the interrupt
+ movhu (GxICR(SCgRXIRQ)),d2 # flush
+
+ movm (sp),[d2,d3,a2,a3]
+ bset 0x01,(gdbstub_busy)
+ beq gdbstub_io_rx_enter
+ rti
+
+gdbstub_io_rx_overflow:
+ bset 0x01,(gdbstub_rx_overflow)
+ bra gdbstub_io_rx_done
+
+###############################################################################
+#
+# debugging interrupt - enter the GDB stub proper
+#
+###############################################################################
+gdbstub_io_rx_enter:
+ or EPSW_IE|EPSW_IM_1,epsw
+ add -4,sp
+ SAVE_ALL
+
+ mov 0xffffffff,d0
+ mov d0,(REG_ORIG_D0,fp)
+ mov 0x280,d1
+
+ mov fp,d0
+ call gdbstub_rx_irq[],0 # gdbstub_io_rx_irq(regs,excep)
+
+ and ~EPSW_IE,epsw
+ bclr 0x01,(gdbstub_busy)
+
+ .globl gdbstub_return
+gdbstub_return:
+ RESTORE_ALL
+
+ .size gdbstub_io_rx_handler,.-gdbstub_io_rx_handler
diff --git a/arch/mn10300/kernel/gdb-io-ttysm.c b/arch/mn10300/kernel/gdb-io-ttysm.c
new file mode 100644
index 00000000000..c5451592d40
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-io-ttysm.c
@@ -0,0 +1,299 @@
+/* MN10300 On-chip serial driver for gdbstub I/O
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/gdb-stub.h>
+#include <asm/exceptions.h>
+#include <asm/unit/clock.h>
+#include "mn10300-serial.h"
+
+#if defined(CONFIG_GDBSTUB_ON_TTYSM0)
+struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif0;
+#elif defined(CONFIG_GDBSTUB_ON_TTYSM1)
+struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif1;
+#else
+struct mn10300_serial_port *const gdbstub_port = &mn10300_serial_port_sif2;
+#endif
+
+
+/*
+ * initialise the GDB stub I/O routines
+ */
+void __init gdbstub_io_init(void)
+{
+ uint16_t scxctr;
+ int tmp;
+
+ switch (gdbstub_port->clock_src) {
+ case MNSCx_CLOCK_SRC_IOCLK:
+ gdbstub_port->ioclk = MN10300_IOCLK;
+ break;
+
+#ifdef MN10300_IOBCLK
+ case MNSCx_CLOCK_SRC_IOBCLK:
+ gdbstub_port->ioclk = MN10300_IOBCLK;
+ break;
+#endif
+ default:
+ BUG();
+ }
+
+ /* set up the serial port */
+ gdbstub_io_set_baud(115200);
+
+ /* we want to get serial receive interrupts */
+ set_intr_level(gdbstub_port->rx_irq, GxICR_LEVEL_0);
+ set_intr_level(gdbstub_port->tx_irq, GxICR_LEVEL_0);
+ set_intr_stub(EXCEP_IRQ_LEVEL0, gdbstub_io_rx_handler);
+
+ *gdbstub_port->rx_icr |= GxICR_ENABLE;
+ tmp = *gdbstub_port->rx_icr;
+
+ /* enable the device */
+ scxctr = SC01CTR_CLN_8BIT; /* 1N8 */
+ switch (gdbstub_port->div_timer) {
+ case MNSCx_DIV_TIMER_16BIT:
+ scxctr |= SC0CTR_CK_TM8UFLOW_8; /* == SC1CTR_CK_TM9UFLOW_8
+ == SC2CTR_CK_TM10UFLOW_8 */
+ break;
+
+ case MNSCx_DIV_TIMER_8BIT:
+ scxctr |= SC0CTR_CK_TM2UFLOW_8;
+ break;
+ }
+
+ scxctr |= SC01CTR_TXE | SC01CTR_RXE;
+
+ *gdbstub_port->_control = scxctr;
+ tmp = *gdbstub_port->_control;
+
+ /* permit level 0 IRQs only */
+ asm volatile(
+ " and %0,epsw \n"
+ " or %1,epsw \n"
+ :
+ : "i"(~EPSW_IM), "i"(EPSW_IE|EPSW_IM_1)
+ );
+}
+
+/*
+ * set up the GDB stub serial port baud rate timers
+ */
+void gdbstub_io_set_baud(unsigned baud)
+{
+ const unsigned bits = 10; /* 1 [start] + 8 [data] + 0 [parity] +
+ * 1 [stop] */
+ unsigned long ioclk = gdbstub_port->ioclk;
+ unsigned xdiv, tmp;
+ uint16_t tmxbr;
+ uint8_t tmxmd;
+
+ if (!baud) {
+ baud = 9600;
+ } else if (baud == 134) {
+ baud = 269; /* 134 is really 134.5 */
+ xdiv = 2;
+ }
+
+try_alternative:
+ xdiv = 1;
+
+ switch (gdbstub_port->div_timer) {
+ case MNSCx_DIV_TIMER_16BIT:
+ tmxmd = TM8MD_SRC_IOCLK;
+ tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 65535)
+ goto timer_okay;
+
+ tmxmd = TM8MD_SRC_IOCLK_8;
+ tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 65535)
+ goto timer_okay;
+
+ tmxmd = TM8MD_SRC_IOCLK_32;
+ tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 65535)
+ goto timer_okay;
+
+ break;
+
+ case MNSCx_DIV_TIMER_8BIT:
+ tmxmd = TM2MD_SRC_IOCLK;
+ tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 255)
+ goto timer_okay;
+
+ tmxmd = TM2MD_SRC_IOCLK_8;
+ tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 255)
+ goto timer_okay;
+
+ tmxmd = TM2MD_SRC_IOCLK_32;
+ tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 255)
+ goto timer_okay;
+ break;
+ }
+
+ /* as a last resort, if the quotient is zero, default to 9600 bps */
+ baud = 9600;
+ goto try_alternative;
+
+timer_okay:
+ gdbstub_port->uart.timeout = (2 * bits * HZ) / baud;
+ gdbstub_port->uart.timeout += HZ / 50;
+
+ /* set the timer to produce the required baud rate */
+ switch (gdbstub_port->div_timer) {
+ case MNSCx_DIV_TIMER_16BIT:
+ *gdbstub_port->_tmxmd = 0;
+ *gdbstub_port->_tmxbr = tmxbr;
+ *gdbstub_port->_tmxmd = TM8MD_INIT_COUNTER;
+ *gdbstub_port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE;
+ break;
+
+ case MNSCx_DIV_TIMER_8BIT:
+ *gdbstub_port->_tmxmd = 0;
+ *(volatile u8 *) gdbstub_port->_tmxbr = (u8)tmxbr;
+ *gdbstub_port->_tmxmd = TM2MD_INIT_COUNTER;
+ *gdbstub_port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE;
+ break;
+ }
+}
+
+/*
+ * wait for a character to come from the debugger
+ */
+int gdbstub_io_rx_char(unsigned char *_ch, int nonblock)
+{
+ unsigned ix;
+ u8 ch, st;
+
+ *_ch = 0xff;
+
+ if (gdbstub_rx_unget) {
+ *_ch = gdbstub_rx_unget;
+ gdbstub_rx_unget = 0;
+ return 0;
+ }
+
+try_again:
+ /* pull chars out of the buffer */
+ ix = gdbstub_rx_outp;
+ if (ix == gdbstub_rx_inp) {
+ if (nonblock)
+ return -EAGAIN;
+#ifdef CONFIG_MN10300_WD_TIMER
+ watchdog_alert_counter = 0;
+#endif /* CONFIG_MN10300_WD_TIMER */
+ goto try_again;
+ }
+
+ ch = gdbstub_rx_buffer[ix++];
+ st = gdbstub_rx_buffer[ix++];
+ gdbstub_rx_outp = ix & (PAGE_SIZE - 1);
+
+ st &= SC01STR_RXF | SC01STR_RBF | SC01STR_FEF | SC01STR_PEF |
+ SC01STR_OEF;
+
+ /* deal with what we've got
+ * - note that the UART doesn't do BREAK-detection for us
+ */
+ if (st & SC01STR_FEF && ch == 0) {
+ switch (gdbstub_port->rx_brk) {
+ case 0: gdbstub_port->rx_brk = 1; goto try_again;
+ case 1: gdbstub_port->rx_brk = 2; goto try_again;
+ case 2:
+ gdbstub_port->rx_brk = 3;
+ gdbstub_proto("### GDB MNSERIAL Rx Break Detected"
+ " ###\n");
+ return -EINTR;
+ default:
+ goto try_again;
+ }
+ } else if (st & SC01STR_FEF) {
+ if (gdbstub_port->rx_brk)
+ goto try_again;
+
+ gdbstub_proto("### GDB MNSERIAL Framing Error ###\n");
+ return -EIO;
+ } else if (st & SC01STR_OEF) {
+ if (gdbstub_port->rx_brk)
+ goto try_again;
+
+ gdbstub_proto("### GDB MNSERIAL Overrun Error ###\n");
+ return -EIO;
+ } else if (st & SC01STR_PEF) {
+ if (gdbstub_port->rx_brk)
+ goto try_again;
+
+ gdbstub_proto("### GDB MNSERIAL Parity Error ###\n");
+ return -EIO;
+ } else {
+ /* look for the tail-end char on a break run */
+ if (gdbstub_port->rx_brk == 3) {
+ switch (ch) {
+ case 0xFF:
+ case 0xFE:
+ case 0xFC:
+ case 0xF8:
+ case 0xF0:
+ case 0xE0:
+ case 0xC0:
+ case 0x80:
+ case 0x00:
+ gdbstub_port->rx_brk = 0;
+ goto try_again;
+ default:
+ break;
+ }
+ }
+
+ gdbstub_port->rx_brk = 0;
+ gdbstub_io("### GDB Rx %02x (st=%02x) ###\n", ch, st);
+ *_ch = ch & 0x7f;
+ return 0;
+ }
+}
+
+/*
+ * send a character to the debugger
+ */
+void gdbstub_io_tx_char(unsigned char ch)
+{
+ while (*gdbstub_port->_status & SC01STR_TBF)
+ continue;
+
+ if (ch == 0x0a) {
+ *(u8 *) gdbstub_port->_txb = 0x0d;
+ while (*gdbstub_port->_status & SC01STR_TBF)
+ continue;
+ }
+
+ *(u8 *) gdbstub_port->_txb = ch;
+}
+
+/*
+ * flush the transmission buffers
+ */
+void gdbstub_io_tx_flush(void)
+{
+ while (*gdbstub_port->_status & (SC01STR_TBF | SC01STR_TXF))
+ continue;
+}
diff --git a/arch/mn10300/kernel/gdb-low.S b/arch/mn10300/kernel/gdb-low.S
new file mode 100644
index 00000000000..e2725552cd8
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-low.S
@@ -0,0 +1,115 @@
+###############################################################################
+#
+# MN10300 Low-level gdbstub routines
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/cache.h>
+#include <asm/cpu-regs.h>
+#include <asm/exceptions.h>
+#include <asm/frame.inc>
+#include <asm/serial-regs.h>
+
+ .text
+
+###############################################################################
+#
+# GDB stub read memory with guard
+# - D0 holds the memory address to read
+# - D1 holds the address to store the byte into
+#
+###############################################################################
+ .globl gdbstub_read_byte_guard
+ .globl gdbstub_read_byte_cont
+ENTRY(gdbstub_read_byte)
+ mov d0,a0
+ mov d1,a1
+ clr d0
+gdbstub_read_byte_guard:
+ movbu (a0),d1
+gdbstub_read_byte_cont:
+ movbu d1,(a1)
+ ret [],0
+
+ .globl gdbstub_read_word_guard
+ .globl gdbstub_read_word_cont
+ENTRY(gdbstub_read_word)
+ mov d0,a0
+ mov d1,a1
+ clr d0
+gdbstub_read_word_guard:
+ movhu (a0),d1
+gdbstub_read_word_cont:
+ movhu d1,(a1)
+ ret [],0
+
+ .globl gdbstub_read_dword_guard
+ .globl gdbstub_read_dword_cont
+ENTRY(gdbstub_read_dword)
+ mov d0,a0
+ mov d1,a1
+ clr d0
+gdbstub_read_dword_guard:
+ mov (a0),d1
+gdbstub_read_dword_cont:
+ mov d1,(a1)
+ ret [],0
+
+###############################################################################
+#
+# GDB stub write memory with guard
+# - D0 holds the byte to store
+# - D1 holds the memory address to write
+#
+###############################################################################
+ .globl gdbstub_write_byte_guard
+ .globl gdbstub_write_byte_cont
+ENTRY(gdbstub_write_byte)
+ mov d0,a0
+ mov d1,a1
+ clr d0
+gdbstub_write_byte_guard:
+ movbu a0,(a1)
+gdbstub_write_byte_cont:
+ ret [],0
+
+ .globl gdbstub_write_word_guard
+ .globl gdbstub_write_word_cont
+ENTRY(gdbstub_write_word)
+ mov d0,a0
+ mov d1,a1
+ clr d0
+gdbstub_write_word_guard:
+ movhu a0,(a1)
+gdbstub_write_word_cont:
+ ret [],0
+
+ .globl gdbstub_write_dword_guard
+ .globl gdbstub_write_dword_cont
+ENTRY(gdbstub_write_dword)
+ mov d0,a0
+ mov d1,a1
+ clr d0
+gdbstub_write_dword_guard:
+ mov a0,(a1)
+gdbstub_write_dword_cont:
+ ret [],0
+
+###############################################################################
+#
+# GDB stub BUG() trap
+#
+###############################################################################
+ENTRY(__gdbstub_bug_trap)
+ .byte 0xF7,0xF7 # don't use 0xFF as the JTAG unit preempts that
+ ret [],0
diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c
new file mode 100644
index 00000000000..21891c71d54
--- /dev/null
+++ b/arch/mn10300/kernel/gdb-stub.c
@@ -0,0 +1,1947 @@
+/* MN10300 GDB stub
+ *
+ * Originally written by Glenn Engel, Lake Stevens Instrument Division
+ *
+ * Contributed by HP Systems
+ *
+ * Modified for SPARC by Stu Grossman, Cygnus Support.
+ *
+ * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
+ * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
+ *
+ * Copyright (C) 1995 Andreas Busse
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified for Linux/mn10300 by David Howells <dhowells@redhat.com>
+ */
+
+/*
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a BREAK instruction.
+ *
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
+ * baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ *
+ * ==============
+ * MORE EXAMPLES:
+ * ==============
+ *
+ * For reference -- the following are the steps that one
+ * company took (RidgeRun Inc) to get remote gdb debugging
+ * going. In this scenario the host machine was a PC and the
+ * target platform was a Galileo EVB64120A MIPS evaluation
+ * board.
+ *
+ * Step 1:
+ * First download gdb-5.0.tar.gz from the internet.
+ * and then build/install the package.
+ *
+ * Example:
+ * $ tar zxf gdb-5.0.tar.gz
+ * $ cd gdb-5.0
+ * $ ./configure --target=am33_2.0-linux-gnu
+ * $ make
+ * $ install
+ * am33_2.0-linux-gnu-gdb
+ *
+ * Step 2:
+ * Configure linux for remote debugging and build it.
+ *
+ * Example:
+ * $ cd ~/linux
+ * $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
+ * $ make dep; make vmlinux
+ *
+ * Step 3:
+ * Download the kernel to the remote target and start
+ * the kernel running. It will promptly halt and wait
+ * for the host gdb session to connect. It does this
+ * since the "Kernel Hacking" option has defined
+ * CONFIG_REMOTE_DEBUG which in turn enables your calls
+ * to:
+ * set_debug_traps();
+ * breakpoint();
+ *
+ * Step 4:
+ * Start the gdb session on the host.
+ *
+ * Example:
+ * $ am33_2.0-linux-gnu-gdb vmlinux
+ * (gdb) set remotebaud 115200
+ * (gdb) target remote /dev/ttyS1
+ * ...at this point you are connected to
+ * the remote target and can use gdb
+ * in the normal fasion. Setting
+ * breakpoints, single stepping,
+ * printing variables, etc.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/bug.h>
+
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/gdb-stub.h>
+#include <asm/exceptions.h>
+#include <asm/cacheflush.h>
+#include <asm/serial-regs.h>
+#include <asm/busctl-regs.h>
+#include <asm/unit/leds.h>
+#include <asm/unit/serial.h>
+
+/* define to use F7F7 rather than FF which is subverted by JTAG debugger */
+#undef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+ * at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 2048
+
+static const char gdbstub_banner[] =
+ "Linux/MN10300 GDB Stub (c) RedHat 2007\n";
+
+u8 gdbstub_rx_buffer[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
+u32 gdbstub_rx_inp;
+u32 gdbstub_rx_outp;
+u8 gdbstub_busy;
+u8 gdbstub_rx_overflow;
+u8 gdbstub_rx_unget;
+
+static u8 gdbstub_flush_caches;
+static char input_buffer[BUFMAX];
+static char output_buffer[BUFMAX];
+static char trans_buffer[BUFMAX];
+
+static const char hexchars[] = "0123456789abcdef";
+
+struct gdbstub_bkpt {
+ u8 *addr; /* address of breakpoint */
+ u8 len; /* size of breakpoint */
+ u8 origbytes[7]; /* original bytes */
+};
+
+static struct gdbstub_bkpt gdbstub_bkpts[256];
+
+/*
+ * local prototypes
+ */
+static void getpacket(char *buffer);
+static int putpacket(char *buffer);
+static int computeSignal(enum exception_code excep);
+static int hex(unsigned char ch);
+static int hexToInt(char **ptr, int *intValue);
+static unsigned char *mem2hex(const void *mem, char *buf, int count,
+ int may_fault);
+static const char *hex2mem(const char *buf, void *_mem, int count,
+ int may_fault);
+
+/*
+ * Convert ch from a hex digit to an int
+ */
+static int hex(unsigned char ch)
+{
+ if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ return -1;
+}
+
+#ifdef CONFIG_GDBSTUB_DEBUGGING
+
+void debug_to_serial(const char *p, int n)
+{
+ __debug_to_serial(p, n);
+ /* gdbstub_console_write(NULL, p, n); */
+}
+
+void gdbstub_printk(const char *fmt, ...)
+{
+ va_list args;
+ int len;
+
+ /* Emit the output into the temporary buffer */
+ va_start(args, fmt);
+ len = vsnprintf(trans_buffer, sizeof(trans_buffer), fmt, args);
+ va_end(args);
+ debug_to_serial(trans_buffer, len);
+}
+
+#endif
+
+static inline char *gdbstub_strcpy(char *dst, const char *src)
+{
+ int loop = 0;
+ while ((dst[loop] = src[loop]))
+ loop++;
+ return dst;
+}
+
+/*
+ * scan for the sequence $<data>#<checksum>
+ */
+static void getpacket(char *buffer)
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ unsigned char ch;
+ int count, i, ret, error;
+
+ for (;;) {
+ /*
+ * wait around for the start character,
+ * ignore all other characters
+ */
+ do {
+ gdbstub_io_rx_char(&ch, 0);
+ } while (ch != '$');
+
+ checksum = 0;
+ xmitcsum = -1;
+ count = 0;
+ error = 0;
+
+ /*
+ * now, read until a # or end of buffer is found
+ */
+ while (count < BUFMAX) {
+ ret = gdbstub_io_rx_char(&ch, 0);
+ if (ret < 0)
+ error = ret;
+
+ if (ch == '#')
+ break;
+ checksum += ch;
+ buffer[count] = ch;
+ count++;
+ }
+
+ if (error == -EIO) {
+ gdbstub_proto("### GDB Rx Error - Skipping packet"
+ " ###\n");
+ gdbstub_proto("### GDB Tx NAK\n");
+ gdbstub_io_tx_char('-');
+ continue;
+ }
+
+ if (count >= BUFMAX || error)
+ continue;
+
+ buffer[count] = 0;
+
+ /* read the checksum */
+ ret = gdbstub_io_rx_char(&ch, 0);
+ if (ret < 0)
+ error = ret;
+ xmitcsum = hex(ch) << 4;
+
+ ret = gdbstub_io_rx_char(&ch, 0);
+ if (ret < 0)
+ error = ret;
+ xmitcsum |= hex(ch);
+
+ if (error) {
+ if (error == -EIO)
+ gdbstub_io("### GDB Rx Error -"
+ " Skipping packet\n");
+ gdbstub_io("### GDB Tx NAK\n");
+ gdbstub_io_tx_char('-');
+ continue;
+ }
+
+ /* check the checksum */
+ if (checksum != xmitcsum) {
+ gdbstub_io("### GDB Tx NAK\n");
+ gdbstub_io_tx_char('-'); /* failed checksum */
+ continue;
+ }
+
+ gdbstub_proto("### GDB Rx '$%s#%02x' ###\n", buffer, checksum);
+ gdbstub_io("### GDB Tx ACK\n");
+ gdbstub_io_tx_char('+'); /* successful transfer */
+
+ /*
+ * if a sequence char is present,
+ * reply the sequence ID
+ */
+ if (buffer[2] == ':') {
+ gdbstub_io_tx_char(buffer[0]);
+ gdbstub_io_tx_char(buffer[1]);
+
+ /*
+ * remove sequence chars from buffer
+ */
+ count = 0;
+ while (buffer[count])
+ count++;
+ for (i = 3; i <= count; i++)
+ buffer[i - 3] = buffer[i];
+ }
+
+ break;
+ }
+}
+
+/*
+ * send the packet in buffer.
+ * - return 0 if successfully ACK'd
+ * - return 1 if abandoned due to new incoming packet
+ */
+static int putpacket(char *buffer)
+{
+ unsigned char checksum;
+ unsigned char ch;
+ int count;
+
+ /*
+ * $<packet info>#<checksum>.
+ */
+ gdbstub_proto("### GDB Tx $'%s'#?? ###\n", buffer);
+
+ do {
+ gdbstub_io_tx_char('$');
+ checksum = 0;
+ count = 0;
+
+ while ((ch = buffer[count]) != 0) {
+ gdbstub_io_tx_char(ch);
+ checksum += ch;
+ count += 1;
+ }
+
+ gdbstub_io_tx_char('#');
+ gdbstub_io_tx_char(hexchars[checksum >> 4]);
+ gdbstub_io_tx_char(hexchars[checksum & 0xf]);
+
+ } while (gdbstub_io_rx_char(&ch, 0),
+ ch == '-' && (gdbstub_io("### GDB Rx NAK\n"), 0),
+ ch != '-' && ch != '+' &&
+ (gdbstub_io("### GDB Rx ??? %02x\n", ch), 0),
+ ch != '+' && ch != '$');
+
+ if (ch == '+') {
+ gdbstub_io("### GDB Rx ACK\n");
+ return 0;
+ }
+
+ gdbstub_io("### GDB Tx Abandoned\n");
+ gdbstub_rx_unget = ch;
+ return 1;
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+static int hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr) {
+ hexValue = hex(**ptr);
+ if (hexValue < 0)
+ break;
+
+ *intValue = (*intValue << 4) | hexValue;
+ numChars++;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+/*
+ * We single-step by setting breakpoints. When an exception
+ * is handled, we need to restore the instructions hoisted
+ * when the breakpoints were set.
+ *
+ * This is where we save the original instructions.
+ */
+static struct gdb_bp_save {
+ u8 *addr;
+ u8 opcode[2];
+} step_bp[2];
+
+static const unsigned char gdbstub_insn_sizes[256] =
+{
+ /* 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, /* 0 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */
+ 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, /* 2 */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, /* 3 */
+ 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, /* 4 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, /* 5 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
+ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 8 */
+ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 9 */
+ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* a */
+ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* b */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, /* c */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
+ 0, 2, 2, 2, 2, 2, 2, 4, 0, 3, 0, 4, 0, 6, 7, 1 /* f */
+};
+
+static int __gdbstub_mark_bp(u8 *addr, int ix)
+{
+ if (addr < (u8 *) 0x70000000UL)
+ return 0;
+ /* 70000000-7fffffff: vmalloc area */
+ if (addr < (u8 *) 0x80000000UL)
+ goto okay;
+ if (addr < (u8 *) 0x8c000000UL)
+ return 0;
+ /* 8c000000-93ffffff: SRAM, SDRAM */
+ if (addr < (u8 *) 0x94000000UL)
+ goto okay;
+ return 0;
+
+okay:
+ if (gdbstub_read_byte(addr + 0, &step_bp[ix].opcode[0]) < 0 ||
+ gdbstub_read_byte(addr + 1, &step_bp[ix].opcode[1]) < 0)
+ return 0;
+
+ step_bp[ix].addr = addr;
+ return 1;
+}
+
+static inline void __gdbstub_restore_bp(void)
+{
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+ if (step_bp[0].addr) {
+ gdbstub_write_byte(step_bp[0].opcode[0], step_bp[0].addr + 0);
+ gdbstub_write_byte(step_bp[0].opcode[1], step_bp[0].addr + 1);
+ }
+ if (step_bp[1].addr) {
+ gdbstub_write_byte(step_bp[1].opcode[0], step_bp[1].addr + 0);
+ gdbstub_write_byte(step_bp[1].opcode[1], step_bp[1].addr + 1);
+ }
+#else
+ if (step_bp[0].addr)
+ gdbstub_write_byte(step_bp[0].opcode[0], step_bp[0].addr + 0);
+ if (step_bp[1].addr)
+ gdbstub_write_byte(step_bp[1].opcode[0], step_bp[1].addr + 0);
+#endif
+
+ gdbstub_flush_caches = 1;
+
+ step_bp[0].addr = NULL;
+ step_bp[0].opcode[0] = 0;
+ step_bp[0].opcode[1] = 0;
+ step_bp[1].addr = NULL;
+ step_bp[1].opcode[0] = 0;
+ step_bp[1].opcode[1] = 0;
+}
+
+/*
+ * emulate single stepping by means of breakpoint instructions
+ */
+static int gdbstub_single_step(struct pt_regs *regs)
+{
+ unsigned size;
+ uint32_t x;
+ uint8_t cur, *pc, *sp;
+
+ step_bp[0].addr = NULL;
+ step_bp[0].opcode[0] = 0;
+ step_bp[0].opcode[1] = 0;
+ step_bp[1].addr = NULL;
+ step_bp[1].opcode[0] = 0;
+ step_bp[1].opcode[1] = 0;
+ x = 0;
+
+ pc = (u8 *) regs->pc;
+ sp = (u8 *) (regs + 1);
+ if (gdbstub_read_byte(pc, &cur) < 0)
+ return -EFAULT;
+
+ gdbstub_bkpt("Single Step from %p { %02x }\n", pc, cur);
+
+ gdbstub_flush_caches = 1;
+
+ size = gdbstub_insn_sizes[cur];
+ if (size > 0) {
+ if (!__gdbstub_mark_bp(pc + size, 0))
+ goto fault;
+ } else {
+ switch (cur) {
+ /* Bxx (d8,PC) */
+ case 0xc0:
+ case 0xc1:
+ case 0xc2:
+ case 0xc3:
+ case 0xc4:
+ case 0xc5:
+ case 0xc6:
+ case 0xc7:
+ case 0xc8:
+ case 0xc9:
+ case 0xca:
+ if (gdbstub_read_byte(pc + 1, (u8 *) &x) < 0)
+ goto fault;
+ if (!__gdbstub_mark_bp(pc + 2, 0))
+ goto fault;
+ if ((x < 0 || x > 2) &&
+ !__gdbstub_mark_bp(pc + (s8) x, 1))
+ goto fault;
+ break;
+
+ /* LXX (d8,PC) */
+ case 0xd0:
+ case 0xd1:
+ case 0xd2:
+ case 0xd3:
+ case 0xd4:
+ case 0xd5:
+ case 0xd6:
+ case 0xd7:
+ case 0xd8:
+ case 0xd9:
+ case 0xda:
+ if (!__gdbstub_mark_bp(pc + 1, 0))
+ goto fault;
+ if (regs->pc != regs->lar &&
+ !__gdbstub_mark_bp((u8 *) regs->lar, 1))
+ goto fault;
+ break;
+
+ /* SETLB - loads the next for bytes into the LIR
+ * register */
+ case 0xdb:
+ if (!__gdbstub_mark_bp(pc + 1, 0))
+ goto fault;
+ break;
+
+ /* JMP (d16,PC) or CALL (d16,PC) */
+ case 0xcc:
+ case 0xcd:
+ if (gdbstub_read_byte(pc + 1, ((u8 *) &x) + 0) < 0 ||
+ gdbstub_read_byte(pc + 2, ((u8 *) &x) + 1) < 0)
+ goto fault;
+ if (!__gdbstub_mark_bp(pc + (s16) x, 0))
+ goto fault;
+ break;
+
+ /* JMP (d32,PC) or CALL (d32,PC) */
+ case 0xdc:
+ case 0xdd:
+ if (gdbstub_read_byte(pc + 1, ((u8 *) &x) + 0) < 0 ||
+ gdbstub_read_byte(pc + 2, ((u8 *) &x) + 1) < 0 ||
+ gdbstub_read_byte(pc + 3, ((u8 *) &x) + 2) < 0 ||
+ gdbstub_read_byte(pc + 4, ((u8 *) &x) + 3) < 0)
+ goto fault;
+ if (!__gdbstub_mark_bp(pc + (s32) x, 0))
+ goto fault;
+ break;
+
+ /* RETF */
+ case 0xde:
+ if (!__gdbstub_mark_bp((u8 *) regs->mdr, 0))
+ goto fault;
+ break;
+
+ /* RET */
+ case 0xdf:
+ if (gdbstub_read_byte(pc + 2, (u8 *) &x) < 0)
+ goto fault;
+ sp += (s8)x;
+ if (gdbstub_read_byte(sp + 0, ((u8 *) &x) + 0) < 0 ||
+ gdbstub_read_byte(sp + 1, ((u8 *) &x) + 1) < 0 ||
+ gdbstub_read_byte(sp + 2, ((u8 *) &x) + 2) < 0 ||
+ gdbstub_read_byte(sp + 3, ((u8 *) &x) + 3) < 0)
+ goto fault;
+ if (!__gdbstub_mark_bp((u8 *) x, 0))
+ goto fault;
+ break;
+
+ case 0xf0:
+ if (gdbstub_read_byte(pc + 1, &cur) < 0)
+ goto fault;
+
+ if (cur >= 0xf0 && cur <= 0xf7) {
+ /* JMP (An) / CALLS (An) */
+ switch (cur & 3) {
+ case 0: x = regs->a0; break;
+ case 1: x = regs->a1; break;
+ case 2: x = regs->a2; break;
+ case 3: x = regs->a3; break;
+ }
+ if (!__gdbstub_mark_bp((u8 *) x, 0))
+ goto fault;
+ } else if (cur == 0xfc) {
+ /* RETS */
+ if (gdbstub_read_byte(
+ sp + 0, ((u8 *) &x) + 0) < 0 ||
+ gdbstub_read_byte(
+ sp + 1, ((u8 *) &x) + 1) < 0 ||
+ gdbstub_read_byte(
+ sp + 2, ((u8 *) &x) + 2) < 0 ||
+ gdbstub_read_byte(
+ sp + 3, ((u8 *) &x) + 3) < 0)
+ goto fault;
+ if (!__gdbstub_mark_bp((u8 *) x, 0))
+ goto fault;
+ } else if (cur == 0xfd) {
+ /* RTI */
+ if (gdbstub_read_byte(
+ sp + 4, ((u8 *) &x) + 0) < 0 ||
+ gdbstub_read_byte(
+ sp + 5, ((u8 *) &x) + 1) < 0 ||
+ gdbstub_read_byte(
+ sp + 6, ((u8 *) &x) + 2) < 0 ||
+ gdbstub_read_byte(
+ sp + 7, ((u8 *) &x) + 3) < 0)
+ goto fault;
+ if (!__gdbstub_mark_bp((u8 *) x, 0))
+ goto fault;
+ } else {
+ if (!__gdbstub_mark_bp(pc + 2, 0))
+ goto fault;
+ }
+
+ break;
+
+ /* potential 3-byte conditional branches */
+ case 0xf8:
+ if (gdbstub_read_byte(pc + 1, &cur) < 0)
+ goto fault;
+ if (!__gdbstub_mark_bp(pc + 3, 0))
+ goto fault;
+
+ if (cur >= 0xe8 && cur <= 0xeb) {
+ if (gdbstub_read_byte(
+ pc + 2, ((u8 *) &x) + 0) < 0)
+ goto fault;
+ if ((x < 0 || x > 3) &&
+ !__gdbstub_mark_bp(pc + (s8) x, 1))
+ goto fault;
+ }
+ break;
+
+ case 0xfa:
+ if (gdbstub_read_byte(pc + 1, &cur) < 0)
+ goto fault;
+
+ if (cur == 0xff) {
+ /* CALLS (d16,PC) */
+ if (gdbstub_read_byte(
+ pc + 2, ((u8 *) &x) + 0) < 0 ||
+ gdbstub_read_byte(
+ pc + 3, ((u8 *) &x) + 1) < 0)
+ goto fault;
+ if (!__gdbstub_mark_bp(pc + (s16) x, 0))
+ goto fault;
+ } else {
+ if (!__gdbstub_mark_bp(pc + 4, 0))
+ goto fault;
+ }
+ break;
+
+ case 0xfc:
+ if (gdbstub_read_byte(pc + 1, &cur) < 0)
+ goto fault;
+ if (cur == 0xff) {
+ /* CALLS (d32,PC) */
+ if (gdbstub_read_byte(
+ pc + 2, ((u8 *) &x) + 0) < 0 ||
+ gdbstub_read_byte(
+ pc + 3, ((u8 *) &x) + 1) < 0 ||
+ gdbstub_read_byte(
+ pc + 4, ((u8 *) &x) + 2) < 0 ||
+ gdbstub_read_byte(
+ pc + 5, ((u8 *) &x) + 3) < 0)
+ goto fault;
+ if (!__gdbstub_mark_bp(
+ pc + (s32) x, 0))
+ goto fault;
+ } else {
+ if (!__gdbstub_mark_bp(
+ pc + 6, 0))
+ goto fault;
+ }
+ break;
+
+ }
+ }
+
+ gdbstub_bkpt("Step: %02x at %p; %02x at %p\n",
+ step_bp[0].opcode[0], step_bp[0].addr,
+ step_bp[1].opcode[0], step_bp[1].addr);
+
+ if (step_bp[0].addr) {
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+ if (gdbstub_write_byte(0xF7, step_bp[0].addr + 0) < 0 ||
+ gdbstub_write_byte(0xF7, step_bp[0].addr + 1) < 0)
+ goto fault;
+#else
+ if (gdbstub_write_byte(0xFF, step_bp[0].addr + 0) < 0)
+ goto fault;
+#endif
+ }
+
+ if (step_bp[1].addr) {
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+ if (gdbstub_write_byte(0xF7, step_bp[1].addr + 0) < 0 ||
+ gdbstub_write_byte(0xF7, step_bp[1].addr + 1) < 0)
+ goto fault;
+#else
+ if (gdbstub_write_byte(0xFF, step_bp[1].addr + 0) < 0)
+ goto fault;
+#endif
+ }
+
+ return 0;
+
+ fault:
+ /* uh-oh - silly address alert, try and restore things */
+ __gdbstub_restore_bp();
+ return -EFAULT;
+}
+
+#ifdef CONFIG_GDBSTUB_CONSOLE
+
+void gdbstub_console_write(struct console *con, const char *p, unsigned n)
+{
+ static const char gdbstub_cr[] = { 0x0d };
+ char outbuf[26];
+ int qty;
+ u8 busy;
+
+ busy = gdbstub_busy;
+ gdbstub_busy = 1;
+
+ outbuf[0] = 'O';
+
+ while (n > 0) {
+ qty = 1;
+
+ while (n > 0 && qty < 20) {
+ mem2hex(p, outbuf + qty, 2, 0);
+ qty += 2;
+ if (*p == 0x0a) {
+ mem2hex(gdbstub_cr, outbuf + qty, 2, 0);
+ qty += 2;
+ }
+ p++;
+ n--;
+ }
+
+ outbuf[qty] = 0;
+ putpacket(outbuf);
+ }
+
+ gdbstub_busy = busy;
+}
+
+static kdev_t gdbstub_console_dev(struct console *con)
+{
+ return MKDEV(1, 3); /* /dev/null */
+}
+
+static struct console gdbstub_console = {
+ .name = "gdb",
+ .write = gdbstub_console_write,
+ .device = gdbstub_console_dev,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+#endif
+
+/*
+ * Convert the memory pointed to by mem into hex, placing result in buf.
+ * - if successful, return a pointer to the last char put in buf (NUL)
+ * - in case of mem fault, return NULL
+ * may_fault is non-zero if we are reading from arbitrary memory, but is
+ * currently not used.
+ */
+static
+unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
+{
+ const u8 *mem = _mem;
+ u8 ch[4];
+
+ if ((u32) mem & 1 && count >= 1) {
+ if (gdbstub_read_byte(mem, ch) != 0)
+ return 0;
+ *buf++ = hexchars[ch[0] >> 4];
+ *buf++ = hexchars[ch[0] & 0xf];
+ mem++;
+ count--;
+ }
+
+ if ((u32) mem & 3 && count >= 2) {
+ if (gdbstub_read_word(mem, ch) != 0)
+ return 0;
+ *buf++ = hexchars[ch[0] >> 4];
+ *buf++ = hexchars[ch[0] & 0xf];
+ *buf++ = hexchars[ch[1] >> 4];
+ *buf++ = hexchars[ch[1] & 0xf];
+ mem += 2;
+ count -= 2;
+ }
+
+ while (count >= 4) {
+ if (gdbstub_read_dword(mem, ch) != 0)
+ return 0;
+ *buf++ = hexchars[ch[0] >> 4];
+ *buf++ = hexchars[ch[0] & 0xf];
+ *buf++ = hexchars[ch[1] >> 4];
+ *buf++ = hexchars[ch[1] & 0xf];
+ *buf++ = hexchars[ch[2] >> 4];
+ *buf++ = hexchars[ch[2] & 0xf];
+ *buf++ = hexchars[ch[3] >> 4];
+ *buf++ = hexchars[ch[3] & 0xf];
+ mem += 4;
+ count -= 4;
+ }
+
+ if (count >= 2) {
+ if (gdbstub_read_word(mem, ch) != 0)
+ return 0;
+ *buf++ = hexchars[ch[0] >> 4];
+ *buf++ = hexchars[ch[0] & 0xf];
+ *buf++ = hexchars[ch[1] >> 4];
+ *buf++ = hexchars[ch[1] & 0xf];
+ mem += 2;
+ count -= 2;
+ }
+
+ if (count >= 1) {
+ if (gdbstub_read_byte(mem, ch) != 0)
+ return 0;
+ *buf++ = hexchars[ch[0] >> 4];
+ *buf++ = hexchars[ch[0] & 0xf];
+ }
+
+ *buf = 0;
+ return buf;
+}
+
+/*
+ * convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written
+ * may_fault is non-zero if we are reading from arbitrary memory, but is
+ * currently not used.
+ */
+static
+const char *hex2mem(const char *buf, void *_mem, int count, int may_fault)
+{
+ u8 *mem = _mem;
+ union {
+ u32 val;
+ u8 b[4];
+ } ch;
+
+ if ((u32) mem & 1 && count >= 1) {
+ ch.b[0] = hex(*buf++) << 4;
+ ch.b[0] |= hex(*buf++);
+ if (gdbstub_write_byte(ch.val, mem) != 0)
+ return 0;
+ mem++;
+ count--;
+ }
+
+ if ((u32) mem & 3 && count >= 2) {
+ ch.b[0] = hex(*buf++) << 4;
+ ch.b[0] |= hex(*buf++);
+ ch.b[1] = hex(*buf++) << 4;
+ ch.b[1] |= hex(*buf++);
+ if (gdbstub_write_word(ch.val, mem) != 0)
+ return 0;
+ mem += 2;
+ count -= 2;
+ }
+
+ while (count >= 4) {
+ ch.b[0] = hex(*buf++) << 4;
+ ch.b[0] |= hex(*buf++);
+ ch.b[1] = hex(*buf++) << 4;
+ ch.b[1] |= hex(*buf++);
+ ch.b[2] = hex(*buf++) << 4;
+ ch.b[2] |= hex(*buf++);
+ ch.b[3] = hex(*buf++) << 4;
+ ch.b[3] |= hex(*buf++);
+ if (gdbstub_write_dword(ch.val, mem) != 0)
+ return 0;
+ mem += 4;
+ count -= 4;
+ }
+
+ if (count >= 2) {
+ ch.b[0] = hex(*buf++) << 4;
+ ch.b[0] |= hex(*buf++);
+ ch.b[1] = hex(*buf++) << 4;
+ ch.b[1] |= hex(*buf++);
+ if (gdbstub_write_word(ch.val, mem) != 0)
+ return 0;
+ mem += 2;
+ count -= 2;
+ }
+
+ if (count >= 1) {
+ ch.b[0] = hex(*buf++) << 4;
+ ch.b[0] |= hex(*buf++);
+ if (gdbstub_write_byte(ch.val, mem) != 0)
+ return 0;
+ }
+
+ return buf;
+}
+
+/*
+ * This table contains the mapping between MN10300 exception codes, and
+ * signals, which are primarily what GDB understands. It also indicates
+ * which hardware traps we need to commandeer when initializing the stub.
+ */
+static const struct excep_to_sig_map {
+ enum exception_code excep; /* MN10300 exception code */
+ unsigned char signo; /* Signal that we map this into */
+} excep_to_sig_map[] = {
+ { EXCEP_ITLBMISS, SIGSEGV },
+ { EXCEP_DTLBMISS, SIGSEGV },
+ { EXCEP_TRAP, SIGTRAP },
+ { EXCEP_ISTEP, SIGTRAP },
+ { EXCEP_IBREAK, SIGTRAP },
+ { EXCEP_OBREAK, SIGTRAP },
+ { EXCEP_UNIMPINS, SIGILL },
+ { EXCEP_UNIMPEXINS, SIGILL },
+ { EXCEP_MEMERR, SIGSEGV },
+ { EXCEP_MISALIGN, SIGSEGV },
+ { EXCEP_BUSERROR, SIGBUS },
+ { EXCEP_ILLINSACC, SIGSEGV },
+ { EXCEP_ILLDATACC, SIGSEGV },
+ { EXCEP_IOINSACC, SIGSEGV },
+ { EXCEP_PRIVINSACC, SIGSEGV },
+ { EXCEP_PRIVDATACC, SIGSEGV },
+ { EXCEP_FPU_DISABLED, SIGFPE },
+ { EXCEP_FPU_UNIMPINS, SIGFPE },
+ { EXCEP_FPU_OPERATION, SIGFPE },
+ { EXCEP_WDT, SIGALRM },
+ { EXCEP_NMI, SIGQUIT },
+ { EXCEP_IRQ_LEVEL0, SIGINT },
+ { EXCEP_IRQ_LEVEL1, SIGINT },
+ { EXCEP_IRQ_LEVEL2, SIGINT },
+ { EXCEP_IRQ_LEVEL3, SIGINT },
+ { EXCEP_IRQ_LEVEL4, SIGINT },
+ { EXCEP_IRQ_LEVEL5, SIGINT },
+ { EXCEP_IRQ_LEVEL6, SIGINT },
+ { 0, 0}
+};
+
+/*
+ * convert the MN10300 exception code into a UNIX signal number
+ */
+static int computeSignal(enum exception_code excep)
+{
+ const struct excep_to_sig_map *map;
+
+ for (map = excep_to_sig_map; map->signo; map++)
+ if (map->excep == excep)
+ return map->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
+static u32 gdbstub_fpcr, gdbstub_fpufs_array[32];
+
+/*
+ *
+ */
+static void gdbstub_store_fpu(void)
+{
+#ifdef CONFIG_FPU
+
+ asm volatile(
+ "or %2,epsw\n"
+#ifdef CONFIG_MN10300_PROC_MN103E010
+ "nop\n"
+ "nop\n"
+#endif
+ "mov %1, a1\n"
+ "fmov fs0, (a1+)\n"
+ "fmov fs1, (a1+)\n"
+ "fmov fs2, (a1+)\n"
+ "fmov fs3, (a1+)\n"
+ "fmov fs4, (a1+)\n"
+ "fmov fs5, (a1+)\n"
+ "fmov fs6, (a1+)\n"
+ "fmov fs7, (a1+)\n"
+ "fmov fs8, (a1+)\n"
+ "fmov fs9, (a1+)\n"
+ "fmov fs10, (a1+)\n"
+ "fmov fs11, (a1+)\n"
+ "fmov fs12, (a1+)\n"
+ "fmov fs13, (a1+)\n"
+ "fmov fs14, (a1+)\n"
+ "fmov fs15, (a1+)\n"
+ "fmov fs16, (a1+)\n"
+ "fmov fs17, (a1+)\n"
+ "fmov fs18, (a1+)\n"
+ "fmov fs19, (a1+)\n"
+ "fmov fs20, (a1+)\n"
+ "fmov fs21, (a1+)\n"
+ "fmov fs22, (a1+)\n"
+ "fmov fs23, (a1+)\n"
+ "fmov fs24, (a1+)\n"
+ "fmov fs25, (a1+)\n"
+ "fmov fs26, (a1+)\n"
+ "fmov fs27, (a1+)\n"
+ "fmov fs28, (a1+)\n"
+ "fmov fs29, (a1+)\n"
+ "fmov fs30, (a1+)\n"
+ "fmov fs31, (a1+)\n"
+ "fmov fpcr, %0\n"
+ : "=d"(gdbstub_fpcr)
+ : "g" (&gdbstub_fpufs_array), "i"(EPSW_FE)
+ : "a1"
+ );
+#endif
+}
+
+/*
+ *
+ */
+static void gdbstub_load_fpu(void)
+{
+#ifdef CONFIG_FPU
+
+ asm volatile(
+ "or %1,epsw\n"
+#ifdef CONFIG_MN10300_PROC_MN103E010
+ "nop\n"
+ "nop\n"
+#endif
+ "mov %0, a1\n"
+ "fmov (a1+), fs0\n"
+ "fmov (a1+), fs1\n"
+ "fmov (a1+), fs2\n"
+ "fmov (a1+), fs3\n"
+ "fmov (a1+), fs4\n"
+ "fmov (a1+), fs5\n"
+ "fmov (a1+), fs6\n"
+ "fmov (a1+), fs7\n"
+ "fmov (a1+), fs8\n"
+ "fmov (a1+), fs9\n"
+ "fmov (a1+), fs10\n"
+ "fmov (a1+), fs11\n"
+ "fmov (a1+), fs12\n"
+ "fmov (a1+), fs13\n"
+ "fmov (a1+), fs14\n"
+ "fmov (a1+), fs15\n"
+ "fmov (a1+), fs16\n"
+ "fmov (a1+), fs17\n"
+ "fmov (a1+), fs18\n"
+ "fmov (a1+), fs19\n"
+ "fmov (a1+), fs20\n"
+ "fmov (a1+), fs21\n"
+ "fmov (a1+), fs22\n"
+ "fmov (a1+), fs23\n"
+ "fmov (a1+), fs24\n"
+ "fmov (a1+), fs25\n"
+ "fmov (a1+), fs26\n"
+ "fmov (a1+), fs27\n"
+ "fmov (a1+), fs28\n"
+ "fmov (a1+), fs29\n"
+ "fmov (a1+), fs30\n"
+ "fmov (a1+), fs31\n"
+ "fmov %2, fpcr\n"
+ :
+ : "g" (&gdbstub_fpufs_array), "i"(EPSW_FE), "d"(gdbstub_fpcr)
+ : "a1"
+ );
+#endif
+}
+
+/*
+ * set a software breakpoint
+ */
+int gdbstub_set_breakpoint(u8 *addr, int len)
+{
+ int bkpt, loop, xloop;
+
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+ len = (len + 1) & ~1;
+#endif
+
+ gdbstub_bkpt("setbkpt(%p,%d)\n", addr, len);
+
+ for (bkpt = 255; bkpt >= 0; bkpt--)
+ if (!gdbstub_bkpts[bkpt].addr)
+ break;
+ if (bkpt < 0)
+ return -ENOSPC;
+
+ for (loop = 0; loop < len; loop++)
+ if (gdbstub_read_byte(&addr[loop],
+ &gdbstub_bkpts[bkpt].origbytes[loop]
+ ) < 0)
+ return -EFAULT;
+
+ gdbstub_flush_caches = 1;
+
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+ for (loop = 0; loop < len; loop++)
+ if (gdbstub_write_byte(0xF7, &addr[loop]) < 0)
+ goto restore;
+#else
+ for (loop = 0; loop < len; loop++)
+ if (gdbstub_write_byte(0xFF, &addr[loop]) < 0)
+ goto restore;
+#endif
+
+ gdbstub_bkpts[bkpt].addr = addr;
+ gdbstub_bkpts[bkpt].len = len;
+
+ gdbstub_bkpt("Set BKPT[%02x]: %p-%p {%02x%02x%02x%02x%02x%02x%02x}\n",
+ bkpt,
+ gdbstub_bkpts[bkpt].addr,
+ gdbstub_bkpts[bkpt].addr + gdbstub_bkpts[bkpt].len - 1,
+ gdbstub_bkpts[bkpt].origbytes[0],
+ gdbstub_bkpts[bkpt].origbytes[1],
+ gdbstub_bkpts[bkpt].origbytes[2],
+ gdbstub_bkpts[bkpt].origbytes[3],
+ gdbstub_bkpts[bkpt].origbytes[4],
+ gdbstub_bkpts[bkpt].origbytes[5],
+ gdbstub_bkpts[bkpt].origbytes[6]
+ );
+
+ return 0;
+
+restore:
+ for (xloop = 0; xloop < loop; xloop++)
+ gdbstub_write_byte(gdbstub_bkpts[bkpt].origbytes[xloop],
+ addr + xloop);
+ return -EFAULT;
+}
+
+/*
+ * clear a software breakpoint
+ */
+int gdbstub_clear_breakpoint(u8 *addr, int len)
+{
+ int bkpt, loop;
+
+#ifdef GDBSTUB_USE_F7F7_AS_BREAKPOINT
+ len = (len + 1) & ~1;
+#endif
+
+ gdbstub_bkpt("clearbkpt(%p,%d)\n", addr, len);
+
+ for (bkpt = 255; bkpt >= 0; bkpt--)
+ if (gdbstub_bkpts[bkpt].addr == addr &&
+ gdbstub_bkpts[bkpt].len == len)
+ break;
+ if (bkpt < 0)
+ return -ENOENT;
+
+ gdbstub_bkpts[bkpt].addr = NULL;
+
+ gdbstub_flush_caches = 1;
+
+ for (loop = 0; loop < len; loop++)
+ if (gdbstub_write_byte(gdbstub_bkpts[bkpt].origbytes[loop],
+ addr + loop) < 0)
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ * This function does all command processing for interfacing to gdb
+ * - returns 1 if the exception should be skipped, 0 otherwise.
+ */
+static int gdbstub(struct pt_regs *regs, enum exception_code excep)
+{
+ unsigned long *stack;
+ unsigned long epsw, mdr;
+ uint32_t zero, ssp;
+ uint8_t broke;
+ char *ptr;
+ int sigval;
+ int addr;
+ int length;
+ int loop;
+
+ if (excep == EXCEP_FPU_DISABLED)
+ return 0;
+
+ gdbstub_flush_caches = 0;
+
+ mn10300_set_gdbleds(1);
+
+ asm volatile("mov mdr,%0" : "=d"(mdr));
+ asm volatile("mov epsw,%0" : "=d"(epsw));
+ asm volatile("mov %0,epsw"
+ :: "d"((epsw & ~EPSW_IM) | EPSW_IE | EPSW_IM_1));
+
+ gdbstub_store_fpu();
+
+#ifdef CONFIG_GDBSTUB_IMMEDIATE
+ /* skip the initial pause loop */
+ if (regs->pc == (unsigned long) __gdbstub_pause)
+ regs->pc = (unsigned long) start_kernel;
+#endif
+
+ /* if we were single stepping, restore the opcodes hoisted for the
+ * breakpoint[s] */
+ broke = 0;
+ if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) ||
+ (step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc))
+ broke = 1;
+
+ __gdbstub_restore_bp();
+
+ if (gdbstub_rx_unget) {
+ sigval = SIGINT;
+ if (gdbstub_rx_unget != 3)
+ goto packet_waiting;
+ gdbstub_rx_unget = 0;
+ }
+
+ stack = (unsigned long *) regs->sp;
+ sigval = broke ? SIGTRAP : computeSignal(excep);
+
+ /* send information about a BUG() */
+ if (!user_mode(regs) && excep == EXCEP_SYSCALL15) {
+ const struct bug_entry *bug;
+
+ bug = find_bug(regs->pc);
+ if (bug)
+ goto found_bug;
+ length = snprintf(trans_buffer, sizeof(trans_buffer),
+ "BUG() at address %lx\n", regs->pc);
+ goto send_bug_pkt;
+
+ found_bug:
+ length = snprintf(trans_buffer, sizeof(trans_buffer),
+ "BUG() at address %lx (%s:%d)\n",
+ regs->pc, bug->file, bug->line);
+
+ send_bug_pkt:
+ ptr = output_buffer;
+ *ptr++ = 'O';
+ ptr = mem2hex(trans_buffer, ptr, length, 0);
+ *ptr = 0;
+ putpacket(output_buffer);
+
+ regs->pc -= 2;
+ sigval = SIGABRT;
+ } else if (regs->pc == (unsigned long) __gdbstub_bug_trap) {
+ regs->pc = regs->mdr;
+ sigval = SIGABRT;
+ }
+
+ /*
+ * send a message to the debugger's user saying what happened if it may
+ * not be clear cut (we can't map exceptions onto signals properly)
+ */
+ if (sigval != SIGINT && sigval != SIGTRAP && sigval != SIGILL) {
+ static const char title[] = "Excep ", tbcberr[] = "BCBERR ";
+ static const char crlf[] = "\r\n";
+ char hx;
+ u32 bcberr = BCBERR;
+
+ ptr = output_buffer;
+ *ptr++ = 'O';
+ ptr = mem2hex(title, ptr, sizeof(title) - 1, 0);
+
+ hx = hexchars[(excep & 0xf000) >> 12];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+ hx = hexchars[(excep & 0x0f00) >> 8];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+ hx = hexchars[(excep & 0x00f0) >> 4];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+ hx = hexchars[(excep & 0x000f)];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+
+ ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
+ *ptr = 0;
+ putpacket(output_buffer); /* send it off... */
+
+ /* BCBERR */
+ ptr = output_buffer;
+ *ptr++ = 'O';
+ ptr = mem2hex(tbcberr, ptr, sizeof(tbcberr) - 1, 0);
+
+ hx = hexchars[(bcberr & 0xf0000000) >> 28];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+ hx = hexchars[(bcberr & 0x0f000000) >> 24];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+ hx = hexchars[(bcberr & 0x00f00000) >> 20];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+ hx = hexchars[(bcberr & 0x000f0000) >> 16];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+ hx = hexchars[(bcberr & 0x0000f000) >> 12];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+ hx = hexchars[(bcberr & 0x00000f00) >> 8];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+ hx = hexchars[(bcberr & 0x000000f0) >> 4];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+ hx = hexchars[(bcberr & 0x0000000f)];
+ *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf];
+
+ ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
+ *ptr = 0;
+ putpacket(output_buffer); /* send it off... */
+ }
+
+ /*
+ * tell the debugger that an exception has occurred
+ */
+ ptr = output_buffer;
+
+ /*
+ * Send trap type (converted to signal)
+ */
+ *ptr++ = 'T';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+
+ /*
+ * Send Error PC
+ */
+ *ptr++ = hexchars[GDB_REGID_PC >> 4];
+ *ptr++ = hexchars[GDB_REGID_PC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex(&regs->pc, ptr, 4, 0);
+ *ptr++ = ';';
+
+ /*
+ * Send frame pointer
+ */
+ *ptr++ = hexchars[GDB_REGID_FP >> 4];
+ *ptr++ = hexchars[GDB_REGID_FP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex(&regs->a3, ptr, 4, 0);
+ *ptr++ = ';';
+
+ /*
+ * Send stack pointer
+ */
+ ssp = (unsigned long) (regs + 1);
+ *ptr++ = hexchars[GDB_REGID_SP >> 4];
+ *ptr++ = hexchars[GDB_REGID_SP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex(&ssp, ptr, 4, 0);
+ *ptr++ = ';';
+
+ *ptr++ = 0;
+ putpacket(output_buffer); /* send it off... */
+
+packet_waiting:
+ /*
+ * Wait for input from remote GDB
+ */
+ while (1) {
+ output_buffer[0] = 0;
+ getpacket(input_buffer);
+
+ switch (input_buffer[0]) {
+ /* request repeat of last signal number */
+ case '?':
+ output_buffer[0] = 'S';
+ output_buffer[1] = hexchars[sigval >> 4];
+ output_buffer[2] = hexchars[sigval & 0xf];
+ output_buffer[3] = 0;
+ break;
+
+ case 'd':
+ /* toggle debug flag */
+ break;
+
+ /*
+ * Return the value of the CPU registers
+ */
+ case 'g':
+ zero = 0;
+ ssp = (u32) (regs + 1);
+ ptr = output_buffer;
+ ptr = mem2hex(&regs->d0, ptr, 4, 0);
+ ptr = mem2hex(&regs->d1, ptr, 4, 0);
+ ptr = mem2hex(&regs->d2, ptr, 4, 0);
+ ptr = mem2hex(&regs->d3, ptr, 4, 0);
+ ptr = mem2hex(&regs->a0, ptr, 4, 0);
+ ptr = mem2hex(&regs->a1, ptr, 4, 0);
+ ptr = mem2hex(&regs->a2, ptr, 4, 0);
+ ptr = mem2hex(&regs->a3, ptr, 4, 0);
+
+ ptr = mem2hex(&ssp, ptr, 4, 0); /* 8 */
+ ptr = mem2hex(&regs->pc, ptr, 4, 0);
+ ptr = mem2hex(&regs->mdr, ptr, 4, 0);
+ ptr = mem2hex(&regs->epsw, ptr, 4, 0);
+ ptr = mem2hex(&regs->lir, ptr, 4, 0);
+ ptr = mem2hex(&regs->lar, ptr, 4, 0);
+ ptr = mem2hex(&regs->mdrq, ptr, 4, 0);
+
+ ptr = mem2hex(&regs->e0, ptr, 4, 0); /* 15 */
+ ptr = mem2hex(&regs->e1, ptr, 4, 0);
+ ptr = mem2hex(&regs->e2, ptr, 4, 0);
+ ptr = mem2hex(&regs->e3, ptr, 4, 0);
+ ptr = mem2hex(&regs->e4, ptr, 4, 0);
+ ptr = mem2hex(&regs->e5, ptr, 4, 0);
+ ptr = mem2hex(&regs->e6, ptr, 4, 0);
+ ptr = mem2hex(&regs->e7, ptr, 4, 0);
+
+ ptr = mem2hex(&ssp, ptr, 4, 0);
+ ptr = mem2hex(&regs, ptr, 4, 0);
+ ptr = mem2hex(&regs->sp, ptr, 4, 0);
+ ptr = mem2hex(&regs->mcrh, ptr, 4, 0); /* 26 */
+ ptr = mem2hex(&regs->mcrl, ptr, 4, 0);
+ ptr = mem2hex(&regs->mcvf, ptr, 4, 0);
+
+ ptr = mem2hex(&gdbstub_fpcr, ptr, 4, 0); /* 29 - FPCR */
+ ptr = mem2hex(&zero, ptr, 4, 0);
+ ptr = mem2hex(&zero, ptr, 4, 0);
+ for (loop = 0; loop < 32; loop++)
+ ptr = mem2hex(&gdbstub_fpufs_array[loop],
+ ptr, 4, 0); /* 32 - FS0-31 */
+
+ break;
+
+ /*
+ * set the value of the CPU registers - return OK
+ */
+ case 'G':
+ {
+ const char *ptr;
+
+ ptr = &input_buffer[1];
+ ptr = hex2mem(ptr, &regs->d0, 4, 0);
+ ptr = hex2mem(ptr, &regs->d1, 4, 0);
+ ptr = hex2mem(ptr, &regs->d2, 4, 0);
+ ptr = hex2mem(ptr, &regs->d3, 4, 0);
+ ptr = hex2mem(ptr, &regs->a0, 4, 0);
+ ptr = hex2mem(ptr, &regs->a1, 4, 0);
+ ptr = hex2mem(ptr, &regs->a2, 4, 0);
+ ptr = hex2mem(ptr, &regs->a3, 4, 0);
+
+ ptr = hex2mem(ptr, &ssp, 4, 0); /* 8 */
+ ptr = hex2mem(ptr, &regs->pc, 4, 0);
+ ptr = hex2mem(ptr, &regs->mdr, 4, 0);
+ ptr = hex2mem(ptr, &regs->epsw, 4, 0);
+ ptr = hex2mem(ptr, &regs->lir, 4, 0);
+ ptr = hex2mem(ptr, &regs->lar, 4, 0);
+ ptr = hex2mem(ptr, &regs->mdrq, 4, 0);
+
+ ptr = hex2mem(ptr, &regs->e0, 4, 0); /* 15 */
+ ptr = hex2mem(ptr, &regs->e1, 4, 0);
+ ptr = hex2mem(ptr, &regs->e2, 4, 0);
+ ptr = hex2mem(ptr, &regs->e3, 4, 0);
+ ptr = hex2mem(ptr, &regs->e4, 4, 0);
+ ptr = hex2mem(ptr, &regs->e5, 4, 0);
+ ptr = hex2mem(ptr, &regs->e6, 4, 0);
+ ptr = hex2mem(ptr, &regs->e7, 4, 0);
+
+ ptr = hex2mem(ptr, &ssp, 4, 0);
+ ptr = hex2mem(ptr, &zero, 4, 0);
+ ptr = hex2mem(ptr, &regs->sp, 4, 0);
+ ptr = hex2mem(ptr, &regs->mcrh, 4, 0); /* 26 */
+ ptr = hex2mem(ptr, &regs->mcrl, 4, 0);
+ ptr = hex2mem(ptr, &regs->mcvf, 4, 0);
+
+ ptr = hex2mem(ptr, &zero, 4, 0); /* 29 - FPCR */
+ ptr = hex2mem(ptr, &zero, 4, 0);
+ ptr = hex2mem(ptr, &zero, 4, 0);
+ for (loop = 0; loop < 32; loop++) /* 32 - FS0-31 */
+ ptr = hex2mem(ptr, &zero, 4, 0);
+
+#if 0
+ /*
+ * See if the stack pointer has moved. If so, then copy
+ * the saved locals and ins to the new location.
+ */
+ unsigned long *newsp = (unsigned long *) registers[SP];
+ if (sp != newsp)
+ sp = memcpy(newsp, sp, 16 * 4);
+#endif
+
+ gdbstub_strcpy(output_buffer, "OK");
+ }
+ break;
+
+ /*
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA
+ */
+ case 'm':
+ ptr = &input_buffer[1];
+
+ if (hexToInt(&ptr, &addr) &&
+ *ptr++ == ',' &&
+ hexToInt(&ptr, &length)
+ ) {
+ if (mem2hex((char *) addr, output_buffer,
+ length, 1))
+ break;
+ gdbstub_strcpy(output_buffer, "E03");
+ } else {
+ gdbstub_strcpy(output_buffer, "E01");
+ }
+ break;
+
+ /*
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA
+ * return OK
+ */
+ case 'M':
+ ptr = &input_buffer[1];
+
+ if (hexToInt(&ptr, &addr) &&
+ *ptr++ == ',' &&
+ hexToInt(&ptr, &length) &&
+ *ptr++ == ':'
+ ) {
+ if (hex2mem(ptr, (char *) addr, length, 1))
+ gdbstub_strcpy(output_buffer, "OK");
+ else
+ gdbstub_strcpy(output_buffer, "E03");
+
+ gdbstub_flush_caches = 1;
+ } else {
+ gdbstub_strcpy(output_buffer, "E02");
+ }
+ break;
+
+ /*
+ * cAA..AA Continue at address AA..AA(optional)
+ */
+ case 'c':
+ /* try to read optional parameter, pc unchanged if no
+ * parm */
+
+ ptr = &input_buffer[1];
+ if (hexToInt(&ptr, &addr))
+ regs->pc = addr;
+ goto done;
+
+ /*
+ * kill the program
+ */
+ case 'k' :
+ goto done; /* just continue */
+
+ /*
+ * Reset the whole machine (FIXME: system dependent)
+ */
+ case 'r':
+ break;
+
+ /*
+ * Step to next instruction
+ */
+ case 's':
+ /*
+ * using the T flag doesn't seem to perform single
+ * stepping (it seems to wind up being caught by the
+ * JTAG unit), so we have to use breakpoints and
+ * continue instead.
+ */
+ if (gdbstub_single_step(regs) < 0)
+ /* ignore any fault error for now */
+ gdbstub_printk("unable to set single-step"
+ " bp\n");
+ goto done;
+
+ /*
+ * Set baud rate (bBB)
+ */
+ case 'b':
+ do {
+ int baudrate;
+
+ ptr = &input_buffer[1];
+ if (!hexToInt(&ptr, &baudrate)) {
+ gdbstub_strcpy(output_buffer, "B01");
+ break;
+ }
+
+ if (baudrate) {
+ /* ACK before changing speed */
+ putpacket("OK");
+ gdbstub_io_set_baud(baudrate);
+ }
+ } while (0);
+ break;
+
+ /*
+ * Set breakpoint
+ */
+ case 'Z':
+ ptr = &input_buffer[1];
+
+ if (!hexToInt(&ptr, &loop) || *ptr++ != ',' ||
+ !hexToInt(&ptr, &addr) || *ptr++ != ',' ||
+ !hexToInt(&ptr, &length)
+ ) {
+ gdbstub_strcpy(output_buffer, "E01");
+ break;
+ }
+
+ /* only support software breakpoints */
+ gdbstub_strcpy(output_buffer, "E03");
+ if (loop != 0 ||
+ length < 1 ||
+ length > 7 ||
+ (unsigned long) addr < 4096)
+ break;
+
+ if (gdbstub_set_breakpoint((u8 *) addr, length) < 0)
+ break;
+
+ gdbstub_strcpy(output_buffer, "OK");
+ break;
+
+ /*
+ * Clear breakpoint
+ */
+ case 'z':
+ ptr = &input_buffer[1];
+
+ if (!hexToInt(&ptr, &loop) || *ptr++ != ',' ||
+ !hexToInt(&ptr, &addr) || *ptr++ != ',' ||
+ !hexToInt(&ptr, &length)
+ ) {
+ gdbstub_strcpy(output_buffer, "E01");
+ break;
+ }
+
+ /* only support software breakpoints */
+ gdbstub_strcpy(output_buffer, "E03");
+ if (loop != 0 ||
+ length < 1 ||
+ length > 7 ||
+ (unsigned long) addr < 4096)
+ break;
+
+ if (gdbstub_clear_breakpoint((u8 *) addr, length) < 0)
+ break;
+
+ gdbstub_strcpy(output_buffer, "OK");
+ break;
+
+ default:
+ gdbstub_proto("### GDB Unsupported Cmd '%s'\n",
+ input_buffer);
+ break;
+ }
+
+ /* reply to the request */
+ putpacket(output_buffer);
+ }
+
+done:
+ /*
+ * Need to flush the instruction cache here, as we may
+ * have deposited a breakpoint, and the icache probably
+ * has no way of knowing that a data ref to some location
+ * may have changed something that is in the instruction
+ * cache.
+ * NB: We flush both caches, just to be sure...
+ */
+ if (gdbstub_flush_caches)
+ gdbstub_purge_cache();
+
+ gdbstub_load_fpu();
+ mn10300_set_gdbleds(0);
+ if (excep == EXCEP_NMI)
+ NMICR = NMICR_NMIF;
+
+ touch_softlockup_watchdog();
+
+ local_irq_restore(epsw);
+ return 1;
+}
+
+/*
+ * handle event interception
+ */
+asmlinkage int gdbstub_intercept(struct pt_regs *regs,
+ enum exception_code excep)
+{
+ static u8 notfirst = 1;
+ int ret;
+
+ if (gdbstub_busy)
+ gdbstub_printk("--> gdbstub reentered itself\n");
+ gdbstub_busy = 1;
+
+ if (notfirst) {
+ unsigned long mdr;
+ asm("mov mdr,%0" : "=d"(mdr));
+
+ gdbstub_entry(
+ "--> gdbstub_intercept(%p,%04x) [MDR=%lx PC=%lx]\n",
+ regs, excep, mdr, regs->pc);
+
+ gdbstub_entry(
+ "PC: %08lx EPSW: %08lx SSP: %08lx mode: %s\n",
+ regs->pc, regs->epsw, (unsigned long) &ret,
+ user_mode(regs) ? "User" : "Super");
+ gdbstub_entry(
+ "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
+ regs->d0, regs->d1, regs->d2, regs->d3);
+ gdbstub_entry(
+ "a0: %08lx a1: %08lx a2: %08lx a3: %08lx\n",
+ regs->a0, regs->a1, regs->a2, regs->a3);
+ gdbstub_entry(
+ "e0: %08lx e1: %08lx e2: %08lx e3: %08lx\n",
+ regs->e0, regs->e1, regs->e2, regs->e3);
+ gdbstub_entry(
+ "e4: %08lx e5: %08lx e6: %08lx e7: %08lx\n",
+ regs->e4, regs->e5, regs->e6, regs->e7);
+ gdbstub_entry(
+ "lar: %08lx lir: %08lx mdr: %08lx usp: %08lx\n",
+ regs->lar, regs->lir, regs->mdr, regs->sp);
+ gdbstub_entry(
+ "cvf: %08lx crl: %08lx crh: %08lx drq: %08lx\n",
+ regs->mcvf, regs->mcrl, regs->mcrh, regs->mdrq);
+ gdbstub_entry(
+ "threadinfo=%p task=%p)\n",
+ current_thread_info(), current);
+ } else {
+ notfirst = 1;
+ }
+
+ ret = gdbstub(regs, excep);
+
+ gdbstub_entry("<-- gdbstub_intercept()\n");
+ gdbstub_busy = 0;
+ return ret;
+}
+
+/*
+ * handle the GDB stub itself causing an exception
+ */
+asmlinkage void gdbstub_exception(struct pt_regs *regs,
+ enum exception_code excep)
+{
+ unsigned long mdr;
+
+ asm("mov mdr,%0" : "=d"(mdr));
+ gdbstub_entry("--> gdbstub exception({%p},%04x) [MDR=%lx]\n",
+ regs, excep, mdr);
+
+ while ((unsigned long) regs == 0xffffffff) {}
+
+ /* handle guarded memory accesses where we know it might fault */
+ if (regs->pc == (unsigned) gdbstub_read_byte_guard) {
+ regs->pc = (unsigned) gdbstub_read_byte_cont;
+ goto fault;
+ }
+
+ if (regs->pc == (unsigned) gdbstub_read_word_guard) {
+ regs->pc = (unsigned) gdbstub_read_word_cont;
+ goto fault;
+ }
+
+ if (regs->pc == (unsigned) gdbstub_read_dword_guard) {
+ regs->pc = (unsigned) gdbstub_read_dword_cont;
+ goto fault;
+ }
+
+ if (regs->pc == (unsigned) gdbstub_write_byte_guard) {
+ regs->pc = (unsigned) gdbstub_write_byte_cont;
+ goto fault;
+ }
+
+ if (regs->pc == (unsigned) gdbstub_write_word_guard) {
+ regs->pc = (unsigned) gdbstub_write_word_cont;
+ goto fault;
+ }
+
+ if (regs->pc == (unsigned) gdbstub_write_dword_guard) {
+ regs->pc = (unsigned) gdbstub_write_dword_cont;
+ goto fault;
+ }
+
+ gdbstub_printk("\n### GDB stub caused an exception ###\n");
+
+ /* something went horribly wrong */
+ console_verbose();
+ show_registers(regs);
+
+ panic("GDB Stub caused an unexpected exception - can't continue\n");
+
+ /* we caught an attempt by the stub to access silly memory */
+fault:
+ gdbstub_entry("<-- gdbstub exception() = EFAULT\n");
+ regs->d0 = -EFAULT;
+ return;
+}
+
+/*
+ * send an exit message to GDB
+ */
+void gdbstub_exit(int status)
+{
+ unsigned char checksum;
+ unsigned char ch;
+ int count;
+
+ gdbstub_busy = 1;
+ output_buffer[0] = 'W';
+ output_buffer[1] = hexchars[(status >> 4) & 0x0F];
+ output_buffer[2] = hexchars[status & 0x0F];
+ output_buffer[3] = 0;
+
+ gdbstub_io_tx_char('$');
+ checksum = 0;
+ count = 0;
+
+ while ((ch = output_buffer[count]) != 0) {
+ gdbstub_io_tx_char(ch);
+ checksum += ch;
+ count += 1;
+ }
+
+ gdbstub_io_tx_char('#');
+ gdbstub_io_tx_char(hexchars[checksum >> 4]);
+ gdbstub_io_tx_char(hexchars[checksum & 0xf]);
+
+ /* make sure the output is flushed, or else RedBoot might clobber it */
+ gdbstub_io_tx_flush();
+
+ gdbstub_busy = 0;
+}
+
+/*
+ * initialise the GDB stub
+ */
+asmlinkage void __init gdbstub_init(void)
+{
+#ifdef CONFIG_GDBSTUB_IMMEDIATE
+ unsigned char ch;
+ int ret;
+#endif
+
+ gdbstub_busy = 1;
+
+ printk(KERN_INFO "%s", gdbstub_banner);
+
+ gdbstub_io_init();
+
+ gdbstub_entry("--> gdbstub_init\n");
+
+ /* try to talk to GDB (or anyone insane enough to want to type GDB
+ * protocol by hand) */
+ gdbstub_io("### GDB Tx ACK\n");
+ gdbstub_io_tx_char('+'); /* 'hello world' */
+
+#ifdef CONFIG_GDBSTUB_IMMEDIATE
+ gdbstub_printk("GDB Stub waiting for packet\n");
+
+ /* in case GDB is started before us, ACK any packets that are already
+ * sitting there (presumably "$?#xx")
+ */
+ do { gdbstub_io_rx_char(&ch, 0); } while (ch != '$');
+ do { gdbstub_io_rx_char(&ch, 0); } while (ch != '#');
+ /* eat first csum byte */
+ do { ret = gdbstub_io_rx_char(&ch, 0); } while (ret != 0);
+ /* eat second csum byte */
+ do { ret = gdbstub_io_rx_char(&ch, 0); } while (ret != 0);
+
+ gdbstub_io("### GDB Tx NAK\n");
+ gdbstub_io_tx_char('-'); /* NAK it */
+
+#else
+ printk("GDB Stub ready\n");
+#endif
+
+ gdbstub_busy = 0;
+ gdbstub_entry("<-- gdbstub_init\n");
+}
+
+/*
+ * register the console at a more appropriate time
+ */
+#ifdef CONFIG_GDBSTUB_CONSOLE
+static int __init gdbstub_postinit(void)
+{
+ printk(KERN_NOTICE "registering console\n");
+ register_console(&gdbstub_console);
+ return 0;
+}
+
+__initcall(gdbstub_postinit);
+#endif
+
+/*
+ * handle character reception on GDB serial port
+ * - jump into the GDB stub if BREAK is detected on the serial line
+ */
+asmlinkage void gdbstub_rx_irq(struct pt_regs *regs, enum exception_code excep)
+{
+ char ch;
+ int ret;
+
+ gdbstub_entry("--> gdbstub_rx_irq\n");
+
+ do {
+ ret = gdbstub_io_rx_char(&ch, 1);
+ if (ret != -EIO && ret != -EAGAIN) {
+ if (ret != -EINTR)
+ gdbstub_rx_unget = ch;
+ gdbstub(regs, excep);
+ }
+ } while (ret != -EAGAIN);
+
+ gdbstub_entry("<-- gdbstub_rx_irq\n");
+}
diff --git a/arch/mn10300/kernel/head.S b/arch/mn10300/kernel/head.S
new file mode 100644
index 00000000000..606bd8c6758
--- /dev/null
+++ b/arch/mn10300/kernel/head.S
@@ -0,0 +1,255 @@
+/* Boot entry point for MN10300 kernel
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/threads.h>
+#include <linux/linkage.h>
+#include <linux/serial_reg.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/frame.inc>
+#include <asm/param.h>
+#include <asm/unit/serial.h>
+
+ .section .text.head,"ax"
+
+###############################################################################
+#
+# bootloader entry point
+#
+###############################################################################
+ .globl _start
+ .type _start,@function
+_start:
+ # save commandline pointer
+ mov d0,a3
+
+ # preload the PGD pointer register
+ mov swapper_pg_dir,d0
+ mov d0,(PTBR)
+
+ # turn on the TLBs
+ mov MMUCTR_IIV|MMUCTR_DIV,d0
+ mov d0,(MMUCTR)
+ mov MMUCTR_ITE|MMUCTR_DTE|MMUCTR_CE,d0
+ mov d0,(MMUCTR)
+
+ # turn on AM33v2 exception handling mode and set the trap table base
+ movhu (CPUP),d0
+ or CPUP_EXM_AM33V2,d0
+ movhu d0,(CPUP)
+ mov CONFIG_INTERRUPT_VECTOR_BASE,d0
+ mov d0,(TBR)
+
+ # invalidate and enable both of the caches
+ mov CHCTR,a0
+ clr d0
+ movhu d0,(a0) # turn off first
+ mov CHCTR_ICINV|CHCTR_DCINV,d0
+ movhu d0,(a0)
+ setlb
+ mov (a0),d0
+ btst CHCTR_ICBUSY|CHCTR_DCBUSY,d0 # wait till not busy
+ lne
+
+#ifndef CONFIG_MN10300_CACHE_DISABLED
+#ifdef CONFIG_MN10300_CACHE_WBACK
+#ifndef CONFIG_MN10300_CACHE_WBACK_NOWRALLOC
+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK,d0
+#else
+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRBACK|CHCTR_DCALMD,d0
+#endif /* CACHE_DISABLED */
+#else
+ mov CHCTR_ICEN|CHCTR_DCEN|CHCTR_DCWTMD_WRTHROUGH,d0
+#endif /* WBACK */
+ movhu d0,(a0) # enable
+#endif /* NOWRALLOC */
+
+ # turn on RTS on the debug serial port if applicable
+#ifdef CONFIG_MN10300_UNIT_ASB2305
+ bset UART_MCR_RTS,(ASB2305_DEBUG_MCR)
+#endif
+
+ # clear the BSS area
+ mov __bss_start,a0
+ mov __bss_stop,a1
+ clr d0
+bssclear:
+ cmp a1,a0
+ bge bssclear_end
+ mov d0,(a0)
+ inc4 a0
+ bra bssclear
+bssclear_end:
+
+ # retrieve the parameters (including command line) before we overwrite
+ # them
+ cmp 0xabadcafe,d1
+ bne __no_parameters
+
+__copy_parameters:
+ mov redboot_command_line,a0
+ mov a0,a1
+ add COMMAND_LINE_SIZE,a1
+1:
+ movbu (a3),d0
+ inc a3
+ movbu d0,(a0)
+ inc a0
+ cmp a1,a0
+ blt 1b
+
+ mov redboot_platform_name,a0
+ mov a0,a1
+ add COMMAND_LINE_SIZE,a1
+ mov d2,a3
+1:
+ movbu (a3),d0
+ inc a3
+ movbu d0,(a0)
+ inc a0
+ cmp a1,a0
+ blt 1b
+
+__no_parameters:
+
+ # set up the registers with recognisable rubbish in them
+ mov init_thread_union+THREAD_SIZE-12,sp
+
+ mov 0xea01eaea,d0
+ mov d0,(4,sp) # EPSW save area
+ mov 0xea02eaea,d0
+ mov d0,(8,sp) # PC save area
+
+ mov 0xeb0060ed,d0
+ mov d0,mdr
+ mov 0xeb0061ed,d0
+ mov d0,mdrq
+ mov 0xeb0062ed,d0
+ mov d0,mcrh
+ mov 0xeb0063ed,d0
+ mov d0,mcrl
+ mov 0xeb0064ed,d0
+ mov d0,mcvf
+ mov 0xed0065ed,a3
+ mov a3,usp
+
+ mov 0xed00e0ed,e0
+ mov 0xed00e1ed,e1
+ mov 0xed00e2ed,e2
+ mov 0xed00e3ed,e3
+ mov 0xed00e4ed,e4
+ mov 0xed00e5ed,e5
+ mov 0xed00e6ed,e6
+ mov 0xed00e7ed,e7
+
+ mov 0xed00d0ed,d0
+ mov 0xed00d1ed,d1
+ mov 0xed00d2ed,d2
+ mov 0xed00d3ed,d3
+ mov 0xed00a0ed,a0
+ mov 0xed00a1ed,a1
+ mov 0xed00a2ed,a2
+ mov 0,a3
+
+ # set up the initial kernel stack
+ SAVE_ALL
+ mov 0xffffffff,d0
+ mov d0,(REG_ORIG_D0,fp)
+
+ # put different recognisable rubbish in the regs
+ mov 0xfb0060ed,d0
+ mov d0,mdr
+ mov 0xfb0061ed,d0
+ mov d0,mdrq
+ mov 0xfb0062ed,d0
+ mov d0,mcrh
+ mov 0xfb0063ed,d0
+ mov d0,mcrl
+ mov 0xfb0064ed,d0
+ mov d0,mcvf
+ mov 0xfd0065ed,a0
+ mov a0,usp
+
+ mov 0xfd00e0ed,e0
+ mov 0xfd00e1ed,e1
+ mov 0xfd00e2ed,e2
+ mov 0xfd00e3ed,e3
+ mov 0xfd00e4ed,e4
+ mov 0xfd00e5ed,e5
+ mov 0xfd00e6ed,e6
+ mov 0xfd00e7ed,e7
+
+ mov 0xfd00d0ed,d0
+ mov 0xfd00d1ed,d1
+ mov 0xfd00d2ed,d2
+ mov 0xfd00d3ed,d3
+ mov 0xfd00a0ed,a0
+ mov 0xfd00a1ed,a1
+ mov 0xfd00a2ed,a2
+
+ # we may be holding current in E2
+#ifdef CONFIG_MN10300_CURRENT_IN_E2
+ mov init_task,e2
+#endif
+
+ # initialise the processor and the unit
+ call processor_init[],0
+ call unit_init[],0
+
+#ifdef CONFIG_GDBSTUB
+ call gdbstub_init[],0
+
+#ifdef CONFIG_GDBSTUB_IMMEDIATE
+ .globl __gdbstub_pause
+__gdbstub_pause:
+ bra __gdbstub_pause
+#endif
+#endif
+
+ jmp start_kernel
+ .size _start, _start-.
+ENTRY(__head_end)
+
+/*
+ * This is initialized to disallow all access to the low 2G region
+ * - the high 2G region is managed directly by the MMU
+ * - range 0x70000000-0x7C000000 are initialised for use by VMALLOC
+ */
+ .section .bss
+ .balign PAGE_SIZE
+ENTRY(swapper_pg_dir)
+ .space PTRS_PER_PGD*4
+
+/*
+ * The page tables are initialized to only 8MB here - the final page
+ * tables are set up later depending on memory size.
+ */
+
+ .balign PAGE_SIZE
+ENTRY(empty_zero_page)
+ .space PAGE_SIZE
+
+ .balign PAGE_SIZE
+ENTRY(empty_bad_page)
+ .space PAGE_SIZE
+
+ .balign PAGE_SIZE
+ENTRY(empty_bad_pte_table)
+ .space PAGE_SIZE
+
+ .balign PAGE_SIZE
+ENTRY(large_page_table)
+ .space PAGE_SIZE
+
+ .balign PAGE_SIZE
+ENTRY(kernel_vmalloc_ptes)
+ .space ((VMALLOC_END-VMALLOC_START)/PAGE_SIZE)*4
diff --git a/arch/mn10300/kernel/init_task.c b/arch/mn10300/kernel/init_task.c
new file mode 100644
index 00000000000..39fe6882dd1
--- /dev/null
+++ b/arch/mn10300/kernel/init_task.c
@@ -0,0 +1,45 @@
+/* MN10300 Initial task definitions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+EXPORT_SYMBOL(init_mm);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is THREAD_SIZE aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"))) =
+ { INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h
new file mode 100644
index 00000000000..eee2eee8626
--- /dev/null
+++ b/arch/mn10300/kernel/internal.h
@@ -0,0 +1,20 @@
+/* Internal definitions for the arch part of the core kernel
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+/*
+ * kthread.S
+ */
+extern int kernel_thread_helper(int);
+
+/*
+ * entry.S
+ */
+extern void ret_from_fork(struct task_struct *) __attribute__((noreturn));
diff --git a/arch/mn10300/kernel/io.c b/arch/mn10300/kernel/io.c
new file mode 100644
index 00000000000..e96fdf6bb54
--- /dev/null
+++ b/arch/mn10300/kernel/io.c
@@ -0,0 +1,30 @@
+/* MN10300 Misaligned multibyte-word I/O
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+
+/*
+ * output data from a potentially misaligned buffer
+ */
+void __outsl(unsigned long addr, const void *buffer, int count)
+{
+ const unsigned char *buf = buffer;
+ unsigned long val;
+
+ while (count--) {
+ memcpy(&val, buf, 4);
+ outl(val, addr);
+ buf += 4;
+ }
+}
+EXPORT_SYMBOL(__outsl);
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
new file mode 100644
index 00000000000..761c434a248
--- /dev/null
+++ b/arch/mn10300/kernel/irq.c
@@ -0,0 +1,235 @@
+/* MN10300 Arch-specific interrupt handling
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
+#include <asm/setup.h>
+
+unsigned long __mn10300_irq_enabled_epsw = EPSW_IE | EPSW_IM_7;
+EXPORT_SYMBOL(__mn10300_irq_enabled_epsw);
+
+atomic_t irq_err_count;
+
+/*
+ * MN10300 INTC controller operations
+ */
+static void mn10300_cpupic_disable(unsigned int irq)
+{
+ u16 tmp = GxICR(irq);
+ GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
+ tmp = GxICR(irq);
+}
+
+static void mn10300_cpupic_enable(unsigned int irq)
+{
+ u16 tmp = GxICR(irq);
+ GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
+ tmp = GxICR(irq);
+}
+
+static void mn10300_cpupic_ack(unsigned int irq)
+{
+ u16 tmp;
+ *(volatile u8 *) &GxICR(irq) = GxICR_DETECT;
+ tmp = GxICR(irq);
+}
+
+static void mn10300_cpupic_mask(unsigned int irq)
+{
+ u16 tmp = GxICR(irq);
+ GxICR(irq) = (tmp & GxICR_LEVEL);
+ tmp = GxICR(irq);
+}
+
+static void mn10300_cpupic_mask_ack(unsigned int irq)
+{
+ u16 tmp = GxICR(irq);
+ GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_DETECT;
+ tmp = GxICR(irq);
+}
+
+static void mn10300_cpupic_unmask(unsigned int irq)
+{
+ u16 tmp = GxICR(irq);
+ GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
+ tmp = GxICR(irq);
+}
+
+static void mn10300_cpupic_end(unsigned int irq)
+{
+ u16 tmp = GxICR(irq);
+ GxICR(irq) = (tmp & GxICR_LEVEL) | GxICR_ENABLE;
+ tmp = GxICR(irq);
+}
+
+static struct irq_chip mn10300_cpu_pic = {
+ .name = "cpu",
+ .disable = mn10300_cpupic_disable,
+ .enable = mn10300_cpupic_enable,
+ .ack = mn10300_cpupic_ack,
+ .mask = mn10300_cpupic_mask,
+ .mask_ack = mn10300_cpupic_mask_ack,
+ .unmask = mn10300_cpupic_unmask,
+ .end = mn10300_cpupic_end,
+};
+
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(int irq)
+{
+ printk(KERN_WARNING "unexpected IRQ trap at vector %02x\n", irq);
+}
+
+/*
+ * change the level at which an IRQ executes
+ * - must not be called whilst interrupts are being processed!
+ */
+void set_intr_level(int irq, u16 level)
+{
+ u16 tmp;
+
+ if (in_interrupt())
+ BUG();
+
+ tmp = GxICR(irq);
+ GxICR(irq) = (tmp & GxICR_ENABLE) | level;
+ tmp = GxICR(irq);
+}
+
+/*
+ * mark an interrupt to be ACK'd after interrupt handlers have been run rather
+ * than before
+ * - see Documentation/mn10300/features.txt
+ */
+void set_intr_postackable(int irq)
+{
+ set_irq_handler(irq, handle_level_irq);
+}
+
+/*
+ * initialise the interrupt system
+ */
+void __init init_IRQ(void)
+{
+ int irq;
+
+ for (irq = 0; irq < NR_IRQS; irq++)
+ if (irq_desc[irq].chip == &no_irq_type)
+ set_irq_chip_and_handler(irq, &mn10300_cpu_pic,
+ handle_edge_irq);
+ unit_init_IRQ();
+}
+
+/*
+ * handle normal device IRQs
+ */
+asmlinkage void do_IRQ(void)
+{
+ unsigned long sp, epsw, irq_disabled_epsw, old_irq_enabled_epsw;
+ int irq;
+
+ sp = current_stack_pointer();
+ if (sp - (sp & ~(THREAD_SIZE - 1)) < STACK_WARN)
+ BUG();
+
+ /* make sure local_irq_enable() doesn't muck up the interrupt priority
+ * setting in EPSW */
+ old_irq_enabled_epsw = __mn10300_irq_enabled_epsw;
+ local_save_flags(epsw);
+ __mn10300_irq_enabled_epsw = EPSW_IE | (EPSW_IM & epsw);
+ irq_disabled_epsw = EPSW_IE | MN10300_CLI_LEVEL;
+
+ __IRQ_STAT(smp_processor_id(), __irq_count)++;
+
+ irq_enter();
+
+ for (;;) {
+ /* ask the interrupt controller for the next IRQ to process
+ * - the result we get depends on EPSW.IM
+ */
+ irq = IAGR & IAGR_GN;
+ if (!irq)
+ break;
+
+ local_irq_restore(irq_disabled_epsw);
+
+ generic_handle_irq(irq >> 2);
+
+ /* restore IRQ controls for IAGR access */
+ local_irq_restore(epsw);
+ }
+
+ __mn10300_irq_enabled_epsw = old_irq_enabled_epsw;
+
+ irq_exit();
+}
+
+/*
+ * Display interrupt management information through /proc/interrupts
+ */
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *) v, j, cpu;
+ struct irqaction *action;
+ unsigned long flags;
+
+ switch (i) {
+ /* display column title bar naming CPUs */
+ case 0:
+ seq_printf(p, " ");
+ for (j = 0; j < NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "CPU%d ", j);
+ seq_putc(p, '\n');
+ break;
+
+ /* display information rows, one per active CPU */
+ case 1 ... NR_IRQS - 1:
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+
+ action = irq_desc[i].action;
+ if (action) {
+ seq_printf(p, "%3d: ", i);
+ for_each_present_cpu(cpu)
+ seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+ seq_printf(p, " %14s.%u", irq_desc[i].chip->name,
+ (GxICR(i) & GxICR_LEVEL) >>
+ GxICR_LEVEL_SHIFT);
+ seq_printf(p, " %s", action->name);
+
+ for (action = action->next;
+ action;
+ action = action->next)
+ seq_printf(p, ", %s", action->name);
+
+ seq_putc(p, '\n');
+ }
+
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ break;
+
+ /* polish off with NMI and error counters */
+ case NR_IRQS:
+ seq_printf(p, "NMI: ");
+ for (j = 0; j < NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "%10u ", nmi_count(j));
+ seq_putc(p, '\n');
+
+ seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+ break;
+ }
+
+ return 0;
+}
diff --git a/arch/mn10300/kernel/kernel_execve.S b/arch/mn10300/kernel/kernel_execve.S
new file mode 100644
index 00000000000..86039f10526
--- /dev/null
+++ b/arch/mn10300/kernel/kernel_execve.S
@@ -0,0 +1,37 @@
+/* MN10300 In-kernel program execution
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+
+###############################################################################
+#
+# Do a system call from kernel instead of calling sys_execve so we end up with
+# proper pt_regs.
+#
+# int kernel_execve(const char *filename, char *const argv[],
+# char *const envp[])
+#
+# On entry: D0/D1/8(SP): arguments to function
+# On return: D0: syscall return.
+#
+###############################################################################
+ .globl kernel_execve
+ .type kernel_execve,@function
+kernel_execve:
+ mov a3,a1
+ mov d0,a0
+ mov (12,sp),a3
+ mov +__NR_execve,d0
+ syscall 0
+ mov a1,a3
+ rets
+
+ .size kernel_execve,.-kernel_execve
diff --git a/arch/mn10300/kernel/kprobes.c b/arch/mn10300/kernel/kprobes.c
new file mode 100644
index 00000000000..dacafab00eb
--- /dev/null
+++ b/arch/mn10300/kernel/kprobes.c
@@ -0,0 +1,653 @@
+/* MN10300 Kernel probes implementation
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by Mark Salter (msalter@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public Licence as published by
+ * the Free Software Foundation; either version 2 of the Licence, 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 Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public Licence
+ * 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/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/spinlock.h>
+#include <linux/preempt.h>
+#include <linux/kdebug.h>
+#include <asm/cacheflush.h>
+
+struct kretprobe_blackpoint kretprobe_blacklist[] = { { NULL, NULL } };
+const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist);
+
+/* kprobe_status settings */
+#define KPROBE_HIT_ACTIVE 0x00000001
+#define KPROBE_HIT_SS 0x00000002
+
+static struct kprobe *current_kprobe;
+static unsigned long current_kprobe_orig_pc;
+static unsigned long current_kprobe_next_pc;
+static int current_kprobe_ss_flags;
+static unsigned long kprobe_status;
+static kprobe_opcode_t current_kprobe_ss_buf[MAX_INSN_SIZE + 2];
+static unsigned long current_kprobe_bp_addr;
+
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+
+
+/* singlestep flag bits */
+#define SINGLESTEP_BRANCH 1
+#define SINGLESTEP_PCREL 2
+
+#define READ_BYTE(p, valp) \
+ do { *(u8 *)(valp) = *(u8 *)(p); } while (0)
+
+#define READ_WORD16(p, valp) \
+ do { \
+ READ_BYTE((p), (valp)); \
+ READ_BYTE((u8 *)(p) + 1, (u8 *)(valp) + 1); \
+ } while (0)
+
+#define READ_WORD32(p, valp) \
+ do { \
+ READ_BYTE((p), (valp)); \
+ READ_BYTE((u8 *)(p) + 1, (u8 *)(valp) + 1); \
+ READ_BYTE((u8 *)(p) + 2, (u8 *)(valp) + 2); \
+ READ_BYTE((u8 *)(p) + 3, (u8 *)(valp) + 3); \
+ } while (0)
+
+
+static const u8 mn10300_insn_sizes[256] =
+{
+ /* 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, /* 0 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */
+ 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, /* 2 */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, /* 3 */
+ 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, /* 4 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, /* 5 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
+ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 8 */
+ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 9 */
+ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* a */
+ 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* b */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, /* c */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
+ 0, 2, 2, 2, 2, 2, 2, 4, 0, 3, 0, 4, 0, 6, 7, 1 /* f */
+};
+
+#define LT (1 << 0)
+#define GT (1 << 1)
+#define GE (1 << 2)
+#define LE (1 << 3)
+#define CS (1 << 4)
+#define HI (1 << 5)
+#define CC (1 << 6)
+#define LS (1 << 7)
+#define EQ (1 << 8)
+#define NE (1 << 9)
+#define RA (1 << 10)
+#define VC (1 << 11)
+#define VS (1 << 12)
+#define NC (1 << 13)
+#define NS (1 << 14)
+
+static const u16 cond_table[] = {
+ /* V C N Z */
+ /* 0 0 0 0 */ (NE | NC | CC | VC | GE | GT | HI),
+ /* 0 0 0 1 */ (EQ | NC | CC | VC | GE | LE | LS),
+ /* 0 0 1 0 */ (NE | NS | CC | VC | LT | LE | HI),
+ /* 0 0 1 1 */ (EQ | NS | CC | VC | LT | LE | LS),
+ /* 0 1 0 0 */ (NE | NC | CS | VC | GE | GT | LS),
+ /* 0 1 0 1 */ (EQ | NC | CS | VC | GE | LE | LS),
+ /* 0 1 1 0 */ (NE | NS | CS | VC | LT | LE | LS),
+ /* 0 1 1 1 */ (EQ | NS | CS | VC | LT | LE | LS),
+ /* 1 0 0 0 */ (NE | NC | CC | VS | LT | LE | HI),
+ /* 1 0 0 1 */ (EQ | NC | CC | VS | LT | LE | LS),
+ /* 1 0 1 0 */ (NE | NS | CC | VS | GE | GT | HI),
+ /* 1 0 1 1 */ (EQ | NS | CC | VS | GE | LE | LS),
+ /* 1 1 0 0 */ (NE | NC | CS | VS | LT | LE | LS),
+ /* 1 1 0 1 */ (EQ | NC | CS | VS | LT | LE | LS),
+ /* 1 1 1 0 */ (NE | NS | CS | VS | GE | GT | LS),
+ /* 1 1 1 1 */ (EQ | NS | CS | VS | GE | LE | LS),
+};
+
+/*
+ * Calculate what the PC will be after executing next instruction
+ */
+static unsigned find_nextpc(struct pt_regs *regs, int *flags)
+{
+ unsigned size;
+ s8 x8;
+ s16 x16;
+ s32 x32;
+ u8 opc, *pc, *sp, *next;
+
+ next = 0;
+ *flags = SINGLESTEP_PCREL;
+
+ pc = (u8 *) regs->pc;
+ sp = (u8 *) (regs + 1);
+ opc = *pc;
+
+ size = mn10300_insn_sizes[opc];
+ if (size > 0) {
+ next = pc + size;
+ } else {
+ switch (opc) {
+ /* Bxx (d8,PC) */
+ case 0xc0 ... 0xca:
+ x8 = 2;
+ if (cond_table[regs->epsw & 0xf] & (1 << (opc & 0xf)))
+ x8 = (s8)pc[1];
+ next = pc + x8;
+ *flags |= SINGLESTEP_BRANCH;
+ break;
+
+ /* JMP (d16,PC) or CALL (d16,PC) */
+ case 0xcc:
+ case 0xcd:
+ READ_WORD16(pc + 1, &x16);
+ next = pc + x16;
+ *flags |= SINGLESTEP_BRANCH;
+ break;
+
+ /* JMP (d32,PC) or CALL (d32,PC) */
+ case 0xdc:
+ case 0xdd:
+ READ_WORD32(pc + 1, &x32);
+ next = pc + x32;
+ *flags |= SINGLESTEP_BRANCH;
+ break;
+
+ /* RETF */
+ case 0xde:
+ next = (u8 *)regs->mdr;
+ *flags &= ~SINGLESTEP_PCREL;
+ *flags |= SINGLESTEP_BRANCH;
+ break;
+
+ /* RET */
+ case 0xdf:
+ sp += pc[2];
+ READ_WORD32(sp, &x32);
+ next = (u8 *)x32;
+ *flags &= ~SINGLESTEP_PCREL;
+ *flags |= SINGLESTEP_BRANCH;
+ break;
+
+ case 0xf0:
+ next = pc + 2;
+ opc = pc[1];
+ if (opc >= 0xf0 && opc <= 0xf7) {
+ /* JMP (An) / CALLS (An) */
+ switch (opc & 3) {
+ case 0:
+ next = (u8 *)regs->a0;
+ break;
+ case 1:
+ next = (u8 *)regs->a1;
+ break;
+ case 2:
+ next = (u8 *)regs->a2;
+ break;
+ case 3:
+ next = (u8 *)regs->a3;
+ break;
+ }
+ *flags &= ~SINGLESTEP_PCREL;
+ *flags |= SINGLESTEP_BRANCH;
+ } else if (opc == 0xfc) {
+ /* RETS */
+ READ_WORD32(sp, &x32);
+ next = (u8 *)x32;
+ *flags &= ~SINGLESTEP_PCREL;
+ *flags |= SINGLESTEP_BRANCH;
+ } else if (opc == 0xfd) {
+ /* RTI */
+ READ_WORD32(sp + 4, &x32);
+ next = (u8 *)x32;
+ *flags &= ~SINGLESTEP_PCREL;
+ *flags |= SINGLESTEP_BRANCH;
+ }
+ break;
+
+ /* potential 3-byte conditional branches */
+ case 0xf8:
+ next = pc + 3;
+ opc = pc[1];
+ if (opc >= 0xe8 && opc <= 0xeb &&
+ (cond_table[regs->epsw & 0xf] &
+ (1 << ((opc & 0xf) + 3)))
+ ) {
+ READ_BYTE(pc+2, &x8);
+ next = pc + x8;
+ *flags |= SINGLESTEP_BRANCH;
+ }
+ break;
+
+ case 0xfa:
+ if (pc[1] == 0xff) {
+ /* CALLS (d16,PC) */
+ READ_WORD16(pc + 2, &x16);
+ next = pc + x16;
+ } else
+ next = pc + 4;
+ *flags |= SINGLESTEP_BRANCH;
+ break;
+
+ case 0xfc:
+ x32 = 6;
+ if (pc[1] == 0xff) {
+ /* CALLS (d32,PC) */
+ READ_WORD32(pc + 2, &x32);
+ }
+ next = pc + x32;
+ *flags |= SINGLESTEP_BRANCH;
+ break;
+ /* LXX (d8,PC) */
+ /* SETLB - loads the next four bytes into the LIR reg */
+ case 0xd0 ... 0xda:
+ case 0xdb:
+ panic("Can't singlestep Lxx/SETLB\n");
+ break;
+ }
+ }
+ return (unsigned)next;
+
+}
+
+/*
+ * set up out of place singlestep of some branching instructions
+ */
+static unsigned __kprobes singlestep_branch_setup(struct pt_regs *regs)
+{
+ u8 opc, *pc, *sp, *next;
+
+ next = NULL;
+ pc = (u8 *) regs->pc;
+ sp = (u8 *) (regs + 1);
+
+ switch (pc[0]) {
+ case 0xc0 ... 0xca: /* Bxx (d8,PC) */
+ case 0xcc: /* JMP (d16,PC) */
+ case 0xdc: /* JMP (d32,PC) */
+ case 0xf8: /* Bxx (d8,PC) 3-byte version */
+ /* don't really need to do anything except cause trap */
+ next = pc;
+ break;
+
+ case 0xcd: /* CALL (d16,PC) */
+ pc[1] = 5;
+ pc[2] = 0;
+ next = pc + 5;
+ break;
+
+ case 0xdd: /* CALL (d32,PC) */
+ pc[1] = 7;
+ pc[2] = 0;
+ pc[3] = 0;
+ pc[4] = 0;
+ next = pc + 7;
+ break;
+
+ case 0xde: /* RETF */
+ next = pc + 3;
+ regs->mdr = (unsigned) next;
+ break;
+
+ case 0xdf: /* RET */
+ sp += pc[2];
+ next = pc + 3;
+ *(unsigned *)sp = (unsigned) next;
+ break;
+
+ case 0xf0:
+ next = pc + 2;
+ opc = pc[1];
+ if (opc >= 0xf0 && opc <= 0xf3) {
+ /* CALLS (An) */
+ /* use CALLS (d16,PC) to avoid mucking with An */
+ pc[0] = 0xfa;
+ pc[1] = 0xff;
+ pc[2] = 4;
+ pc[3] = 0;
+ next = pc + 4;
+ } else if (opc >= 0xf4 && opc <= 0xf7) {
+ /* JMP (An) */
+ next = pc;
+ } else if (opc == 0xfc) {
+ /* RETS */
+ next = pc + 2;
+ *(unsigned *) sp = (unsigned) next;
+ } else if (opc == 0xfd) {
+ /* RTI */
+ next = pc + 2;
+ *(unsigned *)(sp + 4) = (unsigned) next;
+ }
+ break;
+
+ case 0xfa: /* CALLS (d16,PC) */
+ pc[2] = 4;
+ pc[3] = 0;
+ next = pc + 4;
+ break;
+
+ case 0xfc: /* CALLS (d32,PC) */
+ pc[2] = 6;
+ pc[3] = 0;
+ pc[4] = 0;
+ pc[5] = 0;
+ next = pc + 6;
+ break;
+
+ case 0xd0 ... 0xda: /* LXX (d8,PC) */
+ case 0xdb: /* SETLB */
+ panic("Can't singlestep Lxx/SETLB\n");
+ }
+
+ return (unsigned) next;
+}
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+ return 0;
+}
+
+void __kprobes arch_copy_kprobe(struct kprobe *p)
+{
+ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE);
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+ *p->addr = BREAKPOINT_INSTRUCTION;
+ flush_icache_range((unsigned long) p->addr,
+ (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+ mn10300_dcache_flush();
+ mn10300_icache_inv();
+}
+
+void arch_remove_kprobe(struct kprobe *p)
+{
+}
+
+static inline
+void __kprobes disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
+{
+ *p->addr = p->opcode;
+ regs->pc = (unsigned long) p->addr;
+ mn10300_dcache_flush();
+ mn10300_icache_inv();
+}
+
+static inline
+void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+ unsigned long nextpc;
+
+ current_kprobe_orig_pc = regs->pc;
+ memcpy(current_kprobe_ss_buf, &p->ainsn.insn[0], MAX_INSN_SIZE);
+ regs->pc = (unsigned long) current_kprobe_ss_buf;
+
+ nextpc = find_nextpc(regs, &current_kprobe_ss_flags);
+ if (current_kprobe_ss_flags & SINGLESTEP_PCREL)
+ current_kprobe_next_pc =
+ current_kprobe_orig_pc + (nextpc - regs->pc);
+ else
+ current_kprobe_next_pc = nextpc;
+
+ /* branching instructions need special handling */
+ if (current_kprobe_ss_flags & SINGLESTEP_BRANCH)
+ nextpc = singlestep_branch_setup(regs);
+
+ current_kprobe_bp_addr = nextpc;
+
+ *(u8 *) nextpc = BREAKPOINT_INSTRUCTION;
+ mn10300_dcache_flush_range2((unsigned) current_kprobe_ss_buf,
+ sizeof(current_kprobe_ss_buf));
+ mn10300_icache_inv();
+}
+
+static inline int __kprobes kprobe_handler(struct pt_regs *regs)
+{
+ struct kprobe *p;
+ int ret = 0;
+ unsigned int *addr = (unsigned int *) regs->pc;
+
+ /* We're in an interrupt, but this is clear and BUG()-safe. */
+ preempt_disable();
+
+ /* Check we're not actually recursing */
+ if (kprobe_running()) {
+ /* We *are* holding lock here, so this is safe.
+ Disarm the probe we just hit, and ignore it. */
+ p = get_kprobe(addr);
+ if (p) {
+ disarm_kprobe(p, regs);
+ ret = 1;
+ } else {
+ p = current_kprobe;
+ if (p->break_handler && p->break_handler(p, regs))
+ goto ss_probe;
+ }
+ /* If it's not ours, can't be delete race, (we hold lock). */
+ goto no_kprobe;
+ }
+
+ p = get_kprobe(addr);
+ if (!p) {
+ if (*addr != BREAKPOINT_INSTRUCTION) {
+ /* The breakpoint instruction was removed right after
+ * we hit it. Another cpu has removed either a
+ * probepoint or a debugger breakpoint at this address.
+ * In either case, no further handling of this
+ * interrupt is appropriate.
+ */
+ ret = 1;
+ }
+ /* Not one of ours: let kernel handle it */
+ goto no_kprobe;
+ }
+
+ kprobe_status = KPROBE_HIT_ACTIVE;
+ current_kprobe = p;
+ if (p->pre_handler(p, regs)) {
+ /* handler has already set things up, so skip ss setup */
+ return 1;
+ }
+
+ss_probe:
+ prepare_singlestep(p, regs);
+ kprobe_status = KPROBE_HIT_SS;
+ return 1;
+
+no_kprobe:
+ preempt_enable_no_resched();
+ return ret;
+}
+
+/*
+ * Called after single-stepping. p->addr is the address of the
+ * instruction whose first byte has been replaced by the "breakpoint"
+ * instruction. To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction. The address of this
+ * copy is p->ainsn.insn.
+ */
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+ /* we may need to fixup regs/stack after singlestepping a call insn */
+ if (current_kprobe_ss_flags & SINGLESTEP_BRANCH) {
+ regs->pc = current_kprobe_orig_pc;
+ switch (p->ainsn.insn[0]) {
+ case 0xcd: /* CALL (d16,PC) */
+ *(unsigned *) regs->sp = regs->mdr = regs->pc + 5;
+ break;
+ case 0xdd: /* CALL (d32,PC) */
+ /* fixup mdr and return address on stack */
+ *(unsigned *) regs->sp = regs->mdr = regs->pc + 7;
+ break;
+ case 0xf0:
+ if (p->ainsn.insn[1] >= 0xf0 &&
+ p->ainsn.insn[1] <= 0xf3) {
+ /* CALLS (An) */
+ /* fixup MDR and return address on stack */
+ regs->mdr = regs->pc + 2;
+ *(unsigned *) regs->sp = regs->mdr;
+ }
+ break;
+
+ case 0xfa: /* CALLS (d16,PC) */
+ /* fixup MDR and return address on stack */
+ *(unsigned *) regs->sp = regs->mdr = regs->pc + 4;
+ break;
+
+ case 0xfc: /* CALLS (d32,PC) */
+ /* fixup MDR and return address on stack */
+ *(unsigned *) regs->sp = regs->mdr = regs->pc + 6;
+ break;
+ }
+ }
+
+ regs->pc = current_kprobe_next_pc;
+ current_kprobe_bp_addr = 0;
+}
+
+static inline int __kprobes post_kprobe_handler(struct pt_regs *regs)
+{
+ if (!kprobe_running())
+ return 0;
+
+ if (current_kprobe->post_handler)
+ current_kprobe->post_handler(current_kprobe, regs, 0);
+
+ resume_execution(current_kprobe, regs);
+ reset_current_kprobe();
+ preempt_enable_no_resched();
+ return 1;
+}
+
+/* Interrupts disabled, kprobe_lock held. */
+static inline
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+ if (current_kprobe->fault_handler &&
+ current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+ return 1;
+
+ if (kprobe_status & KPROBE_HIT_SS) {
+ resume_execution(current_kprobe, regs);
+ reset_current_kprobe();
+ preempt_enable_no_resched();
+ }
+ return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ struct die_args *args = data;
+
+ switch (val) {
+ case DIE_BREAKPOINT:
+ if (current_kprobe_bp_addr != args->regs->pc) {
+ if (kprobe_handler(args->regs))
+ return NOTIFY_STOP;
+ } else {
+ if (post_kprobe_handler(args->regs))
+ return NOTIFY_STOP;
+ }
+ break;
+ case DIE_GPF:
+ if (kprobe_running() &&
+ kprobe_fault_handler(args->regs, args->trapnr))
+ return NOTIFY_STOP;
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+/* Jprobes support. */
+static struct pt_regs jprobe_saved_regs;
+static struct pt_regs *jprobe_saved_regs_location;
+static kprobe_opcode_t jprobe_saved_stack[MAX_STACK_SIZE];
+
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct jprobe *jp = container_of(p, struct jprobe, kp);
+
+ jprobe_saved_regs_location = regs;
+ memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs));
+
+ /* Save a whole stack frame, this gets arguments
+ * pushed onto the stack after using up all the
+ * arg registers.
+ */
+ memcpy(&jprobe_saved_stack, regs + 1, sizeof(jprobe_saved_stack));
+
+ /* setup return addr to the jprobe handler routine */
+ regs->pc = (unsigned long) jp->entry;
+ return 1;
+}
+
+void __kprobes jprobe_return(void)
+{
+ void *orig_sp = jprobe_saved_regs_location + 1;
+
+ preempt_enable_no_resched();
+ asm volatile(" mov %0,sp\n"
+ ".globl jprobe_return_bp_addr\n"
+ "jprobe_return_bp_addr:\n\t"
+ " .byte 0xff\n"
+ : : "d" (orig_sp));
+}
+
+extern void jprobe_return_bp_addr(void);
+
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ u8 *addr = (u8 *) regs->pc;
+
+ if (addr == (u8 *) jprobe_return_bp_addr) {
+ if (jprobe_saved_regs_location != regs) {
+ printk(KERN_ERR"JPROBE:"
+ " Current regs (%p) does not match saved regs"
+ " (%p).\n",
+ regs, jprobe_saved_regs_location);
+ BUG();
+ }
+
+ /* Restore old register state.
+ */
+ memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
+
+ memcpy(regs + 1, &jprobe_saved_stack,
+ sizeof(jprobe_saved_stack));
+ return 1;
+ }
+ return 0;
+}
+
+int __init arch_init_kprobes(void)
+{
+ return 0;
+}
diff --git a/arch/mn10300/kernel/kthread.S b/arch/mn10300/kernel/kthread.S
new file mode 100644
index 00000000000..b5ae467ac5e
--- /dev/null
+++ b/arch/mn10300/kernel/kthread.S
@@ -0,0 +1,31 @@
+/* MN10300 Kernel thread trampoline function
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by Mark Salter (msalter@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+ .text
+
+###############################################################################
+#
+# kernel_thread_helper - trampoline for kernel_thread()
+#
+# On entry:
+# A2 = address of function to call
+# D2 = function argument
+#
+###############################################################################
+ .globl kernel_thread_helper
+ .type kernel_thread_helper,@function
+kernel_thread_helper:
+ mov do_exit,d1
+ mov d1,(sp)
+ mov d1,mdr
+ mov d2,d0
+ jmp (a2)
+
+ .size kernel_thread_helper,.-kernel_thread_helper
diff --git a/arch/mn10300/kernel/mn10300-debug.c b/arch/mn10300/kernel/mn10300-debug.c
new file mode 100644
index 00000000000..bd8196478cb
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-debug.c
@@ -0,0 +1,58 @@
+/* Debugging stuff for the MN10300-based processors
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <asm/serial-regs.h>
+
+#undef MN10300_CONSOLE_ON_SERIO
+
+/*
+ * write a string directly through one of the serial ports on-board the MN10300
+ */
+#ifdef MN10300_CONSOLE_ON_SERIO
+void debug_to_serial_mnser(const char *p, int n)
+{
+ char ch;
+
+ for (; n > 0; n--) {
+ ch = *p++;
+
+#if MN10300_CONSOLE_ON_SERIO == 0
+ while (SC0STR & (SC01STR_TBF)) continue;
+ SC0TXB = ch;
+ while (SC0STR & (SC01STR_TBF)) continue;
+ if (ch == 0x0a) {
+ SC0TXB = 0x0d;
+ while (SC0STR & (SC01STR_TBF)) continue;
+ }
+
+#elif MN10300_CONSOLE_ON_SERIO == 1
+ while (SC1STR & (SC01STR_TBF)) continue;
+ SC1TXB = ch;
+ while (SC1STR & (SC01STR_TBF)) continue;
+ if (ch == 0x0a) {
+ SC1TXB = 0x0d;
+ while (SC1STR & (SC01STR_TBF)) continue;
+ }
+
+#elif MN10300_CONSOLE_ON_SERIO == 2
+ while (SC2STR & (SC2STR_TBF)) continue;
+ SC2TXB = ch;
+ while (SC2STR & (SC2STR_TBF)) continue;
+ if (ch == 0x0a) {
+ SC2TXB = 0x0d;
+ while (SC2STR & (SC2STR_TBF)) continue;
+ }
+
+#endif
+ }
+}
+#endif
+
diff --git a/arch/mn10300/kernel/mn10300-serial-low.S b/arch/mn10300/kernel/mn10300-serial-low.S
new file mode 100644
index 00000000000..ef3f4c1df2a
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-serial-low.S
@@ -0,0 +1,191 @@
+###############################################################################
+#
+# Virtual DMA driver for MN10300 serial ports
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/smp.h>
+#include <asm/cpu-regs.h>
+#include <asm/frame.inc>
+#include <asm/timer-regs.h>
+#include <asm/proc/cache.h>
+#include <asm/unit/timex.h>
+#include "mn10300-serial.h"
+
+#define SCxCTR 0x00
+#define SCxICR 0x04
+#define SCxTXB 0x08
+#define SCxRXB 0x09
+#define SCxSTR 0x0c
+#define SCxTIM 0x0d
+
+ .text
+
+###############################################################################
+#
+# serial port interrupt virtual DMA entry point
+# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
+#
+###############################################################################
+ .balign L1_CACHE_BYTES
+ENTRY(mn10300_serial_vdma_interrupt)
+ or EPSW_IE,psw # permit overriding by
+ # debugging interrupts
+ movm [d2,d3,a2,a3,exreg0],(sp)
+
+ movhu (IAGR),a2 # see if which interrupt is
+ # pending
+ and IAGR_GN,a2
+ add a2,a2
+ add mn10300_serial_int_tbl,a2
+
+ mov (a2+),a3
+ mov (__iobase,a3),e2
+ mov (a2),a2
+ jmp (a2)
+
+###############################################################################
+#
+# serial port receive interrupt virtual DMA entry point
+# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
+# - stores data/status byte pairs in the ring buffer
+# - induces a scheduler tick timer interrupt when done, which we then subvert
+# on entry:
+# A3 struct mn10300_serial_port *
+# E2 I/O port base
+#
+###############################################################################
+ENTRY(mn10300_serial_vdma_rx_handler)
+ mov (__rx_icr,a3),e3
+ mov GxICR_DETECT,d2
+ movbu d2,(e3) # ACK the interrupt
+ movhu (e3),d2 # flush
+
+ mov (__rx_inp,a3),d3
+ mov d3,a2
+ add 2,d3
+ and MNSC_BUFFER_SIZE-1,d3
+ mov (__rx_outp,a3),d2
+ cmp d3,d2
+ beq mnsc_vdma_rx_overflow
+
+ mov (__rx_buffer,a3),d2
+ add d2,a2
+ movhu (SCxSTR,e2),d2
+ movbu d2,(1,a2)
+ movbu (SCxRXB,e2),d2
+ movbu d2,(a2)
+ mov d3,(__rx_inp,a3)
+ bset MNSCx_RX_AVAIL,(__intr_flags,a3)
+
+mnsc_vdma_rx_done:
+ mov (__tm_icr,a3),a2
+ mov GxICR_LEVEL_6|GxICR_ENABLE|GxICR_REQUEST|GxICR_DETECT,d2
+ movhu d2,(a2) # request a slow interrupt
+ movhu (a2),d2 # flush
+
+ movm (sp),[d2,d3,a2,a3,exreg0]
+ rti
+
+mnsc_vdma_rx_overflow:
+ bset MNSCx_RX_OVERF,(__intr_flags,a3)
+ bra mnsc_vdma_rx_done
+
+###############################################################################
+#
+# serial port transmit interrupt virtual DMA entry point
+# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
+# - retrieves data bytes from the ring buffer and passes them to the serial port
+# - induces a scheduler tick timer interrupt when done, which we then subvert
+# A3 struct mn10300_serial_port *
+# E2 I/O port base
+#
+###############################################################################
+ .balign L1_CACHE_BYTES
+ENTRY(mn10300_serial_vdma_tx_handler)
+ mov (__tx_icr,a3),e3
+ mov GxICR_DETECT,d2
+ movbu d2,(e3) # ACK the interrupt
+ movhu (e3),d2 # flush
+
+ btst 0x01,(__tx_break,a3) # handle transmit break request
+ bne mnsc_vdma_tx_break
+
+ movbu (SCxSTR,e2),d2 # don't try and transmit a char if the
+ # buffer is not empty
+ btst SC01STR_TBF,d2 # (may have tried to jumpstart)
+ bne mnsc_vdma_tx_noint
+
+ movbu (__tx_xchar,a3),d2 # handle hi-pri XON/XOFF
+ or d2,d2
+ bne mnsc_vdma_tx_xchar
+
+ mov (__tx_info_buffer,a3),a2 # get the uart_info struct for Tx
+ mov (__xmit_tail,a2),d3
+ mov (__xmit_head,a2),d2
+ cmp d3,d2
+ beq mnsc_vdma_tx_empty
+
+ mov (__xmit_buffer,a2),d2 # get a char from the buffer and
+ # transmit it
+ movbu (d3,d2),d2
+ movbu d2,(SCxTXB,e2) # Tx
+
+ inc d3 # advance the buffer pointer
+ and __UART_XMIT_SIZE-1,d3
+ mov (__xmit_head,a2),d2
+ mov d3,(__xmit_tail,a2)
+
+ sub d3,d2 # see if we've written everything
+ beq mnsc_vdma_tx_empty
+
+ and __UART_XMIT_SIZE-1,d2 # see if we just made a hole
+ cmp __UART_XMIT_SIZE-2,d2
+ beq mnsc_vdma_tx_made_hole
+
+mnsc_vdma_tx_done:
+ mov (__tm_icr,a3),a2
+ mov GxICR_LEVEL_6|GxICR_ENABLE|GxICR_REQUEST|GxICR_DETECT,d2
+ movhu d2,(a2) # request a slow interrupt
+ movhu (a2),d2 # flush
+
+mnsc_vdma_tx_noint:
+ movm (sp),[d2,d3,a2,a3,exreg0]
+ rti
+
+mnsc_vdma_tx_empty:
+ mov +(GxICR_LEVEL_1|GxICR_DETECT),d2
+ movhu d2,(e3) # disable the interrupt
+ movhu (e3),d2 # flush
+
+ bset MNSCx_TX_EMPTY,(__intr_flags,a3)
+ bra mnsc_vdma_tx_done
+
+mnsc_vdma_tx_break:
+ movhu (SCxCTR,e2),d2 # turn on break mode
+ or SC01CTR_BKE,d2
+ movhu d2,(SCxCTR,e2)
+ mov +(GxICR_LEVEL_1|GxICR_DETECT),d2
+ movhu d2,(e3) # disable transmit interrupts on this
+ # channel
+ movhu (e3),d2 # flush
+ bra mnsc_vdma_tx_noint
+
+mnsc_vdma_tx_xchar:
+ bclr 0xff,(__tx_xchar,a3)
+ movbu d2,(SCxTXB,e2)
+ bra mnsc_vdma_tx_done
+
+mnsc_vdma_tx_made_hole:
+ bset MNSCx_TX_SPACE,(__intr_flags,a3)
+ bra mnsc_vdma_tx_done
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c
new file mode 100644
index 00000000000..b9c268c6b2f
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-serial.c
@@ -0,0 +1,1480 @@
+/* MN10300 On-chip serial port UART driver
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+static const char serial_name[] = "MN10300 Serial driver";
+static const char serial_version[] = "mn10300_serial-1.0";
+static const char serial_revdate[] = "2007-11-06";
+
+#if defined(CONFIG_MN10300_TTYSM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/circ_buf.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/serial-regs.h>
+#include <asm/unit/timex.h>
+#include "mn10300-serial.h"
+
+static inline __attribute__((format(printf, 1, 2)))
+void no_printk(const char *fmt, ...)
+{
+}
+
+#define kenter(FMT, ...) \
+ printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__)
+#define _enter(FMT, ...) \
+ no_printk(KERN_DEBUG "-->%s(" FMT ")\n", __func__, ##__VA_ARGS__)
+#define kdebug(FMT, ...) \
+ printk(KERN_DEBUG "--- " FMT "\n", ##__VA_ARGS__)
+#define _debug(FMT, ...) \
+ no_printk(KERN_DEBUG "--- " FMT "\n", ##__VA_ARGS__)
+#define kproto(FMT, ...) \
+ printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__)
+#define _proto(FMT, ...) \
+ no_printk(KERN_DEBUG "### MNSERIAL " FMT " ###\n", ##__VA_ARGS__)
+
+#define NR_UARTS 3
+
+#ifdef CONFIG_MN10300_TTYSM_CONSOLE
+static void mn10300_serial_console_write(struct console *co,
+ const char *s, unsigned count);
+static int __init mn10300_serial_console_setup(struct console *co,
+ char *options);
+
+static struct uart_driver mn10300_serial_driver;
+static struct console mn10300_serial_console = {
+ .name = "ttySM",
+ .write = mn10300_serial_console_write,
+ .device = uart_console_device,
+ .setup = mn10300_serial_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &mn10300_serial_driver,
+};
+#endif
+
+static struct uart_driver mn10300_serial_driver = {
+ .owner = NULL,
+ .driver_name = "mn10300-serial",
+ .dev_name = "ttySM",
+ .major = TTY_MAJOR,
+ .minor = 128,
+ .nr = NR_UARTS,
+#ifdef CONFIG_MN10300_TTYSM_CONSOLE
+ .cons = &mn10300_serial_console,
+#endif
+};
+
+static unsigned int mn10300_serial_tx_empty(struct uart_port *);
+static void mn10300_serial_set_mctrl(struct uart_port *, unsigned int mctrl);
+static unsigned int mn10300_serial_get_mctrl(struct uart_port *);
+static void mn10300_serial_stop_tx(struct uart_port *);
+static void mn10300_serial_start_tx(struct uart_port *);
+static void mn10300_serial_send_xchar(struct uart_port *, char ch);
+static void mn10300_serial_stop_rx(struct uart_port *);
+static void mn10300_serial_enable_ms(struct uart_port *);
+static void mn10300_serial_break_ctl(struct uart_port *, int ctl);
+static int mn10300_serial_startup(struct uart_port *);
+static void mn10300_serial_shutdown(struct uart_port *);
+static void mn10300_serial_set_termios(struct uart_port *,
+ struct ktermios *new,
+ struct ktermios *old);
+static const char *mn10300_serial_type(struct uart_port *);
+static void mn10300_serial_release_port(struct uart_port *);
+static int mn10300_serial_request_port(struct uart_port *);
+static void mn10300_serial_config_port(struct uart_port *, int);
+static int mn10300_serial_verify_port(struct uart_port *,
+ struct serial_struct *);
+
+static const struct uart_ops mn10300_serial_ops = {
+ .tx_empty = mn10300_serial_tx_empty,
+ .set_mctrl = mn10300_serial_set_mctrl,
+ .get_mctrl = mn10300_serial_get_mctrl,
+ .stop_tx = mn10300_serial_stop_tx,
+ .start_tx = mn10300_serial_start_tx,
+ .send_xchar = mn10300_serial_send_xchar,
+ .stop_rx = mn10300_serial_stop_rx,
+ .enable_ms = mn10300_serial_enable_ms,
+ .break_ctl = mn10300_serial_break_ctl,
+ .startup = mn10300_serial_startup,
+ .shutdown = mn10300_serial_shutdown,
+ .set_termios = mn10300_serial_set_termios,
+ .type = mn10300_serial_type,
+ .release_port = mn10300_serial_release_port,
+ .request_port = mn10300_serial_request_port,
+ .config_port = mn10300_serial_config_port,
+ .verify_port = mn10300_serial_verify_port,
+};
+
+static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id);
+
+/*
+ * the first on-chip serial port: ttySM0 (aka SIF0)
+ */
+#ifdef CONFIG_MN10300_TTYSM0
+struct mn10300_serial_port mn10300_serial_port_sif0 = {
+ .uart.ops = &mn10300_serial_ops,
+ .uart.membase = (void __iomem *) &SC0CTR,
+ .uart.mapbase = (unsigned long) &SC0CTR,
+ .uart.iotype = UPIO_MEM,
+ .uart.irq = 0,
+ .uart.uartclk = 0, /* MN10300_IOCLK, */
+ .uart.fifosize = 1,
+ .uart.flags = UPF_BOOT_AUTOCONF,
+ .uart.line = 0,
+ .uart.type = PORT_MN10300,
+ .uart.lock =
+ __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif0.uart.lock),
+ .name = "ttySM0",
+ ._iobase = &SC0CTR,
+ ._control = &SC0CTR,
+ ._status = (volatile u8 *) &SC0STR,
+ ._intr = &SC0ICR,
+ ._rxb = &SC0RXB,
+ ._txb = &SC0TXB,
+ .rx_name = "ttySM0/Rx",
+ .tx_name = "ttySM0/Tx",
+#ifdef CONFIG_MN10300_TTYSM0_TIMER8
+ .tm_name = "ttySM0/Timer8",
+ ._tmxmd = &TM8MD,
+ ._tmxbr = &TM8BR,
+ ._tmicr = &TM8ICR,
+ .tm_irq = TM8IRQ,
+ .div_timer = MNSCx_DIV_TIMER_16BIT,
+#else /* CONFIG_MN10300_TTYSM0_TIMER2 */
+ .tm_name = "ttySM0/Timer2",
+ ._tmxmd = &TM2MD,
+ ._tmxbr = (volatile u16 *) &TM2BR,
+ ._tmicr = &TM2ICR,
+ .tm_irq = TM2IRQ,
+ .div_timer = MNSCx_DIV_TIMER_8BIT,
+#endif
+ .rx_irq = SC0RXIRQ,
+ .tx_irq = SC0TXIRQ,
+ .rx_icr = &GxICR(SC0RXIRQ),
+ .tx_icr = &GxICR(SC0TXIRQ),
+ .clock_src = MNSCx_CLOCK_SRC_IOCLK,
+ .options = 0,
+#ifdef CONFIG_GDBSTUB_ON_TTYSM0
+ .gdbstub = 1,
+#endif
+};
+#endif /* CONFIG_MN10300_TTYSM0 */
+
+/*
+ * the second on-chip serial port: ttySM1 (aka SIF1)
+ */
+#ifdef CONFIG_MN10300_TTYSM1
+struct mn10300_serial_port mn10300_serial_port_sif1 = {
+ .uart.ops = &mn10300_serial_ops,
+ .uart.membase = (void __iomem *) &SC1CTR,
+ .uart.mapbase = (unsigned long) &SC1CTR,
+ .uart.iotype = UPIO_MEM,
+ .uart.irq = 0,
+ .uart.uartclk = 0, /* MN10300_IOCLK, */
+ .uart.fifosize = 1,
+ .uart.flags = UPF_BOOT_AUTOCONF,
+ .uart.line = 1,
+ .uart.type = PORT_MN10300,
+ .uart.lock =
+ __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif1.uart.lock),
+ .name = "ttySM1",
+ ._iobase = &SC1CTR,
+ ._control = &SC1CTR,
+ ._status = (volatile u8 *) &SC1STR,
+ ._intr = &SC1ICR,
+ ._rxb = &SC1RXB,
+ ._txb = &SC1TXB,
+ .rx_name = "ttySM1/Rx",
+ .tx_name = "ttySM1/Tx",
+#ifdef CONFIG_MN10300_TTYSM1_TIMER9
+ .tm_name = "ttySM1/Timer9",
+ ._tmxmd = &TM9MD,
+ ._tmxbr = &TM9BR,
+ ._tmicr = &TM9ICR,
+ .tm_irq = TM9IRQ,
+ .div_timer = MNSCx_DIV_TIMER_16BIT,
+#else /* CONFIG_MN10300_TTYSM1_TIMER3 */
+ .tm_name = "ttySM1/Timer3",
+ ._tmxmd = &TM3MD,
+ ._tmxbr = (volatile u16 *) &TM3BR,
+ ._tmicr = &TM3ICR,
+ .tm_irq = TM3IRQ,
+ .div_timer = MNSCx_DIV_TIMER_8BIT,
+#endif
+ .rx_irq = SC1RXIRQ,
+ .tx_irq = SC1TXIRQ,
+ .rx_icr = &GxICR(SC1RXIRQ),
+ .tx_icr = &GxICR(SC1TXIRQ),
+ .clock_src = MNSCx_CLOCK_SRC_IOCLK,
+ .options = 0,
+#ifdef CONFIG_GDBSTUB_ON_TTYSM1
+ .gdbstub = 1,
+#endif
+};
+#endif /* CONFIG_MN10300_TTYSM1 */
+
+/*
+ * the third on-chip serial port: ttySM2 (aka SIF2)
+ */
+#ifdef CONFIG_MN10300_TTYSM2
+struct mn10300_serial_port mn10300_serial_port_sif2 = {
+ .uart.ops = &mn10300_serial_ops,
+ .uart.membase = (void __iomem *) &SC2CTR,
+ .uart.mapbase = (unsigned long) &SC2CTR,
+ .uart.iotype = UPIO_MEM,
+ .uart.irq = 0,
+ .uart.uartclk = 0, /* MN10300_IOCLK, */
+ .uart.fifosize = 1,
+ .uart.flags = UPF_BOOT_AUTOCONF,
+ .uart.line = 2,
+#ifdef CONFIG_MN10300_TTYSM2_CTS
+ .uart.type = PORT_MN10300_CTS,
+#else
+ .uart.type = PORT_MN10300,
+#endif
+ .uart.lock =
+ __SPIN_LOCK_UNLOCKED(mn10300_serial_port_sif2.uart.lock),
+ .name = "ttySM2",
+ .rx_name = "ttySM2/Rx",
+ .tx_name = "ttySM2/Tx",
+ .tm_name = "ttySM2/Timer10",
+ ._iobase = &SC2CTR,
+ ._control = &SC2CTR,
+ ._status = &SC2STR,
+ ._intr = &SC2ICR,
+ ._rxb = &SC2RXB,
+ ._txb = &SC2TXB,
+ ._tmxmd = &TM10MD,
+ ._tmxbr = &TM10BR,
+ ._tmicr = &TM10ICR,
+ .tm_irq = TM10IRQ,
+ .div_timer = MNSCx_DIV_TIMER_16BIT,
+ .rx_irq = SC2RXIRQ,
+ .tx_irq = SC2TXIRQ,
+ .rx_icr = &GxICR(SC2RXIRQ),
+ .tx_icr = &GxICR(SC2TXIRQ),
+ .clock_src = MNSCx_CLOCK_SRC_IOCLK,
+#ifdef CONFIG_MN10300_TTYSM2_CTS
+ .options = MNSCx_OPT_CTS,
+#else
+ .options = 0,
+#endif
+#ifdef CONFIG_GDBSTUB_ON_TTYSM2
+ .gdbstub = 1,
+#endif
+};
+#endif /* CONFIG_MN10300_TTYSM2 */
+
+
+/*
+ * list of available serial ports
+ */
+struct mn10300_serial_port *mn10300_serial_ports[NR_UARTS + 1] = {
+#ifdef CONFIG_MN10300_TTYSM0
+ [0] = &mn10300_serial_port_sif0,
+#endif
+#ifdef CONFIG_MN10300_TTYSM1
+ [1] = &mn10300_serial_port_sif1,
+#endif
+#ifdef CONFIG_MN10300_TTYSM2
+ [2] = &mn10300_serial_port_sif2,
+#endif
+ [NR_UARTS] = NULL,
+};
+
+
+/*
+ * we abuse the serial ports' baud timers' interrupt lines to get the ability
+ * to deliver interrupts to userspace as we use the ports' interrupt lines to
+ * do virtual DMA on account of the ports having no hardware FIFOs
+ *
+ * we can generate an interrupt manually in the assembly stubs by writing to
+ * the enable and detect bits in the interrupt control register, so all we need
+ * to do here is disable the interrupt line
+ *
+ * note that we can't just leave the line enabled as the baud rate timer *also*
+ * generates interrupts
+ */
+static void mn10300_serial_mask_ack(unsigned int irq)
+{
+ u16 tmp;
+ GxICR(irq) = GxICR_LEVEL_6;
+ tmp = GxICR(irq); /* flush write buffer */
+}
+
+static void mn10300_serial_nop(unsigned int irq)
+{
+}
+
+static struct irq_chip mn10300_serial_pic = {
+ .name = "mnserial",
+ .ack = mn10300_serial_mask_ack,
+ .mask = mn10300_serial_mask_ack,
+ .mask_ack = mn10300_serial_mask_ack,
+ .unmask = mn10300_serial_nop,
+ .end = mn10300_serial_nop,
+};
+
+
+/*
+ * serial virtual DMA interrupt jump table
+ */
+struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS];
+
+static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port)
+{
+ u16 x;
+ *port->tx_icr = GxICR_LEVEL_1 | GxICR_DETECT;
+ x = *port->tx_icr;
+}
+
+static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port)
+{
+ u16 x;
+ *port->tx_icr = GxICR_LEVEL_1 | GxICR_ENABLE;
+ x = *port->tx_icr;
+}
+
+static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port)
+{
+ u16 x;
+ *port->rx_icr = GxICR_LEVEL_1 | GxICR_DETECT;
+ x = *port->rx_icr;
+}
+
+/*
+ * multi-bit equivalent of test_and_clear_bit()
+ */
+static int mask_test_and_clear(volatile u8 *ptr, u8 mask)
+{
+ u32 epsw;
+ asm volatile(" bclr %1,(%2) \n"
+ " mov epsw,%0 \n"
+ : "=d"(epsw) : "d"(mask), "a"(ptr));
+ return !(epsw & EPSW_FLAG_Z);
+}
+
+/*
+ * receive chars from the ring buffer for this serial port
+ * - must do break detection here (not done in the UART)
+ */
+static void mn10300_serial_receive_interrupt(struct mn10300_serial_port *port)
+{
+ struct uart_icount *icount = &port->uart.icount;
+ struct tty_struct *tty = port->uart.info->tty;
+ unsigned ix;
+ int count;
+ u8 st, ch, push, status, overrun;
+
+ _enter("%s", port->name);
+
+ push = 0;
+
+ count = CIRC_CNT(port->rx_inp, port->rx_outp, MNSC_BUFFER_SIZE);
+ count = tty_buffer_request_room(tty, count);
+ if (count == 0) {
+ if (!tty->low_latency)
+ tty_flip_buffer_push(tty);
+ return;
+ }
+
+try_again:
+ /* pull chars out of the hat */
+ ix = port->rx_outp;
+ if (ix == port->rx_inp) {
+ if (push && !tty->low_latency)
+ tty_flip_buffer_push(tty);
+ return;
+ }
+
+ ch = port->rx_buffer[ix++];
+ st = port->rx_buffer[ix++];
+ smp_rmb();
+ port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
+ port->uart.icount.rx++;
+
+ st &= SC01STR_FEF | SC01STR_PEF | SC01STR_OEF;
+ status = 0;
+ overrun = 0;
+
+ /* the UART doesn't detect BREAK, so we have to do that ourselves
+ * - it starts as a framing error on a NUL character
+ * - then we count another two NUL characters before issuing TTY_BREAK
+ * - then we end on a normal char or one that has all the bottom bits
+ * zero and the top bits set
+ */
+ switch (port->rx_brk) {
+ case 0:
+ /* not breaking at the moment */
+ break;
+
+ case 1:
+ if (st & SC01STR_FEF && ch == 0) {
+ port->rx_brk = 2;
+ goto try_again;
+ }
+ goto not_break;
+
+ case 2:
+ if (st & SC01STR_FEF && ch == 0) {
+ port->rx_brk = 3;
+ _proto("Rx Break Detected");
+ icount->brk++;
+ if (uart_handle_break(&port->uart))
+ goto ignore_char;
+ status |= 1 << TTY_BREAK;
+ goto insert;
+ }
+ goto not_break;
+
+ default:
+ if (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF))
+ goto try_again; /* still breaking */
+
+ port->rx_brk = 0; /* end of the break */
+
+ switch (ch) {
+ case 0xFF:
+ case 0xFE:
+ case 0xFC:
+ case 0xF8:
+ case 0xF0:
+ case 0xE0:
+ case 0xC0:
+ case 0x80:
+ case 0x00:
+ /* discard char at probable break end */
+ goto try_again;
+ }
+ break;
+ }
+
+process_errors:
+ /* handle framing error */
+ if (st & SC01STR_FEF) {
+ if (ch == 0) {
+ /* framing error with NUL char is probably a BREAK */
+ port->rx_brk = 1;
+ goto try_again;
+ }
+
+ _proto("Rx Framing Error");
+ icount->frame++;
+ status |= 1 << TTY_FRAME;
+ }
+
+ /* handle parity error */
+ if (st & SC01STR_PEF) {
+ _proto("Rx Parity Error");
+ icount->parity++;
+ status = TTY_PARITY;
+ }
+
+ /* handle normal char */
+ if (status == 0) {
+ if (uart_handle_sysrq_char(&port->uart, ch))
+ goto ignore_char;
+ status = (1 << TTY_NORMAL);
+ }
+
+ /* handle overrun error */
+ if (st & SC01STR_OEF) {
+ if (port->rx_brk)
+ goto try_again;
+
+ _proto("Rx Overrun Error");
+ icount->overrun++;
+ overrun = 1;
+ }
+
+insert:
+ status &= port->uart.read_status_mask;
+
+ if (!overrun && !(status & port->uart.ignore_status_mask)) {
+ int flag;
+
+ if (status & (1 << TTY_BREAK))
+ flag = TTY_BREAK;
+ else if (status & (1 << TTY_PARITY))
+ flag = TTY_PARITY;
+ else if (status & (1 << TTY_FRAME))
+ flag = TTY_FRAME;
+ else
+ flag = TTY_NORMAL;
+
+ tty_insert_flip_char(tty, ch, flag);
+ }
+
+ /* overrun is special, since it's reported immediately, and doesn't
+ * affect the current character
+ */
+ if (overrun)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+ count--;
+ if (count <= 0) {
+ if (!tty->low_latency)
+ tty_flip_buffer_push(tty);
+ return;
+ }
+
+ignore_char:
+ push = 1;
+ goto try_again;
+
+not_break:
+ port->rx_brk = 0;
+ goto process_errors;
+}
+
+/*
+ * handle an interrupt from the serial transmission "virtual DMA" driver
+ * - note: the interrupt routine will disable its own interrupts when the Tx
+ * buffer is empty
+ */
+static void mn10300_serial_transmit_interrupt(struct mn10300_serial_port *port)
+{
+ _enter("%s", port->name);
+
+ if (uart_tx_stopped(&port->uart) ||
+ uart_circ_empty(&port->uart.info->xmit))
+ mn10300_serial_dis_tx_intr(port);
+
+ if (uart_circ_chars_pending(&port->uart.info->xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&port->uart);
+}
+
+/*
+ * deal with a change in the status of the CTS line
+ */
+static void mn10300_serial_cts_changed(struct mn10300_serial_port *port, u8 st)
+{
+ u16 ctr;
+
+ port->tx_cts = st;
+ port->uart.icount.cts++;
+
+ /* flip the CTS state selector flag to interrupt when it changes
+ * back */
+ ctr = *port->_control;
+ ctr ^= SC2CTR_TWS;
+ *port->_control = ctr;
+
+ uart_handle_cts_change(&port->uart, st & SC2STR_CTS);
+ wake_up_interruptible(&port->uart.info->delta_msr_wait);
+}
+
+/*
+ * handle a virtual interrupt generated by the lower level "virtual DMA"
+ * routines (irq is the baud timer interrupt)
+ */
+static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id)
+{
+ struct mn10300_serial_port *port = dev_id;
+ u8 st;
+
+ spin_lock(&port->uart.lock);
+
+ if (port->intr_flags) {
+ _debug("INT %s: %x", port->name, port->intr_flags);
+
+ if (mask_test_and_clear(&port->intr_flags, MNSCx_RX_AVAIL))
+ mn10300_serial_receive_interrupt(port);
+
+ if (mask_test_and_clear(&port->intr_flags,
+ MNSCx_TX_SPACE | MNSCx_TX_EMPTY))
+ mn10300_serial_transmit_interrupt(port);
+ }
+
+ /* the only modem control line amongst the whole lot is CTS on
+ * serial port 2 */
+ if (port->type == PORT_MN10300_CTS) {
+ st = *port->_status;
+ if ((port->tx_cts ^ st) & SC2STR_CTS)
+ mn10300_serial_cts_changed(port, st);
+ }
+
+ spin_unlock(&port->uart.lock);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * return indication of whether the hardware transmit buffer is empty
+ */
+static unsigned int mn10300_serial_tx_empty(struct uart_port *_port)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ _enter("%s", port->name);
+
+ return (*port->_status & (SC01STR_TXF | SC01STR_TBF)) ?
+ 0 : TIOCSER_TEMT;
+}
+
+/*
+ * set the modem control lines (we don't have any)
+ */
+static void mn10300_serial_set_mctrl(struct uart_port *_port,
+ unsigned int mctrl)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ _enter("%s,%x", port->name, mctrl);
+}
+
+/*
+ * get the modem control line statuses
+ */
+static unsigned int mn10300_serial_get_mctrl(struct uart_port *_port)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ _enter("%s", port->name);
+
+ if (port->type == PORT_MN10300_CTS && !(*port->_status & SC2STR_CTS))
+ return TIOCM_CAR | TIOCM_DSR;
+
+ return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR;
+}
+
+/*
+ * stop transmitting characters
+ */
+static void mn10300_serial_stop_tx(struct uart_port *_port)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ _enter("%s", port->name);
+
+ /* disable the virtual DMA */
+ mn10300_serial_dis_tx_intr(port);
+}
+
+/*
+ * start transmitting characters
+ * - jump-start transmission if it has stalled
+ * - enable the serial Tx interrupt (used by the virtual DMA controller)
+ * - force an interrupt to happen if necessary
+ */
+static void mn10300_serial_start_tx(struct uart_port *_port)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ u16 x;
+
+ _enter("%s{%lu}",
+ port->name,
+ CIRC_CNT(&port->uart.info->xmit.head,
+ &port->uart.info->xmit.tail,
+ UART_XMIT_SIZE));
+
+ /* kick the virtual DMA controller */
+ x = *port->tx_icr;
+ x |= GxICR_ENABLE;
+
+ if (*port->_status & SC01STR_TBF)
+ x &= ~(GxICR_REQUEST | GxICR_DETECT);
+ else
+ x |= GxICR_REQUEST | GxICR_DETECT;
+
+ _debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx",
+ *port->_control, *port->_intr, *port->_status,
+ *port->_tmxmd, *port->_tmxbr, *port->tx_icr);
+
+ *port->tx_icr = x;
+ x = *port->tx_icr;
+}
+
+/*
+ * transmit a high-priority XON/XOFF character
+ */
+static void mn10300_serial_send_xchar(struct uart_port *_port, char ch)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ _enter("%s,%02x", port->name, ch);
+
+ if (likely(port->gdbstub)) {
+ port->tx_xchar = ch;
+ if (ch)
+ mn10300_serial_en_tx_intr(port);
+ }
+}
+
+/*
+ * stop receiving characters
+ * - called whilst the port is being closed
+ */
+static void mn10300_serial_stop_rx(struct uart_port *_port)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ u16 ctr;
+
+ _enter("%s", port->name);
+
+ ctr = *port->_control;
+ ctr &= ~SC01CTR_RXE;
+ *port->_control = ctr;
+
+ mn10300_serial_dis_rx_intr(port);
+}
+
+/*
+ * enable modem status interrupts
+ */
+static void mn10300_serial_enable_ms(struct uart_port *_port)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ u16 ctr, cts;
+
+ _enter("%s", port->name);
+
+ if (port->type == PORT_MN10300_CTS) {
+ /* want to interrupt when CTS goes low if CTS is now high and
+ * vice versa
+ */
+ port->tx_cts = *port->_status;
+
+ cts = (port->tx_cts & SC2STR_CTS) ?
+ SC2CTR_TWE : SC2CTR_TWE | SC2CTR_TWS;
+
+ ctr = *port->_control;
+ ctr &= ~SC2CTR_TWS;
+ ctr |= cts;
+ *port->_control = ctr;
+
+ mn10300_serial_en_tx_intr(port);
+ }
+}
+
+/*
+ * transmit or cease transmitting a break signal
+ */
+static void mn10300_serial_break_ctl(struct uart_port *_port, int ctl)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ _enter("%s,%d", port->name, ctl);
+
+ if (ctl) {
+ /* tell the virtual DMA handler to assert BREAK */
+ port->tx_break = 1;
+ mn10300_serial_en_tx_intr(port);
+ } else {
+ port->tx_break = 0;
+ *port->_control &= ~SC01CTR_BKE;
+ mn10300_serial_en_tx_intr(port);
+ }
+}
+
+/*
+ * grab the interrupts and enable the port for reception
+ */
+static int mn10300_serial_startup(struct uart_port *_port)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+ struct mn10300_serial_int *pint;
+
+ _enter("%s{%d}", port->name, port->gdbstub);
+
+ if (unlikely(port->gdbstub))
+ return -EBUSY;
+
+ /* allocate an Rx buffer for the virtual DMA handler */
+ port->rx_buffer = kmalloc(MNSC_BUFFER_SIZE, GFP_KERNEL);
+ if (!port->rx_buffer)
+ return -ENOMEM;
+
+ port->rx_inp = port->rx_outp = 0;
+
+ /* finally, enable the device */
+ *port->_intr = SC01ICR_TI;
+ *port->_control |= SC01CTR_TXE | SC01CTR_RXE;
+
+ pint = &mn10300_serial_int_tbl[port->rx_irq];
+ pint->port = port;
+ pint->vdma = mn10300_serial_vdma_rx_handler;
+ pint = &mn10300_serial_int_tbl[port->tx_irq];
+ pint->port = port;
+ pint->vdma = mn10300_serial_vdma_tx_handler;
+
+ set_intr_level(port->rx_irq, GxICR_LEVEL_1);
+ set_intr_level(port->tx_irq, GxICR_LEVEL_1);
+ set_irq_chip(port->tm_irq, &mn10300_serial_pic);
+
+ if (request_irq(port->rx_irq, mn10300_serial_interrupt,
+ IRQF_DISABLED, port->rx_name, port) < 0)
+ goto error;
+
+ if (request_irq(port->tx_irq, mn10300_serial_interrupt,
+ IRQF_DISABLED, port->tx_name, port) < 0)
+ goto error2;
+
+ if (request_irq(port->tm_irq, mn10300_serial_interrupt,
+ IRQF_DISABLED, port->tm_name, port) < 0)
+ goto error3;
+ mn10300_serial_mask_ack(port->tm_irq);
+
+ return 0;
+
+error3:
+ free_irq(port->tx_irq, port);
+error2:
+ free_irq(port->rx_irq, port);
+error:
+ kfree(port->rx_buffer);
+ port->rx_buffer = NULL;
+ return -EBUSY;
+}
+
+/*
+ * shutdown the port and release interrupts
+ */
+static void mn10300_serial_shutdown(struct uart_port *_port)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ _enter("%s", port->name);
+
+ /* disable the serial port and its baud rate timer */
+ port->tx_break = 0;
+ *port->_control &= ~(SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE);
+ *port->_tmxmd = 0;
+
+ if (port->rx_buffer) {
+ void *buf = port->rx_buffer;
+ port->rx_buffer = NULL;
+ kfree(buf);
+ }
+
+ /* disable all intrs */
+ free_irq(port->tm_irq, port);
+ free_irq(port->rx_irq, port);
+ free_irq(port->tx_irq, port);
+
+ *port->rx_icr = GxICR_LEVEL_1;
+ *port->tx_icr = GxICR_LEVEL_1;
+}
+
+/*
+ * this routine is called to set the UART divisor registers to match the
+ * specified baud rate for a serial port.
+ */
+static void mn10300_serial_change_speed(struct mn10300_serial_port *port,
+ struct ktermios *new,
+ struct ktermios *old)
+{
+ unsigned long flags;
+ unsigned long ioclk = port->ioclk;
+ unsigned cflag;
+ int baud, bits, xdiv, tmp;
+ u16 tmxbr, scxctr;
+ u8 tmxmd, battempt;
+ u8 div_timer = port->div_timer;
+
+ _enter("%s{%lu}", port->name, ioclk);
+
+ /* byte size and parity */
+ cflag = new->c_cflag;
+ switch (cflag & CSIZE) {
+ case CS7: scxctr = SC01CTR_CLN_7BIT; bits = 9; break;
+ case CS8: scxctr = SC01CTR_CLN_8BIT; bits = 10; break;
+ default: scxctr = SC01CTR_CLN_8BIT; bits = 10; break;
+ }
+
+ if (cflag & CSTOPB) {
+ scxctr |= SC01CTR_STB_2BIT;
+ bits++;
+ }
+
+ if (cflag & PARENB) {
+ bits++;
+ if (cflag & PARODD)
+ scxctr |= SC01CTR_PB_ODD;
+#ifdef CMSPAR
+ else if (cflag & CMSPAR)
+ scxctr |= SC01CTR_PB_FIXED0;
+#endif
+ else
+ scxctr |= SC01CTR_PB_EVEN;
+ }
+
+ /* Determine divisor based on baud rate */
+ battempt = 0;
+
+ if (div_timer == MNSCx_DIV_TIMER_16BIT)
+ scxctr |= SC0CTR_CK_TM8UFLOW_8; /* ( == SC1CTR_CK_TM9UFLOW_8
+ * == SC2CTR_CK_TM10UFLOW) */
+ else if (div_timer == MNSCx_DIV_TIMER_8BIT)
+ scxctr |= SC0CTR_CK_TM2UFLOW_8;
+
+try_alternative:
+ baud = uart_get_baud_rate(&port->uart, new, old, 0,
+ port->ioclk / 8);
+
+ _debug("ALT %d [baud %d]", battempt, baud);
+
+ if (!baud)
+ baud = 9600; /* B0 transition handled in rs_set_termios */
+ xdiv = 1;
+ if (baud == 134) {
+ baud = 269; /* 134 is really 134.5 */
+ xdiv = 2;
+ }
+
+ if (baud == 38400 &&
+ (port->uart.flags & UPF_SPD_MASK) == UPF_SPD_CUST
+ ) {
+ _debug("CUSTOM %u", port->uart.custom_divisor);
+
+ if (div_timer == MNSCx_DIV_TIMER_16BIT) {
+ if (port->uart.custom_divisor <= 65535) {
+ tmxmd = TM8MD_SRC_IOCLK;
+ tmxbr = port->uart.custom_divisor;
+ port->uart.uartclk = ioclk;
+ goto timer_okay;
+ }
+ if (port->uart.custom_divisor / 8 <= 65535) {
+ tmxmd = TM8MD_SRC_IOCLK_8;
+ tmxbr = port->uart.custom_divisor / 8;
+ port->uart.custom_divisor = tmxbr * 8;
+ port->uart.uartclk = ioclk / 8;
+ goto timer_okay;
+ }
+ if (port->uart.custom_divisor / 32 <= 65535) {
+ tmxmd = TM8MD_SRC_IOCLK_32;
+ tmxbr = port->uart.custom_divisor / 32;
+ port->uart.custom_divisor = tmxbr * 32;
+ port->uart.uartclk = ioclk / 32;
+ goto timer_okay;
+ }
+
+ } else if (div_timer == MNSCx_DIV_TIMER_8BIT) {
+ if (port->uart.custom_divisor <= 255) {
+ tmxmd = TM2MD_SRC_IOCLK;
+ tmxbr = port->uart.custom_divisor;
+ port->uart.uartclk = ioclk;
+ goto timer_okay;
+ }
+ if (port->uart.custom_divisor / 8 <= 255) {
+ tmxmd = TM2MD_SRC_IOCLK_8;
+ tmxbr = port->uart.custom_divisor / 8;
+ port->uart.custom_divisor = tmxbr * 8;
+ port->uart.uartclk = ioclk / 8;
+ goto timer_okay;
+ }
+ if (port->uart.custom_divisor / 32 <= 255) {
+ tmxmd = TM2MD_SRC_IOCLK_32;
+ tmxbr = port->uart.custom_divisor / 32;
+ port->uart.custom_divisor = tmxbr * 32;
+ port->uart.uartclk = ioclk / 32;
+ goto timer_okay;
+ }
+ }
+ }
+
+ switch (div_timer) {
+ case MNSCx_DIV_TIMER_16BIT:
+ port->uart.uartclk = ioclk;
+ tmxmd = TM8MD_SRC_IOCLK;
+ tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 65535)
+ goto timer_okay;
+
+ port->uart.uartclk = ioclk / 8;
+ tmxmd = TM8MD_SRC_IOCLK_8;
+ tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 65535)
+ goto timer_okay;
+
+ port->uart.uartclk = ioclk / 32;
+ tmxmd = TM8MD_SRC_IOCLK_32;
+ tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 65535)
+ goto timer_okay;
+ break;
+
+ case MNSCx_DIV_TIMER_8BIT:
+ port->uart.uartclk = ioclk;
+ tmxmd = TM2MD_SRC_IOCLK;
+ tmxbr = tmp = (ioclk / (baud * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 255)
+ goto timer_okay;
+
+ port->uart.uartclk = ioclk / 8;
+ tmxmd = TM2MD_SRC_IOCLK_8;
+ tmxbr = tmp = (ioclk / (baud * 8 * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 255)
+ goto timer_okay;
+
+ port->uart.uartclk = ioclk / 32;
+ tmxmd = TM2MD_SRC_IOCLK_32;
+ tmxbr = tmp = (ioclk / (baud * 32 * xdiv) + 4) / 8 - 1;
+ if (tmp > 0 && tmp <= 255)
+ goto timer_okay;
+ break;
+
+ default:
+ BUG();
+ return;
+ }
+
+ /* refuse to change to a baud rate we can't support */
+ _debug("CAN'T SUPPORT");
+
+ switch (battempt) {
+ case 0:
+ if (old) {
+ new->c_cflag &= ~CBAUD;
+ new->c_cflag |= (old->c_cflag & CBAUD);
+ battempt = 1;
+ goto try_alternative;
+ }
+
+ case 1:
+ /* as a last resort, if the quotient is zero, default to 9600
+ * bps */
+ new->c_cflag &= ~CBAUD;
+ new->c_cflag |= B9600;
+ battempt = 2;
+ goto try_alternative;
+
+ default:
+ /* hmmm... can't seem to support 9600 either
+ * - we could try iterating through the speeds we know about to
+ * find the lowest
+ */
+ new->c_cflag &= ~CBAUD;
+ new->c_cflag |= B0;
+
+ if (div_timer == MNSCx_DIV_TIMER_16BIT)
+ tmxmd = TM8MD_SRC_IOCLK_32;
+ else if (div_timer == MNSCx_DIV_TIMER_8BIT)
+ tmxmd = TM2MD_SRC_IOCLK_32;
+ tmxbr = 1;
+
+ port->uart.uartclk = ioclk / 32;
+ break;
+ }
+timer_okay:
+
+ _debug("UARTCLK: %u / %hu", port->uart.uartclk, tmxbr);
+
+ /* make the changes */
+ spin_lock_irqsave(&port->uart.lock, flags);
+
+ uart_update_timeout(&port->uart, new->c_cflag, baud);
+
+ /* set the timer to produce the required baud rate */
+ switch (div_timer) {
+ case MNSCx_DIV_TIMER_16BIT:
+ *port->_tmxmd = 0;
+ *port->_tmxbr = tmxbr;
+ *port->_tmxmd = TM8MD_INIT_COUNTER;
+ *port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE;
+ break;
+
+ case MNSCx_DIV_TIMER_8BIT:
+ *port->_tmxmd = 0;
+ *(volatile u8 *) port->_tmxbr = (u8) tmxbr;
+ *port->_tmxmd = TM2MD_INIT_COUNTER;
+ *port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE;
+ break;
+ }
+
+ /* CTS flow control flag and modem status interrupts */
+ scxctr &= ~(SC2CTR_TWE | SC2CTR_TWS);
+
+ if (port->type == PORT_MN10300_CTS && cflag & CRTSCTS) {
+ /* want to interrupt when CTS goes low if CTS is now
+ * high and vice versa
+ */
+ port->tx_cts = *port->_status;
+
+ if (port->tx_cts & SC2STR_CTS)
+ scxctr |= SC2CTR_TWE;
+ else
+ scxctr |= SC2CTR_TWE | SC2CTR_TWS;
+ }
+
+ /* set up parity check flag */
+ port->uart.read_status_mask = (1 << TTY_NORMAL) | (1 << TTY_OVERRUN);
+ if (new->c_iflag & INPCK)
+ port->uart.read_status_mask |=
+ (1 << TTY_PARITY) | (1 << TTY_FRAME);
+ if (new->c_iflag & (BRKINT | PARMRK))
+ port->uart.read_status_mask |= (1 << TTY_BREAK);
+
+ /* characters to ignore */
+ port->uart.ignore_status_mask = 0;
+ if (new->c_iflag & IGNPAR)
+ port->uart.ignore_status_mask |=
+ (1 << TTY_PARITY) | (1 << TTY_FRAME);
+ if (new->c_iflag & IGNBRK) {
+ port->uart.ignore_status_mask |= (1 << TTY_BREAK);
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns to (for real raw support).
+ */
+ if (new->c_iflag & IGNPAR)
+ port->uart.ignore_status_mask |= (1 << TTY_OVERRUN);
+ }
+
+ /* Ignore all characters if CREAD is not set */
+ if ((new->c_cflag & CREAD) == 0)
+ port->uart.ignore_status_mask |= (1 << TTY_NORMAL);
+
+ scxctr |= *port->_control & (SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE);
+ *port->_control = scxctr;
+
+ spin_unlock_irqrestore(&port->uart.lock, flags);
+}
+
+/*
+ * set the terminal I/O parameters
+ */
+static void mn10300_serial_set_termios(struct uart_port *_port,
+ struct ktermios *new,
+ struct ktermios *old)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ _enter("%s,%p,%p", port->name, new, old);
+
+ mn10300_serial_change_speed(port, new, old);
+
+ /* handle turning off CRTSCTS */
+ if (!(new->c_cflag & CRTSCTS)) {
+ u16 ctr = *port->_control;
+ ctr &= ~SC2CTR_TWE;
+ *port->_control = ctr;
+ }
+}
+
+/*
+ * return description of port type
+ */
+static const char *mn10300_serial_type(struct uart_port *_port)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ if (port->uart.type == PORT_MN10300_CTS)
+ return "MN10300 SIF_CTS";
+
+ return "MN10300 SIF";
+}
+
+/*
+ * release I/O and memory regions in use by port
+ */
+static void mn10300_serial_release_port(struct uart_port *_port)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ _enter("%s", port->name);
+
+ release_mem_region((unsigned long) port->_iobase, 16);
+}
+
+/*
+ * request I/O and memory regions for port
+ */
+static int mn10300_serial_request_port(struct uart_port *_port)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ _enter("%s", port->name);
+
+ request_mem_region((unsigned long) port->_iobase, 16, port->name);
+ return 0;
+}
+
+/*
+ * configure the type and reserve the ports
+ */
+static void mn10300_serial_config_port(struct uart_port *_port, int type)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+
+ _enter("%s", port->name);
+
+ port->uart.type = PORT_MN10300;
+
+ if (port->options & MNSCx_OPT_CTS)
+ port->uart.type = PORT_MN10300_CTS;
+
+ mn10300_serial_request_port(_port);
+}
+
+/*
+ * verify serial parameters are suitable for this port type
+ */
+static int mn10300_serial_verify_port(struct uart_port *_port,
+ struct serial_struct *ss)
+{
+ struct mn10300_serial_port *port =
+ container_of(_port, struct mn10300_serial_port, uart);
+ void *mapbase = (void *) (unsigned long) port->uart.mapbase;
+
+ _enter("%s", port->name);
+
+ /* these things may not be changed */
+ if (ss->irq != port->uart.irq ||
+ ss->port != port->uart.iobase ||
+ ss->io_type != port->uart.iotype ||
+ ss->iomem_base != mapbase ||
+ ss->iomem_reg_shift != port->uart.regshift ||
+ ss->hub6 != port->uart.hub6 ||
+ ss->xmit_fifo_size != port->uart.fifosize)
+ return -EINVAL;
+
+ /* type may be changed on a port that supports CTS */
+ if (ss->type != port->uart.type) {
+ if (!(port->options & MNSCx_OPT_CTS))
+ return -EINVAL;
+
+ if (ss->type != PORT_MN10300 &&
+ ss->type != PORT_MN10300_CTS)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * initialise the MN10300 on-chip UARTs
+ */
+static int __init mn10300_serial_init(void)
+{
+ struct mn10300_serial_port *port;
+ int ret, i;
+
+ printk(KERN_INFO "%s version %s (%s)\n",
+ serial_name, serial_version, serial_revdate);
+
+#ifdef CONFIG_MN10300_TTYSM2
+ SC2TIM = 8; /* make the baud base of timer 2 IOCLK/8 */
+#endif
+
+ set_intr_stub(EXCEP_IRQ_LEVEL1, mn10300_serial_vdma_interrupt);
+
+ ret = uart_register_driver(&mn10300_serial_driver);
+ if (!ret) {
+ for (i = 0 ; i < NR_PORTS ; i++) {
+ port = mn10300_serial_ports[i];
+ if (!port || port->gdbstub)
+ continue;
+
+ switch (port->clock_src) {
+ case MNSCx_CLOCK_SRC_IOCLK:
+ port->ioclk = MN10300_IOCLK;
+ break;
+
+#ifdef MN10300_IOBCLK
+ case MNSCx_CLOCK_SRC_IOBCLK:
+ port->ioclk = MN10300_IOBCLK;
+ break;
+#endif
+ default:
+ BUG();
+ }
+
+ ret = uart_add_one_port(&mn10300_serial_driver,
+ &port->uart);
+
+ if (ret < 0) {
+ _debug("ERROR %d", -ret);
+ break;
+ }
+ }
+
+ if (ret)
+ uart_unregister_driver(&mn10300_serial_driver);
+ }
+
+ return ret;
+}
+
+__initcall(mn10300_serial_init);
+
+
+#ifdef CONFIG_MN10300_TTYSM_CONSOLE
+
+/*
+ * print a string to the serial port without disturbing the real user of the
+ * port too much
+ * - the console must be locked by the caller
+ */
+static void mn10300_serial_console_write(struct console *co,
+ const char *s, unsigned count)
+{
+ struct mn10300_serial_port *port;
+ unsigned i;
+ u16 scxctr, txicr, tmp;
+ u8 tmxmd;
+
+ port = mn10300_serial_ports[co->index];
+
+ /* firstly hijack the serial port from the "virtual DMA" controller */
+ txicr = *port->tx_icr;
+ *port->tx_icr = GxICR_LEVEL_1;
+ tmp = *port->tx_icr;
+
+ /* the transmitter may be disabled */
+ scxctr = *port->_control;
+ if (!(scxctr & SC01CTR_TXE)) {
+ /* restart the UART clock */
+ tmxmd = *port->_tmxmd;
+
+ switch (port->div_timer) {
+ case MNSCx_DIV_TIMER_16BIT:
+ *port->_tmxmd = 0;
+ *port->_tmxmd = TM8MD_INIT_COUNTER;
+ *port->_tmxmd = tmxmd | TM8MD_COUNT_ENABLE;
+ break;
+
+ case MNSCx_DIV_TIMER_8BIT:
+ *port->_tmxmd = 0;
+ *port->_tmxmd = TM2MD_INIT_COUNTER;
+ *port->_tmxmd = tmxmd | TM2MD_COUNT_ENABLE;
+ break;
+ }
+
+ /* enable the transmitter */
+ *port->_control = (scxctr & ~SC01CTR_BKE) | SC01CTR_TXE;
+
+ } else if (scxctr & SC01CTR_BKE) {
+ /* stop transmitting BREAK */
+ *port->_control = (scxctr & ~SC01CTR_BKE);
+ }
+
+ /* send the chars into the serial port (with LF -> LFCR conversion) */
+ for (i = 0; i < count; i++) {
+ char ch = *s++;
+
+ while (*port->_status & SC01STR_TBF)
+ continue;
+ *(u8 *) port->_txb = ch;
+
+ if (ch == 0x0a) {
+ while (*port->_status & SC01STR_TBF)
+ continue;
+ *(u8 *) port->_txb = 0xd;
+ }
+ }
+
+ /* can't let the transmitter be turned off if it's actually
+ * transmitting */
+ while (*port->_status & (SC01STR_TXF | SC01STR_TBF))
+ continue;
+
+ /* disable the transmitter if we re-enabled it */
+ if (!(scxctr & SC01CTR_TXE))
+ *port->_control = scxctr;
+
+ *port->tx_icr = txicr;
+ tmp = *port->tx_icr;
+}
+
+/*
+ * set up a serial port as a console
+ * - construct a cflag setting for the first rs_open()
+ * - initialize the serial port
+ * - return non-zero if we didn't find a serial port.
+ */
+static int __init mn10300_serial_console_setup(struct console *co,
+ char *options)
+{
+ struct mn10300_serial_port *port;
+ int i, parity = 'n', baud = 9600, bits = 8, flow = 0;
+
+ for (i = 0 ; i < NR_PORTS ; i++) {
+ port = mn10300_serial_ports[i];
+ if (port && !port->gdbstub && port->uart.line == co->index)
+ goto found_device;
+ }
+
+ return -ENODEV;
+
+found_device:
+ switch (port->clock_src) {
+ case MNSCx_CLOCK_SRC_IOCLK:
+ port->ioclk = MN10300_IOCLK;
+ break;
+
+#ifdef MN10300_IOBCLK
+ case MNSCx_CLOCK_SRC_IOBCLK:
+ port->ioclk = MN10300_IOBCLK;
+ break;
+#endif
+ default:
+ BUG();
+ }
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(&port->uart, co, baud, parity, bits, flow);
+}
+
+/*
+ * register console
+ */
+static int __init mn10300_serial_console_init(void)
+{
+ register_console(&mn10300_serial_console);
+ return 0;
+}
+
+console_initcall(mn10300_serial_console_init);
+#endif
diff --git a/arch/mn10300/kernel/mn10300-serial.h b/arch/mn10300/kernel/mn10300-serial.h
new file mode 100644
index 00000000000..6796499bf78
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-serial.h
@@ -0,0 +1,126 @@
+/* MN10300 On-chip serial port driver definitions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _MN10300_SERIAL_H
+#define _MN10300_SERIAL_H
+
+#ifndef __ASSEMBLY__
+#include <linux/serial_core.h>
+#include <linux/termios.h>
+#endif
+
+#include <asm/page.h>
+#include <asm/serial-regs.h>
+
+#define NR_PORTS 3 /* should be set 3 or 9 or 16 */
+
+#define MNSC_BUFFER_SIZE +(PAGE_SIZE / 2)
+
+/* intr_flags bits */
+#define MNSCx_RX_AVAIL 0x01
+#define MNSCx_RX_OVERF 0x02
+#define MNSCx_TX_SPACE 0x04
+#define MNSCx_TX_EMPTY 0x08
+
+#ifndef __ASSEMBLY__
+
+struct mn10300_serial_port {
+ char *rx_buffer; /* reception buffer base */
+ unsigned rx_inp; /* pointer to rx input offset */
+ unsigned rx_outp; /* pointer to rx output offset */
+ u8 tx_xchar; /* high-priority XON/XOFF buffer */
+ u8 tx_break; /* transmit break request */
+ u8 intr_flags; /* interrupt flags */
+ volatile u16 *rx_icr; /* Rx interrupt control register */
+ volatile u16 *tx_icr; /* Tx interrupt control register */
+ int rx_irq; /* reception IRQ */
+ int tx_irq; /* transmission IRQ */
+ int tm_irq; /* timer IRQ */
+
+ const char *name; /* name of serial port */
+ const char *rx_name; /* Rx interrupt handler name of serial port */
+ const char *tx_name; /* Tx interrupt handler name of serial port */
+ const char *tm_name; /* Timer interrupt handler name */
+ unsigned short type; /* type of serial port */
+ unsigned char isconsole; /* T if it's a console */
+ volatile void *_iobase; /* pointer to base of I/O control regs */
+ volatile u16 *_control; /* control register pointer */
+ volatile u8 *_status; /* status register pointer */
+ volatile u8 *_intr; /* interrupt register pointer */
+ volatile void *_rxb; /* receive buffer register pointer */
+ volatile void *_txb; /* transmit buffer register pointer */
+ volatile u16 *_tmicr; /* timer interrupt control register */
+ volatile u8 *_tmxmd; /* baud rate timer mode register */
+ volatile u16 *_tmxbr; /* baud rate timer base register */
+
+ /* this must come down here so that assembly can use BSET to access the
+ * above fields */
+ struct uart_port uart;
+
+ unsigned short rx_brk; /* current break reception status */
+ u16 tx_cts; /* current CTS status */
+ int gdbstub; /* preemptively stolen by GDB stub */
+
+ u8 clock_src; /* clock source */
+#define MNSCx_CLOCK_SRC_IOCLK 0
+#define MNSCx_CLOCK_SRC_IOBCLK 1
+
+ u8 div_timer; /* timer used as divisor */
+#define MNSCx_DIV_TIMER_16BIT 0
+#define MNSCx_DIV_TIMER_8BIT 1
+
+ u16 options; /* options */
+#define MNSCx_OPT_CTS 0x0001
+
+ unsigned long ioclk; /* base clock rate */
+};
+
+#ifdef CONFIG_MN10300_TTYSM0
+extern struct mn10300_serial_port mn10300_serial_port_sif0;
+#endif
+
+#ifdef CONFIG_MN10300_TTYSM1
+extern struct mn10300_serial_port mn10300_serial_port_sif1;
+#endif
+
+#ifdef CONFIG_MN10300_TTYSM2
+extern struct mn10300_serial_port mn10300_serial_port_sif2;
+#endif
+
+extern struct mn10300_serial_port *mn10300_serial_ports[];
+
+struct mn10300_serial_int {
+ struct mn10300_serial_port *port;
+ asmlinkage void (*vdma)(void);
+};
+
+extern struct mn10300_serial_int mn10300_serial_int_tbl[];
+
+extern asmlinkage void mn10300_serial_vdma_interrupt(void);
+extern asmlinkage void mn10300_serial_vdma_rx_handler(void);
+extern asmlinkage void mn10300_serial_vdma_tx_handler(void);
+
+#endif /* __ASSEMBLY__ */
+
+#if defined(CONFIG_GDBSTUB_ON_TTYSM0)
+#define SCgSTR SC0STR
+#define SCgRXB SC0RXB
+#define SCgRXIRQ SC0RXIRQ
+#elif defined(CONFIG_GDBSTUB_ON_TTYSM1)
+#define SCgSTR SC1STR
+#define SCgRXB SC1RXB
+#define SCgRXIRQ SC1RXIRQ
+#elif defined(CONFIG_GDBSTUB_ON_TTYSM2)
+#define SCgSTR SC2STR
+#define SCgRXB SC2RXB
+#define SCgRXIRQ SC2RXIRQ
+#endif
+
+#endif /* _MN10300_SERIAL_H */
diff --git a/arch/mn10300/kernel/mn10300-watchdog-low.S b/arch/mn10300/kernel/mn10300-watchdog-low.S
new file mode 100644
index 00000000000..996244745cc
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-watchdog-low.S
@@ -0,0 +1,59 @@
+###############################################################################
+#
+# MN10300 Watchdog interrupt handler
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/intctl-regs.h>
+#include <asm/timer-regs.h>
+#include <asm/frame.inc>
+
+ .text
+
+###############################################################################
+#
+# Watchdog handler entry point
+# - special non-maskable interrupt
+#
+###############################################################################
+ .globl watchdog_handler
+ .type watchdog_handler,@function
+watchdog_handler:
+ add -4,sp
+ SAVE_ALL
+
+ mov 0xffffffff,d0
+ mov d0,(REG_ORIG_D0,fp)
+
+ mov fp,d0
+ lsr 2,d1
+ call watchdog_interrupt[],0 # watchdog_interrupt(regs,irq)
+
+ jmp ret_from_intr
+
+ .size watchdog_handler,.-watchdog_handler
+
+###############################################################################
+#
+# Watchdog touch entry point
+# - kept to absolute minimum (unfortunately, it's prototyped in linux/nmi.h so
+# we can't inline it)
+#
+###############################################################################
+ .globl touch_nmi_watchdog
+ .type touch_nmi_watchdog,@function
+touch_nmi_watchdog:
+ clr d0
+ mov d0,(watchdog_alert_counter)
+ ret [],0
+
+ .size touch_nmi_watchdog,.-touch_nmi_watchdog
diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c
new file mode 100644
index 00000000000..10811e981d2
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300-watchdog.c
@@ -0,0 +1,183 @@
+/* MN10300 Watchdog timer
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from arch/i386/kernel/nmi.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/nmi.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/intctl-regs.h>
+#include <asm/rtc-regs.h>
+#include <asm/div64.h>
+#include <asm/smp.h>
+#include <asm/gdb-stub.h>
+#include <asm/proc/clock.h>
+
+static DEFINE_SPINLOCK(watchdog_print_lock);
+static unsigned int watchdog;
+static unsigned int watchdog_hz = 1;
+unsigned int watchdog_alert_counter;
+
+EXPORT_SYMBOL(touch_nmi_watchdog);
+
+/*
+ * the best way to detect whether a CPU has a 'hard lockup' problem
+ * is to check its timer makes IRQ counts. If they are not
+ * changing then that CPU has some problem.
+ *
+ * as these watchdog NMI IRQs are generated on every CPU, we only
+ * have to check the current processor.
+ *
+ * since NMIs dont listen to _any_ locks, we have to be extremely
+ * careful not to rely on unsafe variables. The printk might lock
+ * up though, so we have to break up any console locks first ...
+ * [when there will be more tty-related locks, break them up
+ * here too!]
+ */
+static unsigned int last_irq_sums[NR_CPUS];
+
+int __init check_watchdog(void)
+{
+ irq_cpustat_t tmp[1];
+
+ printk(KERN_INFO "Testing Watchdog... ");
+
+ memcpy(tmp, irq_stat, sizeof(tmp));
+ local_irq_enable();
+ mdelay((10 * 1000) / watchdog_hz); /* wait 10 ticks */
+ local_irq_disable();
+
+ if (nmi_count(0) - tmp[0].__nmi_count <= 5) {
+ printk(KERN_WARNING "CPU#%d: Watchdog appears to be stuck!\n",
+ 0);
+ return -1;
+ }
+
+ printk(KERN_INFO "OK.\n");
+
+ /* now that we know it works we can reduce NMI frequency to
+ * something more reasonable; makes a difference in some configs
+ */
+ watchdog_hz = 1;
+
+ return 0;
+}
+
+static int __init setup_watchdog(char *str)
+{
+ unsigned tmp;
+ int opt;
+ u8 ctr;
+
+ get_option(&str, &opt);
+ if (opt != 1)
+ return 0;
+
+ watchdog = opt;
+ if (watchdog) {
+ set_intr_stub(EXCEP_WDT, watchdog_handler);
+ ctr = WDCTR_WDCK_65536th;
+ WDCTR = WDCTR_WDRST | ctr;
+ WDCTR = ctr;
+ tmp = WDCTR;
+
+ tmp = __muldiv64u(1 << (16 + ctr * 2), 1000000, MN10300_WDCLK);
+ tmp = 1000000000 / tmp;
+ watchdog_hz = (tmp + 500) / 1000;
+ }
+
+ return 1;
+}
+
+__setup("watchdog=", setup_watchdog);
+
+void __init watchdog_go(void)
+{
+ u8 wdt;
+
+ if (watchdog) {
+ printk(KERN_INFO "Watchdog: running at %uHz\n", watchdog_hz);
+ wdt = WDCTR & ~WDCTR_WDCNE;
+ WDCTR = wdt | WDCTR_WDRST;
+ wdt = WDCTR;
+ WDCTR = wdt | WDCTR_WDCNE;
+ wdt = WDCTR;
+
+ check_watchdog();
+ }
+}
+
+asmlinkage
+void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep)
+{
+
+ /*
+ * Since current-> is always on the stack, and we always switch
+ * the stack NMI-atomically, it's safe to use smp_processor_id().
+ */
+ int sum, cpu = smp_processor_id();
+ u8 wdt, tmp;
+
+ wdt = WDCTR & ~WDCTR_WDCNE;
+ WDCTR = wdt;
+ tmp = WDCTR;
+ NMICR = NMICR_WDIF;
+
+ nmi_count(cpu)++;
+ kstat_this_cpu.irqs[NMIIRQ]++;
+ sum = irq_stat[cpu].__irq_count;
+
+ if (last_irq_sums[cpu] == sum) {
+ /*
+ * Ayiee, looks like this CPU is stuck ...
+ * wait a few IRQs (5 seconds) before doing the oops ...
+ */
+ watchdog_alert_counter++;
+ if (watchdog_alert_counter == 5 * watchdog_hz) {
+ spin_lock(&watchdog_print_lock);
+ /*
+ * We are in trouble anyway, lets at least try
+ * to get a message out.
+ */
+ bust_spinlocks(1);
+ printk(KERN_ERR
+ "NMI Watchdog detected LOCKUP on CPU%d,"
+ " pc %08lx, registers:\n",
+ cpu, regs->pc);
+ show_registers(regs);
+ printk("console shuts up ...\n");
+ console_silent();
+ spin_unlock(&watchdog_print_lock);
+ bust_spinlocks(0);
+#ifdef CONFIG_GDBSTUB
+ if (gdbstub_busy)
+ gdbstub_exception(regs, excep);
+ else
+ gdbstub_intercept(regs, excep);
+#endif
+ do_exit(SIGSEGV);
+ }
+ } else {
+ last_irq_sums[cpu] = sum;
+ watchdog_alert_counter = 0;
+ }
+
+ WDCTR = wdt | WDCTR_WDRST;
+ tmp = WDCTR;
+ WDCTR = wdt | WDCTR_WDCNE;
+ tmp = WDCTR;
+}
diff --git a/arch/mn10300/kernel/mn10300_ksyms.c b/arch/mn10300/kernel/mn10300_ksyms.c
new file mode 100644
index 00000000000..6d19628634e
--- /dev/null
+++ b/arch/mn10300/kernel/mn10300_ksyms.c
@@ -0,0 +1,37 @@
+/* MN10300 Miscellaneous and library kernel exports
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+
+EXPORT_SYMBOL(change_bit);
+EXPORT_SYMBOL(test_and_change_bit);
+
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memset);
+
+EXPORT_SYMBOL(strncpy_from_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(clear_user);
+EXPORT_SYMBOL(__clear_user);
+EXPORT_SYMBOL(__generic_copy_from_user);
+EXPORT_SYMBOL(__generic_copy_to_user);
+EXPORT_SYMBOL(strnlen_user);
+
+extern u64 __ashrdi3(u64, unsigned);
+extern u64 __ashldi3(u64, unsigned);
+extern u64 __lshrdi3(u64, unsigned);
+extern s64 __negdi2(s64);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__negdi2);
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c
new file mode 100644
index 00000000000..0e4d2f6fa6e
--- /dev/null
+++ b/arch/mn10300/kernel/module.c
@@ -0,0 +1,206 @@
+/* MN10300 Kernel module helper routines
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by Mark Salter (msalter@redhat.com)
+ * - Derived from arch/i386/kernel/module.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public Licence as published by
+ * the Free Software Foundation; either version 2 of the Licence, 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 Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public Licence
+ * 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/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt, ...)
+#endif
+
+/*
+ * allocate storage for a module
+ */
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc_exec(size);
+}
+
+/*
+ * free memory returned from module_alloc()
+ */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+ /* FIXME: If module_region == mod->init_region, trim exception
+ * table entries. */
+}
+
+/*
+ * allow the arch to fix up the section table
+ * - we don't need anything special
+ */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
+ struct module *mod)
+{
+ return 0;
+}
+
+static uint32_t reloc_get16(uint8_t *p)
+{
+ return p[0] | (p[1] << 8);
+}
+
+static uint32_t reloc_get24(uint8_t *p)
+{
+ return reloc_get16(p) | (p[2] << 16);
+}
+
+static uint32_t reloc_get32(uint8_t *p)
+{
+ return reloc_get16(p) | (reloc_get16(p+2) << 16);
+}
+
+static void reloc_put16(uint8_t *p, uint32_t val)
+{
+ p[0] = val & 0xff;
+ p[1] = (val >> 8) & 0xff;
+}
+
+static void reloc_put24(uint8_t *p, uint32_t val)
+{
+ reloc_put16(p, val);
+ p[2] = (val >> 16) & 0xff;
+}
+
+static void reloc_put32(uint8_t *p, uint32_t val)
+{
+ reloc_put16(p, val);
+ reloc_put16(p+2, val >> 16);
+}
+
+/*
+ * apply a REL relocation
+ */
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ printk(KERN_ERR "module %s: RELOCATION unsupported\n",
+ me->name);
+ return -ENOEXEC;
+}
+
+/*
+ * apply a RELA relocation
+ */
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ unsigned int i;
+ Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ Elf32_Addr relocation;
+ uint8_t *location;
+ uint32_t value;
+
+ DEBUGP("Applying relocate section %u to %u\n",
+ relsec, sechdrs[relsec].sh_info);
+
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* this is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+
+ /* this is the symbol the relocation is referring to (note that
+ * all undefined symbols have been resolved by the caller) */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rel[i].r_info);
+
+ /* this is the adjustment to be made */
+ relocation = sym->st_value + rel[i].r_addend;
+
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+ /* for the first four relocation types, we add the
+ * adjustment into the value at the location given */
+ case R_MN10300_32:
+ value = reloc_get32(location);
+ value += relocation;
+ reloc_put32(location, value);
+ break;
+ case R_MN10300_24:
+ value = reloc_get24(location);
+ value += relocation;
+ reloc_put24(location, value);
+ break;
+ case R_MN10300_16:
+ value = reloc_get16(location);
+ value += relocation;
+ reloc_put16(location, value);
+ break;
+ case R_MN10300_8:
+ *location += relocation;
+ break;
+
+ /* for the next three relocation types, we write the
+ * adjustment with the address subtracted over the
+ * value at the location given */
+ case R_MN10300_PCREL32:
+ value = relocation - (uint32_t) location;
+ reloc_put32(location, value);
+ break;
+ case R_MN10300_PCREL16:
+ value = relocation - (uint32_t) location;
+ reloc_put16(location, value);
+ break;
+ case R_MN10300_PCREL8:
+ *location = relocation - (uint32_t) location;
+ break;
+
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+
+/*
+ * finish loading the module
+ */
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ return 0;
+}
+
+/*
+ * finish clearing the module
+ */
+void module_arch_cleanup(struct module *mod)
+{
+}
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
new file mode 100644
index 00000000000..3b0d579fc15
--- /dev/null
+++ b/arch/mn10300/kernel/process.c
@@ -0,0 +1,297 @@
+/* MN10300 Process handling code
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/percpu.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/mmu_context.h>
+#include <asm/fpu.h>
+#include <asm/reset-regs.h>
+#include <asm/gdb-stub.h>
+#include "internal.h"
+
+/*
+ * power management idle function, if any..
+ */
+void (*pm_idle)(void);
+EXPORT_SYMBOL(pm_idle);
+
+/*
+ * return saved PC of a blocked thread.
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+ return ((unsigned long *) tsk->thread.sp)[3];
+}
+
+/*
+ * power off function, if any
+ */
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
+/*
+ * we use this if we don't have any better idle routine
+ */
+static void default_idle(void)
+{
+ local_irq_disable();
+ if (!need_resched())
+ safe_halt();
+ else
+ local_irq_enable();
+}
+
+/*
+ * the idle thread
+ * - there's no useful work to be done, so just try to conserve power and have
+ * a low exit latency (ie sit in a loop waiting for somebody to say that
+ * they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+ int cpu = smp_processor_id();
+
+ /* endless idle loop with no priority at all */
+ for (;;) {
+ while (!need_resched()) {
+ void (*idle)(void);
+
+ smp_rmb();
+ idle = pm_idle;
+ if (!idle)
+ idle = default_idle;
+
+ irq_stat[cpu].idle_timestamp = jiffies;
+ idle();
+ }
+
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
+ }
+}
+
+void release_segments(struct mm_struct *mm)
+{
+}
+
+void machine_restart(char *cmd)
+{
+#ifdef CONFIG_GDBSTUB
+ gdbstub_exit(0);
+#endif
+
+#ifdef mn10300_unit_hard_reset
+ mn10300_unit_hard_reset();
+#else
+ mn10300_proc_hard_reset();
+#endif
+}
+
+void machine_halt(void)
+{
+#ifdef CONFIG_GDBSTUB
+ gdbstub_exit(0);
+#endif
+}
+
+void machine_power_off(void)
+{
+#ifdef CONFIG_GDBSTUB
+ gdbstub_exit(0);
+#endif
+}
+
+void show_regs(struct pt_regs *regs)
+{
+}
+
+/*
+ * create a kernel thread
+ */
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+ struct pt_regs regs;
+
+ memset(&regs, 0, sizeof(regs));
+
+ regs.a2 = (unsigned long) fn;
+ regs.d2 = (unsigned long) arg;
+ regs.pc = (unsigned long) kernel_thread_helper;
+ local_save_flags(regs.epsw);
+ regs.epsw |= EPSW_IE | EPSW_IM_7;
+
+ /* Ok, create the new process.. */
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0,
+ NULL, NULL);
+}
+
+/*
+ * free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+ exit_fpu();
+}
+
+void flush_thread(void)
+{
+ flush_fpu();
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * we do not have to muck with descriptors here, that is
+ * done in switch_mm() as needed.
+ */
+void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
+{
+}
+
+/*
+ * this gets called before we allocate a new thread and copy the current task
+ * into it so that we can store lazy state into memory
+ */
+void prepare_to_copy(struct task_struct *tsk)
+{
+ unlazy_fpu(tsk);
+}
+
+/*
+ * set up the kernel stack for a new thread and copy arch-specific thread
+ * control information
+ */
+int copy_thread(int nr, unsigned long clone_flags,
+ unsigned long c_usp, unsigned long ustk_size,
+ struct task_struct *p, struct pt_regs *kregs)
+{
+ struct pt_regs *c_uregs, *c_kregs, *uregs;
+ unsigned long c_ksp;
+
+ uregs = current->thread.uregs;
+
+ c_ksp = (unsigned long) task_stack_page(p) + THREAD_SIZE;
+
+ /* allocate the userspace exception frame and set it up */
+ c_ksp -= sizeof(struct pt_regs);
+ c_uregs = (struct pt_regs *) c_ksp;
+
+ p->thread.uregs = c_uregs;
+ *c_uregs = *uregs;
+ c_uregs->sp = c_usp;
+ c_uregs->epsw &= ~EPSW_FE; /* my FPU */
+
+ c_ksp -= 12; /* allocate function call ABI slack */
+
+ /* the new TLS pointer is passed in as arg #5 to sys_clone() */
+ if (clone_flags & CLONE_SETTLS)
+ c_uregs->e2 = __frame->d3;
+
+ /* set up the return kernel frame if called from kernel_thread() */
+ c_kregs = c_uregs;
+ if (kregs != uregs) {
+ c_ksp -= sizeof(struct pt_regs);
+ c_kregs = (struct pt_regs *) c_ksp;
+ *c_kregs = *kregs;
+ c_kregs->sp = c_usp;
+ c_kregs->next = c_uregs;
+#ifdef CONFIG_MN10300_CURRENT_IN_E2
+ c_kregs->e2 = (unsigned long) p; /* current */
+#endif
+
+ c_ksp -= 12; /* allocate function call ABI slack */
+ }
+
+ /* set up things up so the scheduler can start the new task */
+ p->thread.__frame = c_kregs;
+ p->thread.a3 = (unsigned long) c_kregs;
+ p->thread.sp = c_ksp;
+ p->thread.pc = (unsigned long) ret_from_fork;
+ p->thread.wchan = (unsigned long) ret_from_fork;
+ p->thread.usp = c_usp;
+
+ return 0;
+}
+
+/*
+ * clone a process
+ * - tlsptr is retrieved by copy_thread() from __frame->d3
+ */
+asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
+ int __user *parent_tidptr, int __user *child_tidptr,
+ int __user *tlsptr)
+{
+ return do_fork(clone_flags, newsp ?: __frame->sp, __frame, 0,
+ parent_tidptr, child_tidptr);
+}
+
+asmlinkage long sys_fork(void)
+{
+ return do_fork(SIGCHLD, __frame->sp, __frame, 0, NULL, NULL);
+}
+
+asmlinkage long sys_vfork(void)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, __frame->sp, __frame,
+ 0, NULL, NULL);
+}
+
+asmlinkage long sys_execve(char __user *name,
+ char __user * __user *argv,
+ char __user * __user *envp)
+{
+ char *filename;
+ int error;
+
+ lock_kernel();
+
+ filename = getname(name);
+ error = PTR_ERR(filename);
+ if (!IS_ERR(filename)) {
+ error = do_execve(filename, argv, envp, __frame);
+ if (error == 0)
+ current->ptrace &= ~PT_DTRACE;
+
+ putname(filename);
+ }
+
+ unlock_kernel();
+ return error;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+ return p->thread.wchan;
+}
diff --git a/arch/mn10300/kernel/profile-low.S b/arch/mn10300/kernel/profile-low.S
new file mode 100644
index 00000000000..94ffac12d02
--- /dev/null
+++ b/arch/mn10300/kernel/profile-low.S
@@ -0,0 +1,72 @@
+###############################################################################
+#
+# Fast profiling interrupt handler
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/smp.h>
+#include <asm/intctl-regs.h>
+#include <asm/timer-regs.h>
+
+#define pi break
+
+ .balign 4
+counter:
+ .long -1
+
+###############################################################################
+#
+# Profiling interrupt entry point
+# - intended to run at interrupt priority 1
+#
+###############################################################################
+ENTRY(profile_handler)
+ movm [d2,d3,a2],(sp)
+
+ # ignore userspace
+ mov (12,sp),d2
+ and EPSW_nSL,d2
+ bne out
+
+ # do nothing if there's no buffer
+ mov (prof_buffer),a2
+ and a2,a2
+ beq out
+ or 0x20000000,a2
+
+ # calculate relative position in text segment
+ mov (16,sp),d2
+ sub _stext,d2
+ mov (prof_shift),d3
+ lsr d3,d2
+ mov (prof_len),d3
+ cmp d3,d2
+ bcc outside_text
+
+ # increment the appropriate profile bucket
+do_inc:
+ asl2 d2
+ mov (a2,d2),d3
+ inc d3
+ mov d3,(a2,d2)
+out:
+ mov GxICR_DETECT,d2
+ movbu d2,(TM11ICR) # ACK the interrupt
+ movbu (TM11ICR),d2
+ movm (sp),[d2,d3,a2]
+ rti
+
+outside_text:
+ sub 1,d3
+ mov d3,d2
+ bra do_inc
diff --git a/arch/mn10300/kernel/profile.c b/arch/mn10300/kernel/profile.c
new file mode 100644
index 00000000000..20d7d0306b1
--- /dev/null
+++ b/arch/mn10300/kernel/profile.c
@@ -0,0 +1,51 @@
+/* MN10300 Profiling setup
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+/*
+ * initialise the profiling if enabled
+ * - using with gdbstub will give anomalous results
+ * - can't be used with gdbstub if running at IRQ priority 0
+ */
+static __init int profile_init(void)
+{
+ u16 tmp;
+
+ if (!prof_buffer)
+ return 0;
+
+ /* use timer 11 to drive the profiling interrupts */
+ set_intr_stub(EXCEP_IRQ_LEVEL0, profile_handler);
+
+ /* set IRQ priority at which to run */
+ set_intr_level(TM11IRQ, GxICR_LEVEL_0);
+
+ /* set up timer 11
+ * - source: (IOCLK 33MHz)*2 = 66MHz
+ * - frequency: (33330000*2) / 8 / 20625 = 202Hz
+ */
+ TM11BR = 20625 - 1;
+ TM11MD = TM8MD_SRC_IOCLK_8;
+ TM11MD |= TM8MD_INIT_COUNTER;
+ TM11MD &= ~TM8MD_INIT_COUNTER;
+ TM11MD |= TM8MD_COUNT_ENABLE;
+
+ TM11ICR |= GxICR_ENABLE;
+ tmp = TM11ICR;
+
+ printk(KERN_INFO "Profiling initiated on timer 11, priority 0, %uHz\n",
+ mn10300_ioclk / 8 / (TM11BR + 1));
+ printk(KERN_INFO "Profile histogram stored %p-%p\n",
+ prof_buffer, (u8 *)(prof_buffer + prof_len) - 1);
+
+ return 0;
+}
+
+__initcall(profile_init);
diff --git a/arch/mn10300/kernel/ptrace.c b/arch/mn10300/kernel/ptrace.c
new file mode 100644
index 00000000000..d6d6cdc75c5
--- /dev/null
+++ b/arch/mn10300/kernel/ptrace.c
@@ -0,0 +1,379 @@
+/* MN10300 Process tracing
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/fpu.h>
+#include <asm/asm-offsets.h>
+
+/*
+ * translate ptrace register IDs into struct pt_regs offsets
+ */
+static const u8 ptrace_regid_to_frame[] = {
+ [PT_A3 << 2] = REG_A3,
+ [PT_A2 << 2] = REG_A2,
+ [PT_D3 << 2] = REG_D3,
+ [PT_D2 << 2] = REG_D2,
+ [PT_MCVF << 2] = REG_MCVF,
+ [PT_MCRL << 2] = REG_MCRL,
+ [PT_MCRH << 2] = REG_MCRH,
+ [PT_MDRQ << 2] = REG_MDRQ,
+ [PT_E1 << 2] = REG_E1,
+ [PT_E0 << 2] = REG_E0,
+ [PT_E7 << 2] = REG_E7,
+ [PT_E6 << 2] = REG_E6,
+ [PT_E5 << 2] = REG_E5,
+ [PT_E4 << 2] = REG_E4,
+ [PT_E3 << 2] = REG_E3,
+ [PT_E2 << 2] = REG_E2,
+ [PT_SP << 2] = REG_SP,
+ [PT_LAR << 2] = REG_LAR,
+ [PT_LIR << 2] = REG_LIR,
+ [PT_MDR << 2] = REG_MDR,
+ [PT_A1 << 2] = REG_A1,
+ [PT_A0 << 2] = REG_A0,
+ [PT_D1 << 2] = REG_D1,
+ [PT_D0 << 2] = REG_D0,
+ [PT_ORIG_D0 << 2] = REG_ORIG_D0,
+ [PT_EPSW << 2] = REG_EPSW,
+ [PT_PC << 2] = REG_PC,
+};
+
+static inline int get_stack_long(struct task_struct *task, int offset)
+{
+ return *(unsigned long *)
+ ((unsigned long) task->thread.uregs + offset);
+}
+
+/*
+ * this routine will put a word on the processes privileged stack.
+ * the offset is how far from the base addr as stored in the TSS.
+ * this routine assumes that all the privileged stacks are in our
+ * data space.
+ */
+static inline
+int put_stack_long(struct task_struct *task, int offset, unsigned long data)
+{
+ unsigned long stack;
+
+ stack = (unsigned long) task->thread.uregs + offset;
+ *(unsigned long *) stack = data;
+ return 0;
+}
+
+static inline unsigned long get_fpregs(struct fpu_state_struct *buf,
+ struct task_struct *tsk)
+{
+ return __copy_to_user(buf, &tsk->thread.fpu_state,
+ sizeof(struct fpu_state_struct));
+}
+
+static inline unsigned long set_fpregs(struct task_struct *tsk,
+ struct fpu_state_struct *buf)
+{
+ return __copy_from_user(&tsk->thread.fpu_state, buf,
+ sizeof(struct fpu_state_struct));
+}
+
+static inline void fpsave_init(struct task_struct *task)
+{
+ memset(&task->thread.fpu_state, 0, sizeof(struct fpu_state_struct));
+}
+
+/*
+ * make sure the single step bit is not set
+ */
+void ptrace_disable(struct task_struct *child)
+{
+#ifndef CONFIG_MN10300_USING_JTAG
+ struct user *dummy = NULL;
+ long tmp;
+
+ tmp = get_stack_long(child, (unsigned long) &dummy->regs.epsw);
+ tmp &= ~EPSW_T;
+ put_stack_long(child, (unsigned long) &dummy->regs.epsw, tmp);
+#endif
+}
+
+/*
+ * set the single step bit
+ */
+void ptrace_enable(struct task_struct *child)
+{
+#ifndef CONFIG_MN10300_USING_JTAG
+ struct user *dummy = NULL;
+ long tmp;
+
+ tmp = get_stack_long(child, (unsigned long) &dummy->regs.epsw);
+ tmp |= EPSW_T;
+ put_stack_long(child, (unsigned long) &dummy->regs.epsw, tmp);
+#endif
+}
+
+/*
+ * handle the arch-specific side of process tracing
+ */
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+{
+ struct fpu_state_struct fpu_state;
+ int i, ret;
+
+ switch (request) {
+ /* read the word at location addr. */
+ case PTRACE_PEEKTEXT: {
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ break;
+ ret = put_user(tmp, (unsigned long *) data);
+ break;
+ }
+
+ /* read the word at location addr. */
+ case PTRACE_PEEKDATA: {
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ break;
+ ret = put_user(tmp, (unsigned long *) data);
+ break;
+ }
+
+ /* read the word at location addr in the USER area. */
+ case PTRACE_PEEKUSR: {
+ unsigned long tmp;
+
+ ret = -EIO;
+ if ((addr & 3) || addr < 0 ||
+ addr > sizeof(struct user) - 3)
+ break;
+
+ tmp = 0; /* Default return condition */
+ if (addr < NR_PTREGS << 2)
+ tmp = get_stack_long(child,
+ ptrace_regid_to_frame[addr]);
+ ret = put_user(tmp, (unsigned long *) data);
+ break;
+ }
+
+ /* write the word at location addr. */
+ case PTRACE_POKETEXT:
+ case PTRACE_POKEDATA:
+ if (access_process_vm(child, addr, &data, sizeof(data), 1) ==
+ sizeof(data))
+ ret = 0;
+ else
+ ret = -EIO;
+ break;
+
+ /* write the word at location addr in the USER area */
+ case PTRACE_POKEUSR:
+ ret = -EIO;
+ if ((addr & 3) || addr < 0 ||
+ addr > sizeof(struct user) - 3)
+ break;
+
+ ret = 0;
+ if (addr < NR_PTREGS << 2)
+ ret = put_stack_long(child, ptrace_regid_to_frame[addr],
+ data);
+ break;
+
+ /* continue and stop at next (return from) syscall */
+ case PTRACE_SYSCALL:
+ /* restart after signal. */
+ case PTRACE_CONT:
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ if (request == PTRACE_SYSCALL)
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ else
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ child->exit_code = data;
+ ptrace_disable(child);
+ wake_up_process(child);
+ ret = 0;
+ break;
+
+ /*
+ * make the child exit
+ * - the best I can do is send it a sigkill
+ * - perhaps it should be put in the status that it wants to
+ * exit
+ */
+ case PTRACE_KILL:
+ ret = 0;
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+ break;
+ child->exit_code = SIGKILL;
+ clear_tsk_thread_flag(child, TIF_SINGLESTEP);
+ ptrace_disable(child);
+ wake_up_process(child);
+ break;
+
+ case PTRACE_SINGLESTEP: /* set the trap flag. */
+#ifndef CONFIG_MN10300_USING_JTAG
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ ptrace_enable(child);
+ child->exit_code = data;
+ wake_up_process(child);
+ ret = 0;
+#else
+ ret = -EINVAL;
+#endif
+ break;
+
+ case PTRACE_DETACH: /* detach a process that was attached. */
+ ret = ptrace_detach(child, data);
+ break;
+
+ /* Get all gp regs from the child. */
+ case PTRACE_GETREGS: {
+ unsigned long tmp;
+
+ if (!access_ok(VERIFY_WRITE, (unsigned *) data, NR_PTREGS << 2)) {
+ ret = -EIO;
+ break;
+ }
+
+ for (i = 0; i < NR_PTREGS << 2; i += 4) {
+ tmp = get_stack_long(child, ptrace_regid_to_frame[i]);
+ __put_user(tmp, (unsigned long *) data);
+ data += sizeof(tmp);
+ }
+ ret = 0;
+ break;
+ }
+
+ case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+ unsigned long tmp;
+
+ if (!access_ok(VERIFY_READ, (unsigned long *)data,
+ sizeof(struct pt_regs))) {
+ ret = -EIO;
+ break;
+ }
+
+ for (i = 0; i < NR_PTREGS << 2; i += 4) {
+ __get_user(tmp, (unsigned long *) data);
+ put_stack_long(child, ptrace_regid_to_frame[i], tmp);
+ data += sizeof(tmp);
+ }
+ ret = 0;
+ break;
+ }
+
+ case PTRACE_GETFPREGS: { /* Get the child FPU state. */
+ if (is_using_fpu(child)) {
+ unlazy_fpu(child);
+ fpu_state = child->thread.fpu_state;
+ } else {
+ memset(&fpu_state, 0, sizeof(fpu_state));
+ }
+
+ ret = -EIO;
+ if (copy_to_user((void *) data, &fpu_state,
+ sizeof(fpu_state)) == 0)
+ ret = 0;
+ break;
+ }
+
+ case PTRACE_SETFPREGS: { /* Set the child FPU state. */
+ ret = -EFAULT;
+ if (copy_from_user(&fpu_state, (const void *) data,
+ sizeof(fpu_state)) == 0) {
+ fpu_kill_state(child);
+ child->thread.fpu_state = fpu_state;
+ set_using_fpu(child);
+ ret = 0;
+ }
+ break;
+ }
+
+ case PTRACE_SETOPTIONS: {
+ if (data & PTRACE_O_TRACESYSGOOD)
+ child->ptrace |= PT_TRACESYSGOOD;
+ else
+ child->ptrace &= ~PT_TRACESYSGOOD;
+ ret = 0;
+ break;
+ }
+
+ default:
+ ret = -EIO;
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * notification of system call entry/exit
+ * - triggered by current->work.syscall_trace
+ */
+asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
+{
+#if 0
+ /* just in case... */
+ printk(KERN_DEBUG "[%d] syscall_%lu(%lx,%lx,%lx,%lx) = %lx\n",
+ current->pid,
+ regs->orig_d0,
+ regs->a0,
+ regs->d1,
+ regs->a3,
+ regs->a2,
+ regs->d0);
+ return;
+#endif
+
+ if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
+ !test_thread_flag(TIF_SINGLESTEP))
+ return;
+ if (!(current->ptrace & PT_PTRACED))
+ return;
+
+ /* the 0x80 provides a way for the tracing parent to distinguish
+ between a syscall stop and SIGTRAP delivery */
+ ptrace_notify(SIGTRAP |
+ ((current->ptrace & PT_TRACESYSGOOD) &&
+ !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
+
+ /*
+ * this isn't the same as continuing with a signal, but it will do
+ * for normal use. strace only continues with a signal if the
+ * stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
diff --git a/arch/mn10300/kernel/rtc.c b/arch/mn10300/kernel/rtc.c
new file mode 100644
index 00000000000..042f792d843
--- /dev/null
+++ b/arch/mn10300/kernel/rtc.c
@@ -0,0 +1,173 @@
+/* MN10300 RTC management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+#include <linux/bcd.h>
+#include <linux/timex.h>
+#include <asm/rtc-regs.h>
+#include <asm/rtc.h>
+
+DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL(rtc_lock);
+
+/* last time the RTC got updated */
+static long last_rtc_update;
+
+/* time for RTC to update itself in ioclks */
+static unsigned long mn10300_rtc_update_period;
+
+/*
+ * read the current RTC time
+ */
+unsigned long __init get_initial_rtc_time(void)
+{
+ struct rtc_time tm;
+
+ get_rtc_time(&tm);
+
+ return mktime(tm.tm_year, tm.tm_mon, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
+ * ms after the second nowtime has started, because when nowtime is written
+ * into the registers of the CMOS clock, it will jump to the next second
+ * precisely 500 ms later. Check the Motorola MC146818A or Dallas DS12887 data
+ * sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ * sets the minutes. Usually you'll only notice that after reboot!
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+ unsigned char save_control, save_freq_select;
+ int retval = 0;
+ int real_seconds, real_minutes, cmos_minutes;
+
+ /* gets recalled with irq locally disabled */
+ spin_lock(&rtc_lock);
+ save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being
+ * set */
+ CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL);
+
+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset
+ * prescaler */
+ CMOS_WRITE(save_freq_select | RTC_DIV_RESET2, RTC_FREQ_SELECT);
+
+ cmos_minutes = CMOS_READ(RTC_MINUTES);
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ BCD_TO_BIN(cmos_minutes);
+
+ /*
+ * since we're only adjusting minutes and seconds,
+ * don't interfere with hour overflow. This avoids
+ * messing with unknown time zones but requires your
+ * RTC not to be off by more than 15 minutes
+ */
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
+ /* correct for half hour time zone */
+ real_minutes += 30;
+ real_minutes %= 60;
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BIN_TO_BCD(real_seconds);
+ BIN_TO_BCD(real_minutes);
+ }
+ CMOS_WRITE(real_seconds, RTC_SECONDS);
+ CMOS_WRITE(real_minutes, RTC_MINUTES);
+ } else {
+ printk(KERN_WARNING
+ "set_rtc_mmss: can't update from %d to %d\n",
+ cmos_minutes, real_minutes);
+ retval = -1;
+ }
+
+ /* The following flags have to be released exactly in this order,
+ * otherwise the DS12887 (popular MC146818A clone with integrated
+ * battery and quartz) will not reset the oscillator and will not
+ * update precisely 500 ms later. You won't find this mentioned in
+ * the Dallas Semiconductor data sheets, but who believes data
+ * sheets anyway ... -- Markus Kuhn
+ */
+ CMOS_WRITE(save_control, RTC_CONTROL);
+ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+ spin_unlock(&rtc_lock);
+
+ return retval;
+}
+
+void check_rtc_time(void)
+{
+ /* the RTC clock just finished ticking over again this second
+ * - if we have an externally synchronized Linux clock, then update
+ * RTC clock accordingly every ~11 minutes. set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ */
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ xtime.tv_nsec / 1000 >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
+ xtime.tv_nsec / 1000 <= 500000 + ((unsigned) TICK_SIZE) / 2
+ ) {
+ if (set_rtc_mmss(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ /* do it again in 60s */
+ last_rtc_update = xtime.tv_sec - 600;
+ }
+}
+
+/*
+ * calibrate the TSC clock against the RTC
+ */
+void __init calibrate_clock(void)
+{
+ unsigned long count0, counth, count1;
+ unsigned char status;
+
+ /* make sure the RTC is running and is set to operate in 24hr mode */
+ status = RTSRC;
+ RTCRB |= RTCRB_SET;
+ RTCRB |= RTCRB_TM_24HR;
+ RTCRA |= RTCRA_DVR;
+ RTCRA &= ~RTCRA_DVR;
+ RTCRB &= ~RTCRB_SET;
+
+ /* work out the clock speed by counting clock cycles between ends of
+ * the RTC update cycle - track the RTC through one complete update
+ * cycle (1 second)
+ */
+ startup_timestamp_counter();
+
+ while (!(RTCRA & RTCRA_UIP)) {}
+ while ((RTCRA & RTCRA_UIP)) {}
+
+ count0 = TMTSCBC;
+
+ while (!(RTCRA & RTCRA_UIP)) {}
+
+ counth = TMTSCBC;
+
+ while ((RTCRA & RTCRA_UIP)) {}
+
+ count1 = TMTSCBC;
+
+ shutdown_timestamp_counter();
+
+ MN10300_TSCCLK = count0 - count1; /* the timers count down */
+ mn10300_rtc_update_period = counth - count1;
+ MN10300_TSC_PER_HZ = MN10300_TSCCLK / HZ;
+}
diff --git a/arch/mn10300/kernel/semaphore.c b/arch/mn10300/kernel/semaphore.c
new file mode 100644
index 00000000000..9153c4039fd
--- /dev/null
+++ b/arch/mn10300/kernel/semaphore.c
@@ -0,0 +1,149 @@
+/* MN10300 Semaphore implementation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <asm/semaphore.h>
+
+struct sem_waiter {
+ struct list_head list;
+ struct task_struct *task;
+};
+
+#if SEMAPHORE_DEBUG
+void semtrace(struct semaphore *sem, const char *str)
+{
+ if (sem->debug)
+ printk(KERN_DEBUG "[%d] %s({%d,%d})\n",
+ current->pid,
+ str,
+ atomic_read(&sem->count),
+ list_empty(&sem->wait_list) ? 0 : 1);
+}
+#else
+#define semtrace(SEM, STR) do { } while (0)
+#endif
+
+/*
+ * wait for a token to be granted from a semaphore
+ * - entered with lock held and interrupts disabled
+ */
+void __down(struct semaphore *sem, unsigned long flags)
+{
+ struct task_struct *tsk = current;
+ struct sem_waiter waiter;
+
+ semtrace(sem, "Entering __down");
+
+ /* set up my own style of waitqueue */
+ waiter.task = tsk;
+ get_task_struct(tsk);
+
+ list_add_tail(&waiter.list, &sem->wait_list);
+
+ /* we don't need to touch the semaphore struct anymore */
+ spin_unlock_irqrestore(&sem->wait_lock, flags);
+
+ /* wait to be given the semaphore */
+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+
+ for (;;) {
+ if (!waiter.task)
+ break;
+ schedule();
+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+ }
+
+ tsk->state = TASK_RUNNING;
+ semtrace(sem, "Leaving __down");
+}
+EXPORT_SYMBOL(__down);
+
+/*
+ * interruptibly wait for a token to be granted from a semaphore
+ * - entered with lock held and interrupts disabled
+ */
+int __down_interruptible(struct semaphore *sem, unsigned long flags)
+{
+ struct task_struct *tsk = current;
+ struct sem_waiter waiter;
+ int ret;
+
+ semtrace(sem, "Entering __down_interruptible");
+
+ /* set up my own style of waitqueue */
+ waiter.task = tsk;
+ get_task_struct(tsk);
+
+ list_add_tail(&waiter.list, &sem->wait_list);
+
+ /* we don't need to touch the semaphore struct anymore */
+ set_task_state(tsk, TASK_INTERRUPTIBLE);
+
+ spin_unlock_irqrestore(&sem->wait_lock, flags);
+
+ /* wait to be given the semaphore */
+ ret = 0;
+ for (;;) {
+ if (!waiter.task)
+ break;
+ if (unlikely(signal_pending(current)))
+ goto interrupted;
+ schedule();
+ set_task_state(tsk, TASK_INTERRUPTIBLE);
+ }
+
+ out:
+ tsk->state = TASK_RUNNING;
+ semtrace(sem, "Leaving __down_interruptible");
+ return ret;
+
+ interrupted:
+ spin_lock_irqsave(&sem->wait_lock, flags);
+ list_del(&waiter.list);
+ spin_unlock_irqrestore(&sem->wait_lock, flags);
+
+ ret = 0;
+ if (!waiter.task) {
+ put_task_struct(current);
+ ret = -EINTR;
+ }
+ goto out;
+}
+EXPORT_SYMBOL(__down_interruptible);
+
+/*
+ * release a single token back to a semaphore
+ * - entered with lock held and interrupts disabled
+ */
+void __up(struct semaphore *sem)
+{
+ struct task_struct *tsk;
+ struct sem_waiter *waiter;
+
+ semtrace(sem, "Entering __up");
+
+ /* grant the token to the process at the front of the queue */
+ waiter = list_entry(sem->wait_list.next, struct sem_waiter, list);
+
+ /* We must be careful not to touch 'waiter' after we set ->task = NULL.
+ * It is an allocated on the waiter's stack and may become invalid at
+ * any time after that point (due to a wakeup from another source).
+ */
+ list_del_init(&waiter->list);
+ tsk = waiter->task;
+ smp_mb();
+ waiter->task = NULL;
+ wake_up_process(tsk);
+ put_task_struct(tsk);
+
+ semtrace(sem, "Leaving __up");
+}
+EXPORT_SYMBOL(__up);
diff --git a/arch/mn10300/kernel/setup.c b/arch/mn10300/kernel/setup.c
new file mode 100644
index 00000000000..6b7ce263685
--- /dev/null
+++ b/arch/mn10300/kernel/setup.c
@@ -0,0 +1,298 @@
+/* MN10300 Arch-specific initialisation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <asm/processor.h>
+#include <linux/console.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/proc/proc.h>
+#include <asm/busctl-regs.h>
+#include <asm/fpu.h>
+#include <asm/sections.h>
+
+struct mn10300_cpuinfo boot_cpu_data;
+
+/* For PCI or other memory-mapped resources */
+unsigned long pci_mem_start = 0x18000000;
+
+char redboot_command_line[COMMAND_LINE_SIZE] =
+ "console=ttyS0,115200 root=/dev/mtdblock3 rw";
+
+char __initdata redboot_platform_name[COMMAND_LINE_SIZE];
+
+static struct resource code_resource = {
+ .start = 0x100000,
+ .end = 0,
+ .name = "Kernel code",
+};
+
+static struct resource data_resource = {
+ .start = 0,
+ .end = 0,
+ .name = "Kernel data",
+};
+
+static unsigned long __initdata phys_memory_base;
+static unsigned long __initdata phys_memory_end;
+static unsigned long __initdata memory_end;
+unsigned long memory_size;
+
+struct thread_info *__current_ti = &init_thread_union.thread_info;
+struct task_struct *__current = &init_task;
+
+#define mn10300_known_cpus 3
+static const char *const mn10300_cputypes[] = {
+ "am33v1",
+ "am33v2",
+ "am34v1",
+ "unknown"
+};
+
+/*
+ *
+ */
+static void __init parse_mem_cmdline(char **cmdline_p)
+{
+ char *from, *to, c;
+
+ /* save unparsed command line copy for /proc/cmdline */
+ strcpy(boot_command_line, redboot_command_line);
+
+ /* see if there's an explicit memory size option */
+ from = redboot_command_line;
+ to = redboot_command_line;
+ c = ' ';
+
+ for (;;) {
+ if (c == ' ' && !memcmp(from, "mem=", 4)) {
+ if (to != redboot_command_line)
+ to--;
+ memory_size = memparse(from + 4, &from);
+ }
+
+ c = *(from++);
+ if (!c)
+ break;
+
+ *(to++) = c;
+ }
+
+ *to = '\0';
+ *cmdline_p = redboot_command_line;
+
+ if (memory_size == 0)
+ panic("Memory size not known\n");
+
+ memory_end = (unsigned long) CONFIG_KERNEL_RAM_BASE_ADDRESS +
+ memory_size;
+ if (memory_end > phys_memory_end)
+ memory_end = phys_memory_end;
+}
+
+/*
+ * architecture specific setup
+ */
+void __init setup_arch(char **cmdline_p)
+{
+ unsigned long bootmap_size;
+ unsigned long kstart_pfn, start_pfn, free_pfn, end_pfn;
+
+ cpu_init();
+ unit_setup();
+ parse_mem_cmdline(cmdline_p);
+
+ init_mm.start_code = (unsigned long)&_text;
+ init_mm.end_code = (unsigned long) &_etext;
+ init_mm.end_data = (unsigned long) &_edata;
+ init_mm.brk = (unsigned long) &_end;
+
+ code_resource.start = virt_to_bus(&_text);
+ code_resource.end = virt_to_bus(&_etext)-1;
+ data_resource.start = virt_to_bus(&_etext);
+ data_resource.end = virt_to_bus(&_edata)-1;
+
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+
+ start_pfn = (CONFIG_KERNEL_RAM_BASE_ADDRESS >> PAGE_SHIFT);
+ kstart_pfn = PFN_UP(__pa(&_text));
+ free_pfn = PFN_UP(__pa(&_end));
+ end_pfn = PFN_DOWN(__pa(memory_end));
+
+ bootmap_size = init_bootmem_node(&contig_page_data,
+ free_pfn,
+ start_pfn,
+ end_pfn);
+
+ if (kstart_pfn > start_pfn)
+ free_bootmem(PFN_PHYS(start_pfn),
+ PFN_PHYS(kstart_pfn - start_pfn));
+
+ free_bootmem(PFN_PHYS(free_pfn),
+ PFN_PHYS(end_pfn - free_pfn));
+
+ /* If interrupt vector table is in main ram, then we need to
+ reserve the page it is occupying. */
+ if (CONFIG_INTERRUPT_VECTOR_BASE >= CONFIG_KERNEL_RAM_BASE_ADDRESS &&
+ CONFIG_INTERRUPT_VECTOR_BASE < memory_end)
+ reserve_bootmem(CONFIG_INTERRUPT_VECTOR_BASE, 1,
+ BOOTMEM_DEFAULT);
+
+ reserve_bootmem(PAGE_ALIGN(PFN_PHYS(free_pfn)), bootmap_size,
+ BOOTMEM_DEFAULT);
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+ conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+#endif
+#endif
+
+ paging_init();
+}
+
+/*
+ * perform CPU initialisation
+ */
+void __init cpu_init(void)
+{
+ unsigned long cpurev = CPUREV, type;
+ unsigned long base, size;
+
+ type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S;
+ if (type > mn10300_known_cpus)
+ type = mn10300_known_cpus;
+
+ printk(KERN_INFO "Matsushita %s, rev %ld\n",
+ mn10300_cputypes[type],
+ (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S);
+
+ /* determine the memory size and base from the memory controller regs */
+ memory_size = 0;
+
+ base = SDBASE(0);
+ if (base & SDBASE_CE) {
+ size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
+ size = ~size + 1;
+ base &= SDBASE_CBA;
+
+ printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base);
+ memory_size += size;
+ phys_memory_base = base;
+ }
+
+ base = SDBASE(1);
+ if (base & SDBASE_CE) {
+ size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT;
+ size = ~size + 1;
+ base &= SDBASE_CBA;
+
+ printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base);
+ memory_size += size;
+ if (phys_memory_base == 0)
+ phys_memory_base = base;
+ }
+
+ phys_memory_end = phys_memory_base + memory_size;
+
+#ifdef CONFIG_FPU
+ fpu_init_state();
+#endif
+}
+
+/*
+ * Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+ unsigned long cpurev = CPUREV, type, icachesz, dcachesz;
+
+ type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S;
+ if (type > mn10300_known_cpus)
+ type = mn10300_known_cpus;
+
+ icachesz =
+ ((cpurev & CPUREV_ICWAY ) >> CPUREV_ICWAY_S) *
+ ((cpurev & CPUREV_ICSIZE) >> CPUREV_ICSIZE_S) *
+ 1024;
+
+ dcachesz =
+ ((cpurev & CPUREV_DCWAY ) >> CPUREV_DCWAY_S) *
+ ((cpurev & CPUREV_DCSIZE) >> CPUREV_DCSIZE_S) *
+ 1024;
+
+ seq_printf(m,
+ "processor : 0\n"
+ "vendor_id : Matsushita\n"
+ "cpu core : %s\n"
+ "cpu rev : %lu\n"
+ "model name : " PROCESSOR_MODEL_NAME "\n"
+ "icache size: %lu\n"
+ "dcache size: %lu\n",
+ mn10300_cputypes[type],
+ (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S,
+ icachesz,
+ dcachesz
+ );
+
+ seq_printf(m,
+ "ioclk speed: %lu.%02luMHz\n"
+ "bogomips : %lu.%02lu\n\n",
+ MN10300_IOCLK / 1000000,
+ (MN10300_IOCLK / 10000) % 100,
+ loops_per_jiffy / (500000 / HZ),
+ (loops_per_jiffy / (5000 / HZ)) % 100
+ );
+
+ return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+struct seq_operations cpuinfo_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = show_cpuinfo,
+};
diff --git a/arch/mn10300/kernel/sigframe.h b/arch/mn10300/kernel/sigframe.h
new file mode 100644
index 00000000000..0decba28ae8
--- /dev/null
+++ b/arch/mn10300/kernel/sigframe.h
@@ -0,0 +1,33 @@
+/* MN10300 Signal frame definitions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+struct sigframe
+{
+ void (*pretcode)(void);
+ int sig;
+ struct sigcontext *psc;
+ struct sigcontext sc;
+ struct fpucontext fpuctx;
+ unsigned long extramask[_NSIG_WORDS-1];
+ char retcode[8];
+};
+
+struct rt_sigframe
+{
+ void (*pretcode)(void);
+ int sig;
+ struct siginfo *pinfo;
+ void *puc;
+ struct siginfo info;
+ struct ucontext uc;
+ struct fpucontext fpuctx;
+ char retcode[8];
+};
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c
new file mode 100644
index 00000000000..841ca9955a1
--- /dev/null
+++ b/arch/mn10300/kernel/signal.c
@@ -0,0 +1,564 @@
+/* MN10300 Signal handling
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/tty.h>
+#include <linux/personality.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+#include <asm/fpu.h>
+#include "sigframe.h"
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/*
+ * atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
+{
+ mask &= _BLOCKABLE;
+ spin_lock_irq(&current->sighand->siglock);
+ current->saved_sigmask = current->blocked;
+ siginitset(&current->blocked, mask);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
+}
+
+/*
+ * set signal action syscall
+ */
+asmlinkage long sys_sigaction(int sig,
+ const struct old_sigaction __user *act,
+ struct old_sigaction __user *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+ if (act) {
+ old_sigset_t mask;
+ if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+ return -EFAULT;
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ __get_user(mask, &act->sa_mask);
+ siginitset(&new_ka.sa.sa_mask, mask);
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+ return -EFAULT;
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+ }
+
+ return ret;
+}
+
+/*
+ * set alternate signal stack syscall
+ */
+asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss)
+{
+ return do_sigaltstack(uss, uoss, __frame->sp);
+}
+
+/*
+ * do a signal return; undo the signal stack.
+ */
+static int restore_sigcontext(struct pt_regs *regs,
+ struct sigcontext __user *sc, long *_d0)
+{
+ unsigned int err = 0;
+
+ if (is_using_fpu(current))
+ fpu_kill_state(current);
+
+#define COPY(x) err |= __get_user(regs->x, &sc->x)
+ COPY(d1); COPY(d2); COPY(d3);
+ COPY(a0); COPY(a1); COPY(a2); COPY(a3);
+ COPY(e0); COPY(e1); COPY(e2); COPY(e3);
+ COPY(e4); COPY(e5); COPY(e6); COPY(e7);
+ COPY(lar); COPY(lir);
+ COPY(mdr); COPY(mdrq);
+ COPY(mcvf); COPY(mcrl); COPY(mcrh);
+ COPY(sp); COPY(pc);
+#undef COPY
+
+ {
+ unsigned int tmpflags;
+#ifndef CONFIG_MN10300_USING_JTAG
+#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \
+ EPSW_T | EPSW_nAR)
+#else
+#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \
+ EPSW_nAR)
+#endif
+ err |= __get_user(tmpflags, &sc->epsw);
+ regs->epsw = (regs->epsw & ~USER_EPSW) |
+ (tmpflags & USER_EPSW);
+ regs->orig_d0 = -1; /* disable syscall checks */
+ }
+
+ {
+ struct fpucontext *buf;
+ err |= __get_user(buf, &sc->fpucontext);
+ if (buf) {
+ if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+ goto badframe;
+ err |= fpu_restore_sigcontext(buf);
+ }
+ }
+
+ err |= __get_user(*_d0, &sc->d0);
+ return err;
+
+badframe:
+ return 1;
+}
+
+/*
+ * standard signal return syscall
+ */
+asmlinkage long sys_sigreturn(void)
+{
+ struct sigframe __user *frame = (struct sigframe __user *) __frame->sp;
+ sigset_t set;
+ long d0;
+
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__get_user(set.sig[0], &frame->sc.oldmask))
+ goto badframe;
+
+ if (_NSIG_WORDS > 1 &&
+ __copy_from_user(&set.sig[1], &frame->extramask,
+ sizeof(frame->extramask)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if (restore_sigcontext(__frame, &frame->sc, &d0))
+ goto badframe;
+
+ return d0;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+/*
+ * realtime signal return syscall
+ */
+asmlinkage long sys_rt_sigreturn(void)
+{
+ struct rt_sigframe __user *frame =
+ (struct rt_sigframe __user *) __frame->sp;
+ sigset_t set;
+ unsigned long d0;
+
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if (restore_sigcontext(__frame, &frame->uc.uc_mcontext, &d0))
+ goto badframe;
+
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT)
+ goto badframe;
+
+ return d0;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+/*
+ * store the userspace context into a signal frame
+ */
+static int setup_sigcontext(struct sigcontext __user *sc,
+ struct fpucontext *fpuctx,
+ struct pt_regs *regs,
+ unsigned long mask)
+{
+ int tmp, err = 0;
+
+#define COPY(x) err |= __put_user(regs->x, &sc->x)
+ COPY(d0); COPY(d1); COPY(d2); COPY(d3);
+ COPY(a0); COPY(a1); COPY(a2); COPY(a3);
+ COPY(e0); COPY(e1); COPY(e2); COPY(e3);
+ COPY(e4); COPY(e5); COPY(e6); COPY(e7);
+ COPY(lar); COPY(lir);
+ COPY(mdr); COPY(mdrq);
+ COPY(mcvf); COPY(mcrl); COPY(mcrh);
+ COPY(sp); COPY(epsw); COPY(pc);
+#undef COPY
+
+ tmp = fpu_setup_sigcontext(fpuctx);
+ if (tmp < 0)
+ err = 1;
+ else
+ err |= __put_user(tmp ? fpuctx : NULL, &sc->fpucontext);
+
+ /* non-iBCS2 extensions.. */
+ err |= __put_user(mask, &sc->oldmask);
+
+ return err;
+}
+
+/*
+ * determine which stack to use..
+ */
+static inline void __user *get_sigframe(struct k_sigaction *ka,
+ struct pt_regs *regs,
+ size_t frame_size)
+{
+ unsigned long sp;
+
+ /* default to using normal stack */
+ sp = regs->sp;
+
+ /* this is the X/Open sanctioned signal stack switching. */
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (!on_sig_stack(sp))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+ }
+
+ return (void __user *) ((sp - frame_size) & ~7UL);
+}
+
+/*
+ * set up a normal signal frame
+ */
+static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
+ struct pt_regs *regs)
+{
+ struct sigframe __user *frame;
+ int rsig;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ rsig = sig;
+ if (sig < 32 &&
+ current_thread_info()->exec_domain &&
+ current_thread_info()->exec_domain->signal_invmap)
+ rsig = current_thread_info()->exec_domain->signal_invmap[sig];
+
+ if (__put_user(rsig, &frame->sig) < 0 ||
+ __put_user(&frame->sc, &frame->psc) < 0)
+ goto give_sigsegv;
+
+ if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0]))
+ goto give_sigsegv;
+
+ if (_NSIG_WORDS > 1) {
+ if (__copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask)))
+ goto give_sigsegv;
+ }
+
+ /* set up to return from userspace. If provided, use a stub already in
+ * userspace */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
+ goto give_sigsegv;
+ } else {
+ if (__put_user((void (*)(void))frame->retcode,
+ &frame->pretcode))
+ goto give_sigsegv;
+ /* this is mov $,d0; syscall 0 */
+ if (__put_user(0x2c, (char *)(frame->retcode + 0)) ||
+ __put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) ||
+ __put_user(0x00, (char *)(frame->retcode + 2)) ||
+ __put_user(0xf0, (char *)(frame->retcode + 3)) ||
+ __put_user(0xe0, (char *)(frame->retcode + 4)))
+ goto give_sigsegv;
+ flush_icache_range((unsigned long) frame->retcode,
+ (unsigned long) frame->retcode + 5);
+ }
+
+ /* set up registers for signal handler */
+ regs->sp = (unsigned long) frame;
+ regs->pc = (unsigned long) ka->sa.sa_handler;
+ regs->d0 = sig;
+ regs->d1 = (unsigned long) &frame->sc;
+
+ set_fs(USER_DS);
+
+ /* the tracer may want to single-step inside the handler */
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+
+#if DEBUG_SIG
+ printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
+ sig, current->comm, current->pid, frame, regs->pc,
+ frame->pretcode);
+#endif
+
+ return 0;
+
+give_sigsegv:
+ force_sig(SIGSEGV, current);
+ return -EFAULT;
+}
+
+/*
+ * set up a realtime signal frame
+ */
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct rt_sigframe __user *frame;
+ int rsig;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ rsig = sig;
+ if (sig < 32 &&
+ current_thread_info()->exec_domain &&
+ current_thread_info()->exec_domain->signal_invmap)
+ rsig = current_thread_info()->exec_domain->signal_invmap[sig];
+
+ if (__put_user(rsig, &frame->sig) ||
+ __put_user(&frame->info, &frame->pinfo) ||
+ __put_user(&frame->uc, &frame->puc) ||
+ copy_siginfo_to_user(&frame->info, info))
+ goto give_sigsegv;
+
+ /* create the ucontext. */
+ if (__put_user(0, &frame->uc.uc_flags) ||
+ __put_user(0, &frame->uc.uc_link) ||
+ __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
+ __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) ||
+ __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size) ||
+ setup_sigcontext(&frame->uc.uc_mcontext,
+ &frame->fpuctx, regs, set->sig[0]) ||
+ __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
+ goto give_sigsegv;
+
+ /* set up to return from userspace. If provided, use a stub already in
+ * userspace */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
+ goto give_sigsegv;
+ } else {
+ if (__put_user((void(*)(void))frame->retcode,
+ &frame->pretcode) ||
+ /* This is mov $,d0; syscall 0 */
+ __put_user(0x2c, (char *)(frame->retcode + 0)) ||
+ __put_user(__NR_rt_sigreturn,
+ (char *)(frame->retcode + 1)) ||
+ __put_user(0x00, (char *)(frame->retcode + 2)) ||
+ __put_user(0xf0, (char *)(frame->retcode + 3)) ||
+ __put_user(0xe0, (char *)(frame->retcode + 4)))
+ goto give_sigsegv;
+
+ flush_icache_range((u_long) frame->retcode,
+ (u_long) frame->retcode + 5);
+ }
+
+ /* Set up registers for signal handler */
+ regs->sp = (unsigned long) frame;
+ regs->pc = (unsigned long) ka->sa.sa_handler;
+ regs->d0 = sig;
+ regs->d1 = (long) &frame->info;
+
+ set_fs(USER_DS);
+
+ /* the tracer may want to single-step inside the handler */
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+
+#if DEBUG_SIG
+ printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
+ sig, current->comm, current->pid, frame, regs->pc,
+ frame->pretcode);
+#endif
+
+ return 0;
+
+give_sigsegv:
+ force_sig(SIGSEGV, current);
+ return -EFAULT;
+}
+
+/*
+ * handle the actual delivery of a signal to userspace
+ */
+static int handle_signal(int sig,
+ siginfo_t *info, struct k_sigaction *ka,
+ sigset_t *oldset, struct pt_regs *regs)
+{
+ int ret;
+
+ /* Are we from a system call? */
+ if (regs->orig_d0 >= 0) {
+ /* If so, check system call restarting.. */
+ switch (regs->d0) {
+ case -ERESTART_RESTARTBLOCK:
+ case -ERESTARTNOHAND:
+ regs->d0 = -EINTR;
+ break;
+
+ case -ERESTARTSYS:
+ if (!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->d0 = -EINTR;
+ break;
+ }
+
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ regs->d0 = regs->orig_d0;
+ regs->pc -= 2;
+ }
+ }
+
+ /* Set up the stack frame */
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
+ else
+ ret = setup_frame(sig, ka, oldset, regs);
+
+ if (ret == 0) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked,
+ &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked, sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
+
+ return ret;
+}
+
+/*
+ * handle a potential signal
+ */
+static void do_signal(struct pt_regs *regs)
+{
+ struct k_sigaction ka;
+ siginfo_t info;
+ sigset_t *oldset;
+ int signr;
+
+ /* we want the common case to go fast, which is why we may in certain
+ * cases get here from kernel mode */
+ if (!user_mode(regs))
+ return;
+
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
+ oldset = &current->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+ if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+
+ return;
+ }
+
+ /* did we come from a system call? */
+ if (regs->orig_d0 >= 0) {
+ /* restart the system call - no handlers present */
+ switch (regs->d0) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ regs->d0 = regs->orig_d0;
+ regs->pc -= 2;
+ break;
+
+ case -ERESTART_RESTARTBLOCK:
+ regs->d0 = __NR_restart_syscall;
+ regs->pc -= 2;
+ break;
+ }
+ }
+
+ /* if there's no signal to deliver, we just put the saved sigmask
+ * back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
+}
+
+/*
+ * notification of userspace execution resumption
+ * - triggered by current->work.notify_resume
+ */
+asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
+{
+ /* Pending single-step? */
+ if (thread_info_flags & _TIF_SINGLESTEP) {
+#ifndef CONFIG_MN10300_USING_JTAG
+ regs->epsw |= EPSW_T;
+ clear_thread_flag(TIF_SINGLESTEP);
+#else
+ BUG(); /* no h/w single-step if using JTAG unit */
+#endif
+ }
+
+ /* deal with pending signal delivery */
+ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ do_signal(regs);
+}
diff --git a/arch/mn10300/kernel/switch_to.S b/arch/mn10300/kernel/switch_to.S
new file mode 100644
index 00000000000..630aad71b94
--- /dev/null
+++ b/arch/mn10300/kernel/switch_to.S
@@ -0,0 +1,71 @@
+###############################################################################
+#
+# MN10300 Context switch operation
+#
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Written by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/cpu-regs.h>
+
+ .text
+
+###############################################################################
+#
+# struct task_struct *__switch_to(struct thread_struct *prev,
+# struct thread_struct *next,
+# struct task_struct *prev_task)
+#
+###############################################################################
+ENTRY(__switch_to)
+ movm [d2,d3,a2,a3,exreg1],(sp)
+ or EPSW_NMID,epsw
+
+ mov (44,sp),d2
+
+ mov d0,a0
+ mov d1,a1
+
+ # save prev context
+ mov (__frame),d0
+ mov d0,(THREAD_FRAME,a0)
+ mov __switch_back,d0
+ mov d0,(THREAD_PC,a0)
+ mov sp,a2
+ mov a2,(THREAD_SP,a0)
+ mov a3,(THREAD_A3,a0)
+
+ mov (THREAD_A3,a1),a3
+ mov (THREAD_SP,a1),a2
+
+ # switch
+ mov a2,sp
+
+ # load next context
+ GET_THREAD_INFO a2
+ mov a2,(__current_ti)
+ mov (TI_task,a2),a2
+ mov a2,(__current)
+#ifdef CONFIG_MN10300_CURRENT_IN_E2
+ mov a2,e2
+#endif
+
+ mov (THREAD_FRAME,a1),a2
+ mov a2,(__frame)
+ mov (THREAD_PC,a1),a2
+ mov d2,d0 # for ret_from_fork
+ mov d0,a0 # for __switch_to
+
+ jmp (a2)
+
+__switch_back:
+ and ~EPSW_NMID,epsw
+ ret [d2,d3,a2,a3,exreg1],32
diff --git a/arch/mn10300/kernel/sys_mn10300.c b/arch/mn10300/kernel/sys_mn10300.c
new file mode 100644
index 00000000000..5f17a1ebc82
--- /dev/null
+++ b/arch/mn10300/kernel/sys_mn10300.c
@@ -0,0 +1,193 @@
+/* MN10300 Weird system calls
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/utsname.h>
+#include <linux/syscalls.h>
+#include <linux/tty.h>
+
+#include <asm/uaccess.h>
+
+#define MIN_MAP_ADDR PAGE_SIZE /* minimum fixed mmap address */
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way Unix traditionally does this, though.
+ */
+asmlinkage long sys_pipe(unsigned long __user *fildes)
+{
+ int fd[2];
+ int error;
+
+ error = do_pipe(fd);
+ if (!error) {
+ if (copy_to_user(fildes, fd, 2 * sizeof(int)))
+ error = -EFAULT;
+ }
+ return error;
+}
+
+/*
+ * memory mapping syscall
+ */
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ struct file *file = NULL;
+ long error = -EINVAL;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ if (flags & MAP_FIXED && addr < MIN_MAP_ADDR)
+ goto out;
+
+ error = -EBADF;
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+
+ down_write(&current->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(&current->mm->mmap_sem);
+
+ if (file)
+ fput(file);
+out:
+ return error;
+}
+
+asmlinkage long old_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long offset)
+{
+ if (offset & ~PAGE_MASK)
+ return -EINVAL;
+ return sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+}
+
+struct sel_arg_struct {
+ unsigned long n;
+ fd_set *inp;
+ fd_set *outp;
+ fd_set *exp;
+ struct timeval *tvp;
+};
+
+asmlinkage int old_select(struct sel_arg_struct __user *arg)
+{
+ struct sel_arg_struct a;
+
+ if (copy_from_user(&a, arg, sizeof(a)))
+ return -EFAULT;
+ /* sys_select() does the appropriate kernel locking */
+ return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage long sys_ipc(uint call, int first, int second,
+ int third, void __user *ptr, long fifth)
+{
+ int version, ret;
+
+ version = call >> 16; /* hack for backward compatibility */
+ call &= 0xffff;
+
+ switch (call) {
+ case SEMOP:
+ return sys_semtimedop(first, (struct sembuf __user *)ptr,
+ second, NULL);
+ case SEMTIMEDOP:
+ return sys_semtimedop(first, (struct sembuf __user *)ptr,
+ second,
+ (const struct timespec __user *)fifth);
+ case SEMGET:
+ return sys_semget(first, second, third);
+ case SEMCTL: {
+ union semun fourth;
+ if (!ptr)
+ return -EINVAL;
+ if (get_user(fourth.__pad, (void __user * __user *) ptr))
+ return -EFAULT;
+ return sys_semctl(first, second, third, fourth);
+ }
+
+ case MSGSND:
+ return sys_msgsnd(first, (struct msgbuf __user *) ptr,
+ second, third);
+ case MSGRCV:
+ switch (version) {
+ case 0: {
+ struct ipc_kludge tmp;
+ if (!ptr)
+ return -EINVAL;
+
+ if (copy_from_user(&tmp,
+ (struct ipc_kludge __user *) ptr,
+ sizeof(tmp)))
+ return -EFAULT;
+ return sys_msgrcv(first, tmp.msgp, second,
+ tmp.msgtyp, third);
+ }
+ default:
+ return sys_msgrcv(first,
+ (struct msgbuf __user *) ptr,
+ second, fifth, third);
+ }
+ case MSGGET:
+ return sys_msgget((key_t) first, second);
+ case MSGCTL:
+ return sys_msgctl(first, second,
+ (struct msqid_ds __user *) ptr);
+
+ case SHMAT:
+ switch (version) {
+ default: {
+ ulong raddr;
+ ret = do_shmat(first, (char __user *) ptr, second,
+ &raddr);
+ if (ret)
+ return ret;
+ return put_user(raddr, (ulong *) third);
+ }
+ case 1: /* iBCS2 emulator entry point */
+ if (!segment_eq(get_fs(), get_ds()))
+ return -EINVAL;
+ return do_shmat(first, (char __user *) ptr, second,
+ (ulong *) third);
+ }
+ case SHMDT:
+ return sys_shmdt((char __user *)ptr);
+ case SHMGET:
+ return sys_shmget(first, second, third);
+ case SHMCTL:
+ return sys_shmctl(first, second,
+ (struct shmid_ds __user *) ptr);
+ default:
+ return -EINVAL;
+ }
+}
diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c
new file mode 100644
index 00000000000..ff492e3b345
--- /dev/null
+++ b/arch/mn10300/kernel/time.c
@@ -0,0 +1,129 @@
+/* MN10300 Low level time management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from arch/i386/kernel/time.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/profile.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+#include <asm/processor.h>
+#include <asm/intctl-regs.h>
+#include <asm/rtc.h>
+
+#ifdef CONFIG_MN10300_RTC
+unsigned long mn10300_ioclk; /* system I/O clock frequency */
+unsigned long mn10300_iobclk; /* system I/O clock frequency */
+unsigned long mn10300_tsc_per_HZ; /* number of ioclks per jiffy */
+#endif /* CONFIG_MN10300_RTC */
+
+static unsigned long mn10300_last_tsc; /* time-stamp counter at last time
+ * interrupt occurred */
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id);
+
+static struct irqaction timer_irq = {
+ .handler = timer_interrupt,
+ .flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER,
+ .mask = CPU_MASK_NONE,
+ .name = "timer",
+};
+
+/*
+ * scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+ union {
+ unsigned long long l;
+ u32 w[2];
+ } quot;
+
+ quot.w[0] = mn10300_last_tsc - get_cycles();
+ quot.w[1] = 1000000000;
+
+ asm("mulu %2,%3,%0,%1"
+ : "=r"(quot.w[1]), "=r"(quot.w[0])
+ : "0"(quot.w[1]), "1"(quot.w[0])
+ : "cc");
+
+ do_div(quot.l, MN10300_TSCCLK);
+
+ return quot.l;
+}
+
+/*
+ * advance the kernel's time keeping clocks (xtime and jiffies)
+ * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time
+ * there's a need to update
+ */
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+ unsigned tsc, elapse;
+
+ write_seqlock(&xtime_lock);
+
+ while (tsc = get_cycles(),
+ elapse = mn10300_last_tsc - tsc, /* time elapsed since last
+ * tick */
+ elapse > MN10300_TSC_PER_HZ
+ ) {
+ mn10300_last_tsc -= MN10300_TSC_PER_HZ;
+
+ /* advance the kernel's time tracking system */
+ profile_tick(CPU_PROFILING);
+ do_timer(1);
+ update_process_times(user_mode(get_irq_regs()));
+ check_rtc_time();
+ }
+
+ write_sequnlock(&xtime_lock);
+ return IRQ_HANDLED;
+}
+
+/*
+ * initialise the various timers used by the main part of the kernel
+ */
+void __init time_init(void)
+{
+ /* we need the prescalar running to be able to use IOCLK/8
+ * - IOCLK runs at 1/4 (ST5 open) or 1/8 (ST5 closed) internal CPU clock
+ * - IOCLK runs at Fosc rate (crystal speed)
+ */
+ TMPSCNT |= TMPSCNT_ENABLE;
+
+ startup_timestamp_counter();
+
+ printk(KERN_INFO
+ "timestamp counter I/O clock running at %lu.%02lu"
+ " (calibrated against RTC)\n",
+ MN10300_TSCCLK / 1000000, (MN10300_TSCCLK / 10000) % 100);
+
+ xtime.tv_sec = get_initial_rtc_time();
+ xtime.tv_nsec = 0;
+
+ mn10300_last_tsc = TMTSCBC;
+
+ /* use timer 0 & 1 cascaded to tick at as close to HZ as possible */
+ setup_irq(TMJCIRQ, &timer_irq);
+
+ set_intr_level(TMJCIRQ, TMJCICR_LEVEL);
+
+ startup_jiffies_counter();
+
+#ifdef CONFIG_MN10300_WD_TIMER
+ /* start the watchdog timer */
+ watchdog_go();
+#endif
+}
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c
new file mode 100644
index 00000000000..8b9dc6d9dcc
--- /dev/null
+++ b/arch/mn10300/kernel/traps.c
@@ -0,0 +1,619 @@
+/* MN10300 Exception handling
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/kallsyms.h>
+#include <linux/pci.h>
+#include <linux/kdebug.h>
+#include <linux/bug.h>
+#include <linux/irq.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/smp.h>
+#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/cpu-regs.h>
+#include <asm/busctl-regs.h>
+#include <asm/unit/leds.h>
+#include <asm/fpu.h>
+#include <asm/gdb-stub.h>
+#include <asm/sections.h>
+
+#if (CONFIG_INTERRUPT_VECTOR_BASE & 0xffffff)
+#error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!"
+#endif
+
+struct pt_regs *__frame; /* current frame pointer */
+EXPORT_SYMBOL(__frame);
+
+int kstack_depth_to_print = 24;
+
+spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock);
+
+ATOMIC_NOTIFIER_HEAD(mn10300_die_chain);
+
+/*
+ * These constants are for searching for possible module text
+ * segments. MODULE_RANGE is a guess of how much space is likely
+ * to be vmalloced.
+ */
+#define MODULE_RANGE (8 * 1024 * 1024)
+
+#define DO_ERROR(signr, prologue, str, name) \
+asmlinkage void name(struct pt_regs *regs, u32 intcode) \
+{ \
+ prologue; \
+ if (die_if_no_fixup(str, regs, intcode)) \
+ return; \
+ force_sig(signr, current); \
+}
+
+#define DO_EINFO(signr, prologue, str, name, sicode) \
+asmlinkage void name(struct pt_regs *regs, u32 intcode) \
+{ \
+ siginfo_t info; \
+ prologue; \
+ if (die_if_no_fixup(str, regs, intcode)) \
+ return; \
+ info.si_signo = signr; \
+ if (signr == SIGILL && sicode == ILL_ILLOPC) { \
+ uint8_t opcode; \
+ if (get_user(opcode, (uint8_t __user *)regs->pc) == 0) \
+ if (opcode == 0xff) \
+ info.si_signo = SIGTRAP; \
+ } \
+ info.si_errno = 0; \
+ info.si_code = sicode; \
+ info.si_addr = (void *) regs->pc; \
+ force_sig_info(info.si_signo, &info, current); \
+}
+
+DO_ERROR(SIGTRAP, {}, "trap", trap);
+DO_ERROR(SIGSEGV, {}, "ibreak", ibreak);
+DO_ERROR(SIGSEGV, {}, "obreak", obreak);
+DO_EINFO(SIGSEGV, {}, "access error", access_error, SEGV_ACCERR);
+DO_EINFO(SIGSEGV, {}, "insn access error", insn_acc_error, SEGV_ACCERR);
+DO_EINFO(SIGSEGV, {}, "data access error", data_acc_error, SEGV_ACCERR);
+DO_EINFO(SIGILL, {}, "privileged opcode", priv_op, ILL_PRVOPC);
+DO_EINFO(SIGILL, {}, "invalid opcode", invalid_op, ILL_ILLOPC);
+DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC);
+DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR);
+DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR);
+DO_EINFO(SIGILL, {}, "FPU invalid opcode", fpu_invalid_op, ILL_COPROC);
+
+DO_ERROR(SIGTRAP,
+#ifndef CONFIG_MN10300_USING_JTAG
+ DCR &= ~0x0001,
+#else
+ {},
+#endif
+ "single step", istep);
+
+/*
+ * handle NMI
+ */
+asmlinkage void nmi(struct pt_regs *regs, enum exception_code code)
+{
+ /* see if gdbstub wants to deal with it */
+#ifdef CONFIG_GDBSTUB
+ if (gdbstub_intercept(regs, code))
+ return;
+#endif
+
+ printk(KERN_WARNING "--- Register Dump ---\n");
+ show_registers(regs);
+ printk(KERN_WARNING "---------------------\n");
+}
+
+/*
+ * show a stack trace from the specified stack pointer
+ */
+void show_trace(unsigned long *sp)
+{
+ unsigned long *stack, addr, module_start, module_end;
+ int i;
+
+ printk(KERN_EMERG "\n"
+ KERN_EMERG "Call Trace:");
+
+ stack = sp;
+ i = 0;
+ module_start = VMALLOC_START;
+ module_end = VMALLOC_END;
+
+ while (((long) stack & (THREAD_SIZE - 1)) != 0) {
+ addr = *stack++;
+ if (__kernel_text_address(addr)) {
+#if 1
+ printk(" [<%08lx>]", addr);
+ print_symbol(" %s", addr);
+ printk("\n");
+#else
+ if ((i % 6) == 0)
+ printk("\n" KERN_EMERG " ");
+ printk("[<%08lx>] ", addr);
+ i++;
+#endif
+ }
+ }
+
+ printk("\n");
+}
+
+/*
+ * show the raw stack from the specified stack pointer
+ */
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+ unsigned long *stack;
+ int i;
+
+ if (!sp)
+ sp = (unsigned long *) &sp;
+
+ stack = sp;
+ printk(KERN_EMERG "Stack:");
+ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (((long) stack & (THREAD_SIZE - 1)) == 0)
+ break;
+ if ((i % 8) == 0)
+ printk("\n" KERN_EMERG " ");
+ printk("%08lx ", *stack++);
+ }
+
+ show_trace(sp);
+}
+
+/*
+ * the architecture-independent dump_stack generator
+ */
+void dump_stack(void)
+{
+ unsigned long stack;
+
+ show_stack(current, &stack);
+}
+EXPORT_SYMBOL(dump_stack);
+
+/*
+ * dump the register file in the specified exception frame
+ */
+void show_registers_only(struct pt_regs *regs)
+{
+ unsigned long ssp;
+
+ ssp = (unsigned long) regs + sizeof(*regs);
+
+ printk(KERN_EMERG "PC: %08lx EPSW: %08lx SSP: %08lx mode: %s\n",
+ regs->pc, regs->epsw, ssp, user_mode(regs) ? "User" : "Super");
+ printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
+ regs->d0, regs->d1, regs->d2, regs->d3);
+ printk(KERN_EMERG "a0: %08lx a1: %08lx a2: %08lx a3: %08lx\n",
+ regs->a0, regs->a1, regs->a2, regs->a3);
+ printk(KERN_EMERG "e0: %08lx e1: %08lx e2: %08lx e3: %08lx\n",
+ regs->e0, regs->e1, regs->e2, regs->e3);
+ printk(KERN_EMERG "e4: %08lx e5: %08lx e6: %08lx e7: %08lx\n",
+ regs->e4, regs->e5, regs->e6, regs->e7);
+ printk(KERN_EMERG "lar: %08lx lir: %08lx mdr: %08lx usp: %08lx\n",
+ regs->lar, regs->lir, regs->mdr, regs->sp);
+ printk(KERN_EMERG "cvf: %08lx crl: %08lx crh: %08lx drq: %08lx\n",
+ regs->mcvf, regs->mcrl, regs->mcrh, regs->mdrq);
+ printk(KERN_EMERG "threadinfo=%p task=%p)\n",
+ current_thread_info(), current);
+
+ if ((unsigned long) current >= 0x90000000UL &&
+ (unsigned long) current < 0x94000000UL)
+ printk(KERN_EMERG "Process %s (pid: %d)\n",
+ current->comm, current->pid);
+
+ printk(KERN_EMERG "CPUP: %04hx\n", CPUP);
+ printk(KERN_EMERG "TBR: %08x\n", TBR);
+ printk(KERN_EMERG "DEAR: %08x\n", DEAR);
+ printk(KERN_EMERG "sISR: %08x\n", sISR);
+ printk(KERN_EMERG "NMICR: %04hx\n", NMICR);
+ printk(KERN_EMERG "BCBERR: %08x\n", BCBERR);
+ printk(KERN_EMERG "BCBEAR: %08x\n", BCBEAR);
+ printk(KERN_EMERG "MMUFCR: %08x\n", MMUFCR);
+ printk(KERN_EMERG "IPTEU : %08x IPTEL2: %08x\n", IPTEU, IPTEL2);
+ printk(KERN_EMERG "DPTEU: %08x DPTEL2: %08x\n", DPTEU, DPTEL2);
+}
+
+/*
+ * dump the registers and the stack
+ */
+void show_registers(struct pt_regs *regs)
+{
+ unsigned long sp;
+ int i;
+
+ show_registers_only(regs);
+
+ if (!user_mode(regs))
+ sp = (unsigned long) regs + sizeof(*regs);
+ else
+ sp = regs->sp;
+
+ /* when in-kernel, we also print out the stack and code at the
+ * time of the fault..
+ */
+ if (!user_mode(regs)) {
+ printk(KERN_EMERG "\n");
+ show_stack(current, (unsigned long *) sp);
+
+#if 0
+ printk(KERN_EMERG "\n"
+ KERN_EMERG "Code: ");
+ if (regs->pc < PAGE_OFFSET)
+ goto bad;
+
+ for (i = 0; i < 20; i++) {
+ unsigned char c;
+ if (__get_user(c, &((unsigned char *) regs->pc)[i]))
+ goto bad;
+ printk("%02x ", c);
+ }
+#else
+ i = 0;
+#endif
+ }
+
+ printk("\n");
+ return;
+
+#if 0
+bad:
+ printk(KERN_EMERG " Bad PC value.");
+ break;
+#endif
+}
+
+/*
+ *
+ */
+void show_trace_task(struct task_struct *tsk)
+{
+ unsigned long sp = tsk->thread.sp;
+
+ /* User space on another CPU? */
+ if ((sp ^ (unsigned long) tsk) & (PAGE_MASK << 1))
+ return;
+
+ show_trace((unsigned long *) sp);
+}
+
+/*
+ * note the untimely death of part of the kernel
+ */
+void die(const char *str, struct pt_regs *regs, enum exception_code code)
+{
+ console_verbose();
+ spin_lock_irq(&die_lock);
+ printk(KERN_EMERG "\n"
+ KERN_EMERG "%s: %04x\n",
+ str, code & 0xffff);
+ show_registers(regs);
+
+ if (regs->pc >= 0x02000000 && regs->pc < 0x04000000 &&
+ (regs->epsw & (EPSW_IM | EPSW_IE)) != (EPSW_IM | EPSW_IE)) {
+ printk(KERN_EMERG "Exception in usermode interrupt handler\n");
+ printk(KERN_EMERG "\n"
+ KERN_EMERG " Please connect to kernel debugger !!\n");
+ asm volatile ("0: bra 0b");
+ }
+
+ spin_unlock_irq(&die_lock);
+ do_exit(SIGSEGV);
+}
+
+/*
+ * see if there's a fixup handler we can force a jump to when an exception
+ * happens due to something kernel code did
+ */
+int die_if_no_fixup(const char *str, struct pt_regs *regs,
+ enum exception_code code)
+{
+ if (user_mode(regs))
+ return 0;
+
+ peripheral_leds_display_exception(code);
+
+ switch (code) {
+ /* see if we can fixup the kernel accessing memory */
+ case EXCEP_ITLBMISS:
+ case EXCEP_DTLBMISS:
+ case EXCEP_IAERROR:
+ case EXCEP_DAERROR:
+ case EXCEP_MEMERR:
+ case EXCEP_MISALIGN:
+ case EXCEP_BUSERROR:
+ case EXCEP_ILLDATACC:
+ case EXCEP_IOINSACC:
+ case EXCEP_PRIVINSACC:
+ case EXCEP_PRIVDATACC:
+ case EXCEP_DATINSACC:
+ if (fixup_exception(regs))
+ return 1;
+ case EXCEP_UNIMPINS:
+ if (regs->pc && *(uint8_t *)regs->pc == 0xff)
+ if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0))
+ return 1;
+ break;
+ default:
+ break;
+ }
+
+ /* see if gdbstub wants to deal with it */
+#ifdef CONFIG_GDBSTUB
+ if (gdbstub_intercept(regs, code))
+ return 1;
+#endif
+
+ if (notify_die(DIE_GPF, str, regs, code, 0, 0))
+ return 1;
+
+ /* make the process die as the last resort */
+ die(str, regs, code);
+}
+
+/*
+ * handle unsupported syscall instructions (syscall 1-15)
+ */
+static asmlinkage void unsupported_syscall(struct pt_regs *regs,
+ enum exception_code code)
+{
+ struct task_struct *tsk = current;
+ siginfo_t info;
+
+ /* catch a kernel BUG() */
+ if (code == EXCEP_SYSCALL15 && !user_mode(regs)) {
+ if (report_bug(regs->pc, regs) == BUG_TRAP_TYPE_BUG) {
+#ifdef CONFIG_GDBSTUB
+ __gdbstub_bug_trap();
+#endif
+ }
+ }
+
+ regs->pc -= 2; /* syscall return addr is _after_ the instruction */
+
+ die_if_no_fixup("An unsupported syscall insn was used by the kernel\n",
+ regs, code);
+
+ info.si_signo = SIGILL;
+ info.si_errno = ENOSYS;
+ info.si_code = ILL_ILLTRP;
+ info.si_addr = (void *) regs->pc;
+ force_sig_info(SIGILL, &info, tsk);
+}
+
+/*
+ * display the register file when the stack pointer gets clobbered
+ */
+asmlinkage void do_double_fault(struct pt_regs *regs)
+{
+ struct task_struct *tsk = current;
+
+ strcpy(tsk->comm, "emergency tsk");
+ tsk->pid = 0;
+ console_verbose();
+ printk(KERN_EMERG "--- double fault ---\n");
+ show_registers(regs);
+}
+
+/*
+ * asynchronous bus error (external, usually I/O DMA)
+ */
+asmlinkage void io_bus_error(u32 bcberr, u32 bcbear, struct pt_regs *regs)
+{
+ console_verbose();
+
+ printk(KERN_EMERG "\n"
+ KERN_EMERG "Asynchronous I/O Bus Error\n"
+ KERN_EMERG "==========================\n");
+
+ if (bcberr & BCBERR_BEME)
+ printk(KERN_EMERG "- Multiple recorded errors\n");
+
+ printk(KERN_EMERG "- Faulting Buses:%s%s%s\n",
+ bcberr & BCBERR_BEMR_CI ? " CPU-Ins-Fetch" : "",
+ bcberr & BCBERR_BEMR_CD ? " CPU-Data" : "",
+ bcberr & BCBERR_BEMR_DMA ? " DMA" : "");
+
+ printk(KERN_EMERG "- %s %s access made to %s at address %08x\n",
+ bcberr & BCBERR_BEBST ? "Burst" : "Single",
+ bcberr & BCBERR_BERW ? "Read" : "Write",
+ bcberr & BCBERR_BESB_MON ? "Monitor Space" :
+ bcberr & BCBERR_BESB_IO ? "Internal CPU I/O Space" :
+ bcberr & BCBERR_BESB_EX ? "External I/O Bus" :
+ bcberr & BCBERR_BESB_OPEX ? "External Memory Bus" :
+ "On Chip Memory",
+ bcbear
+ );
+
+ printk(KERN_EMERG "- Detected by the %s\n",
+ bcberr&BCBERR_BESD ? "Bus Control Unit" : "Slave Bus");
+
+#ifdef CONFIG_PCI
+#define BRIDGEREGB(X) (*(volatile __u8 *)(0xBE040000 + (X)))
+#define BRIDGEREGW(X) (*(volatile __u16 *)(0xBE040000 + (X)))
+#define BRIDGEREGL(X) (*(volatile __u32 *)(0xBE040000 + (X)))
+
+ printk(KERN_EMERG "- PCI Memory Paging Reg: %08x\n",
+ *(volatile __u32 *) (0xBFFFFFF4));
+ printk(KERN_EMERG "- PCI Bridge Base Address 0: %08x\n",
+ BRIDGEREGL(PCI_BASE_ADDRESS_0));
+ printk(KERN_EMERG "- PCI Bridge AMPCI Base Address: %08x\n",
+ BRIDGEREGL(0x48));
+ printk(KERN_EMERG "- PCI Bridge Command: %04hx\n",
+ BRIDGEREGW(PCI_COMMAND));
+ printk(KERN_EMERG "- PCI Bridge Status: %04hx\n",
+ BRIDGEREGW(PCI_STATUS));
+ printk(KERN_EMERG "- PCI Bridge Int Status: %08hx\n",
+ BRIDGEREGL(0x4c));
+#endif
+
+ printk(KERN_EMERG "\n");
+ show_registers(regs);
+
+ panic("Halted due to asynchronous I/O Bus Error\n");
+}
+
+/*
+ * handle an exception for which a handler has not yet been installed
+ */
+asmlinkage void uninitialised_exception(struct pt_regs *regs,
+ enum exception_code code)
+{
+
+ /* see if gdbstub wants to deal with it */
+#ifdef CONFIG_GDBSTUB
+ if (gdbstub_intercept(regs, code))
+ return;
+#endif
+
+ peripheral_leds_display_exception(code);
+ printk(KERN_EMERG "Uninitialised Exception 0x%04x\n", code & 0xFFFF);
+ show_registers(regs);
+
+ for (;;)
+ continue;
+}
+
+/*
+ * set an interrupt stub to jump to a handler
+ * ! NOTE: this does *not* flush the caches
+ */
+void __init __set_intr_stub(enum exception_code code, void *handler)
+{
+ unsigned long addr;
+ u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
+
+ addr = (unsigned long) handler - (unsigned long) vector;
+ vector[0] = 0xdc; /* JMP handler */
+ vector[1] = addr;
+ vector[2] = addr >> 8;
+ vector[3] = addr >> 16;
+ vector[4] = addr >> 24;
+ vector[5] = 0xcb;
+ vector[6] = 0xcb;
+ vector[7] = 0xcb;
+}
+
+/*
+ * set an interrupt stub to jump to a handler
+ */
+void __init set_intr_stub(enum exception_code code, void *handler)
+{
+ unsigned long addr;
+ u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
+
+ addr = (unsigned long) handler - (unsigned long) vector;
+ vector[0] = 0xdc; /* JMP handler */
+ vector[1] = addr;
+ vector[2] = addr >> 8;
+ vector[3] = addr >> 16;
+ vector[4] = addr >> 24;
+ vector[5] = 0xcb;
+ vector[6] = 0xcb;
+ vector[7] = 0xcb;
+
+ mn10300_dcache_flush_inv();
+ mn10300_icache_inv();
+}
+
+/*
+ * set an interrupt stub to invoke the JTAG unit and then jump to a handler
+ */
+void __init set_jtag_stub(enum exception_code code, void *handler)
+{
+ unsigned long addr;
+ u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code);
+
+ addr = (unsigned long) handler - ((unsigned long) vector + 1);
+ vector[0] = 0xff; /* PI to jump into JTAG debugger */
+ vector[1] = 0xdc; /* jmp handler */
+ vector[2] = addr;
+ vector[3] = addr >> 8;
+ vector[4] = addr >> 16;
+ vector[5] = addr >> 24;
+ vector[6] = 0xcb;
+ vector[7] = 0xcb;
+
+ mn10300_dcache_flush_inv();
+ flush_icache_range((unsigned long) vector, (unsigned long) vector + 8);
+}
+
+/*
+ * initialise the exception table
+ */
+void __init trap_init(void)
+{
+ set_excp_vector(EXCEP_TRAP, trap);
+ set_excp_vector(EXCEP_ISTEP, istep);
+ set_excp_vector(EXCEP_IBREAK, ibreak);
+ set_excp_vector(EXCEP_OBREAK, obreak);
+
+ set_excp_vector(EXCEP_PRIVINS, priv_op);
+ set_excp_vector(EXCEP_UNIMPINS, invalid_op);
+ set_excp_vector(EXCEP_UNIMPEXINS, invalid_exop);
+ set_excp_vector(EXCEP_MEMERR, mem_error);
+ set_excp_vector(EXCEP_MISALIGN, misalignment);
+ set_excp_vector(EXCEP_BUSERROR, bus_error);
+ set_excp_vector(EXCEP_ILLINSACC, insn_acc_error);
+ set_excp_vector(EXCEP_ILLDATACC, data_acc_error);
+ set_excp_vector(EXCEP_IOINSACC, insn_acc_error);
+ set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error);
+ set_excp_vector(EXCEP_PRIVDATACC, data_acc_error);
+ set_excp_vector(EXCEP_DATINSACC, insn_acc_error);
+ set_excp_vector(EXCEP_FPU_DISABLED, fpu_disabled);
+ set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op);
+ set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception);
+
+ set_excp_vector(EXCEP_NMI, nmi);
+
+ set_excp_vector(EXCEP_SYSCALL1, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL2, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL3, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL4, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL5, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL6, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL7, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL8, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL9, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL10, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL11, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL12, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL13, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL14, unsupported_syscall);
+ set_excp_vector(EXCEP_SYSCALL15, unsupported_syscall);
+}
+
+/*
+ * determine if a program counter value is a valid bug address
+ */
+int is_valid_bugaddr(unsigned long pc)
+{
+ return pc >= PAGE_OFFSET;
+}
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
new file mode 100644
index 00000000000..a3e80f444f5
--- /dev/null
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -0,0 +1,159 @@
+/* MN10300 Main kernel linker script
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#define __VMLINUX_LDS__
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/thread_info.h>
+
+OUTPUT_FORMAT("elf32-am33lin", "elf32-am33lin", "elf32-am33lin")
+OUTPUT_ARCH(mn10300)
+ENTRY(_start)
+jiffies = jiffies_64;
+#ifndef CONFIG_MN10300_CURRENT_IN_E2
+current = __current;
+#endif
+SECTIONS
+{
+ . = CONFIG_KERNEL_TEXT_ADDRESS;
+ /* read-only */
+ _stext = .;
+ _text = .; /* Text and read-only data */
+ .text : {
+ *(
+ .text.head
+ .text
+ )
+ TEXT_TEXT
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+ } = 0xcb
+
+ _etext = .; /* End of text section */
+
+ . = ALIGN(16); /* Exception table */
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ BUG_TABLE
+
+ RODATA
+
+ /* writeable */
+ .data : { /* Data */
+ DATA_DATA
+ CONSTRUCTORS
+ }
+
+ . = ALIGN(4096);
+ __nosave_begin = .;
+ .data_nosave : { *(.data.nosave) }
+ . = ALIGN(4096);
+ __nosave_end = .;
+
+ . = ALIGN(4096);
+ .data.page_aligned : { *(.data.idt) }
+
+ . = ALIGN(32);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+ /* rarely changed data like cpu maps */
+ . = ALIGN(32);
+ .data.read_mostly : AT(ADDR(.data.read_mostly)) {
+ *(.data.read_mostly)
+ _edata = .; /* End of data section */
+ }
+
+ . = ALIGN(THREAD_SIZE); /* init_task */
+ .data.init_task : { *(.data.init_task) }
+
+ /* might get freed after init */
+ . = ALIGN(4096);
+ .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
+ __smp_locks = .;
+ *(.smp_locks)
+ __smp_locks_end = .;
+ }
+
+ /* will be freed after init */
+ . = ALIGN(4096); /* Init code and data */
+ __init_begin = .;
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
+ .init.data : { *(.init.data) }
+ . = ALIGN(16);
+ __setup_start = .;
+ .setup.init : { KEEP(*(.init.setup)) }
+ __setup_end = .;
+
+ __initcall_start = .;
+ .initcall.init : {
+ INITCALLS
+ }
+ __initcall_end = .;
+ __con_initcall_start = .;
+ .con_initcall.init : { *(.con_initcall.init) }
+ __con_initcall_end = .;
+
+ SECURITY_INIT
+ . = ALIGN(4);
+ __alt_instructions = .;
+ .altinstructions : { *(.altinstructions) }
+ __alt_instructions_end = .;
+ .altinstr_replacement : { *(.altinstr_replacement) }
+ /* .exit.text is discard at runtime, not link time, to deal with references
+ from .altinstructions and .eh_frame */
+ .exit.text : { *(.exit.text) }
+ .exit.data : { *(.exit.data) }
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ . = ALIGN(4096);
+ __initramfs_start = .;
+ .init.ramfs : { *(.init.ramfs) }
+ __initramfs_end = .;
+#endif
+
+ . = ALIGN(32);
+ __per_cpu_start = .;
+ .data.percpu : { *(.data.percpu) }
+ __per_cpu_end = .;
+ . = ALIGN(4096);
+ __init_end = .;
+ /* freed after init ends here */
+
+ __bss_start = .; /* BSS */
+ .bss : {
+ *(.bss.page_aligned)
+ *(.bss)
+ }
+ . = ALIGN(4);
+ __bss_stop = .;
+
+ _end = . ;
+
+ /* This is where the kernel creates the early boot page tables */
+ . = ALIGN(4096);
+ pg0 = .;
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.exitcall.exit)
+ }
+
+ STABS_DEBUG
+
+ DWARF_DEBUG
+}
diff --git a/arch/mn10300/lib/Makefile b/arch/mn10300/lib/Makefile
new file mode 100644
index 00000000000..fdfa9ec5b5b
--- /dev/null
+++ b/arch/mn10300/lib/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the MN10300-specific library files..
+#
+
+lib-y = delay.o usercopy.o checksum.o bitops.o memcpy.o memmove.o memset.o
+lib-y += do_csum.o
+lib-y += __ashldi3.o __ashrdi3.o __lshrdi3.o negdi2.o
diff --git a/arch/mn10300/lib/__ashldi3.S b/arch/mn10300/lib/__ashldi3.S
new file mode 100644
index 00000000000..a51a9506f00
--- /dev/null
+++ b/arch/mn10300/lib/__ashldi3.S
@@ -0,0 +1,51 @@
+/* MN10300 64-bit arithmetic left shift
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+ .text
+ .balign L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned long long __ashldi3(unsigned long long value [D1:D0],
+# unsigned by [(12,SP)])
+#
+###############################################################################
+ .globl __ashldi3
+ .type __ashldi3,@function
+__ashldi3:
+ mov (12,sp),a0
+ and +63,a0
+ beq __ashldi3_zero
+
+ cmp +31,a0
+ bhi __ashldi3_32plus
+
+ # the count is in the range 1-31
+ asl a0,d1
+
+ mov +32,a1
+ sub a0,a1,a1 # a1 = 32 - count
+ lsr a1,d0,a1 # get overflow from LSW -> MSW
+
+ or_asl a1,d1,a0,d0 # insert overflow into MSW and
+ # shift the LSW
+ rets
+
+ .balign L1_CACHE_BYTES
+ # the count is in the range 32-63
+__ashldi3_32plus:
+ asl a0,d0,d1
+ clr d0
+__ashldi3_zero:
+ rets
+
+ .size __ashldi3, .-__ashldi3
diff --git a/arch/mn10300/lib/__ashrdi3.S b/arch/mn10300/lib/__ashrdi3.S
new file mode 100644
index 00000000000..6f42382728c
--- /dev/null
+++ b/arch/mn10300/lib/__ashrdi3.S
@@ -0,0 +1,52 @@
+/* MN10300 64-bit arithmetic right shift
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+ .text
+ .balign L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned long long __ashrdi3(unsigned long long value [D1:D0],
+# unsigned by [(12,SP)])
+#
+###############################################################################
+ .globl __ashrdi3
+ .type __ashrdi3,@function
+__ashrdi3:
+ mov (12,sp),a0
+ and +63,a0
+ beq __ashrdi3_zero
+
+ cmp +31,a0
+ bhi __ashrdi3_32plus
+
+ # the count is in the range 1-31
+ lsr a0,d0
+
+ mov +32,a1
+ sub a0,a1,a1 # a1 = 32 - count
+ asl a1,d1,a1 # get underflow from MSW -> LSW
+
+ or_asr a1,d0,a0,d1 # insert underflow into LSW and
+ # shift the MSW
+ rets
+
+ .balign L1_CACHE_BYTES
+ # the count is in the range 32-63
+__ashrdi3_32plus:
+ asr a0,d1,d0
+ ext d0 # sign-extend result through MDR
+ mov mdr,d1
+__ashrdi3_zero:
+ rets
+
+ .size __ashrdi3, .-__ashrdi3
diff --git a/arch/mn10300/lib/__lshrdi3.S b/arch/mn10300/lib/__lshrdi3.S
new file mode 100644
index 00000000000..a686aef31e9
--- /dev/null
+++ b/arch/mn10300/lib/__lshrdi3.S
@@ -0,0 +1,52 @@
+/* MN10300 64-bit logical right shift
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <asm/cache.h>
+
+ .text
+ .balign L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned long long __lshrdi3(unsigned long long value [D1:D0],
+# unsigned by [(12,SP)])
+#
+###############################################################################
+ .globl __lshrdi3
+ .type __lshrdi3,@function
+__lshrdi3:
+ mov (12,sp),a0
+ and +63,a0
+ beq __lshrdi3_zero
+
+ cmp +31,a0
+ bhi __lshrdi3_32plus
+
+ # the count is in the range 1-31
+ lsr a0,d0
+
+ mov +32,a1
+ sub a0,a1,a1 # a1 = 32 - count
+ asl a1,d1,a1 # get underflow from MSW -> LSW
+
+ or_lsr a1,d0,a0,d1 # insert underflow into LSW and
+ # shift the MSW
+ rets
+
+ .balign L1_CACHE_BYTES
+ # the count is in the range 32-63
+__lshrdi3_32plus:
+ lsr a0,d1,d0
+ clr d1
+__lshrdi3_zero:
+ rets
+
+ .size __lshrdi3, .-__lshrdi3
diff --git a/arch/mn10300/lib/ashrdi3.c b/arch/mn10300/lib/ashrdi3.c
new file mode 100644
index 00000000000..c54f61ddf0b
--- /dev/null
+++ b/arch/mn10300/lib/ashrdi3.c
@@ -0,0 +1,61 @@
+/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC 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 Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define BITS_PER_UNIT 8
+
+typedef int SItype __attribute__((mode(SI)));
+typedef unsigned int USItype __attribute__((mode(SI)));
+typedef int DItype __attribute__((mode(DI)));
+typedef int word_type __attribute__((mode(__word__)));
+
+struct DIstruct {
+ SItype low;
+ SItype high;
+};
+
+union DIunion {
+ struct DIstruct s;
+ DItype ll;
+};
+
+DItype __ashrdi3(DItype u, word_type b)
+{
+ union DIunion w;
+ union DIunion uu;
+ word_type bm;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+
+ bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
+ if (bm <= 0) {
+ /* w.s.high = 1..1 or 0..0 */
+ w.s.high = uu.s.high >> (sizeof(SItype) * BITS_PER_UNIT - 1);
+ w.s.low = uu.s.high >> -bm;
+ } else {
+ USItype carries = (USItype)uu.s.high << bm;
+ w.s.high = uu.s.high >> b;
+ w.s.low = ((USItype)uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
diff --git a/arch/mn10300/lib/bitops.c b/arch/mn10300/lib/bitops.c
new file mode 100644
index 00000000000..440a7dcbf87
--- /dev/null
+++ b/arch/mn10300/lib/bitops.c
@@ -0,0 +1,51 @@
+/* MN10300 Non-trivial bit operations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <asm/bitops.h>
+#include <asm/system.h>
+
+/*
+ * try flipping a bit using BSET and BCLR
+ */
+void change_bit(int nr, volatile void *addr)
+{
+ if (test_bit(nr, addr))
+ goto try_clear_bit;
+
+try_set_bit:
+ if (!test_and_set_bit(nr, addr))
+ return;
+
+try_clear_bit:
+ if (test_and_clear_bit(nr, addr))
+ return;
+
+ goto try_set_bit;
+}
+
+/*
+ * try flipping a bit using BSET and BCLR and returning the old value
+ */
+int test_and_change_bit(int nr, volatile void *addr)
+{
+ if (test_bit(nr, addr))
+ goto try_clear_bit;
+
+try_set_bit:
+ if (!test_and_set_bit(nr, addr))
+ return 0;
+
+try_clear_bit:
+ if (test_and_clear_bit(nr, addr))
+ return 1;
+
+ goto try_set_bit;
+}
diff --git a/arch/mn10300/lib/checksum.c b/arch/mn10300/lib/checksum.c
new file mode 100644
index 00000000000..274f29ec33c
--- /dev/null
+++ b/arch/mn10300/lib/checksum.c
@@ -0,0 +1,99 @@
+/* MN10300 Optimised checksumming wrappers
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#include "internal.h"
+
+static inline unsigned short from32to16(__wsum sum)
+{
+ asm(" add %1,%0 \n"
+ " addc 0xffff,%0 \n"
+ : "=r" (sum)
+ : "r" (sum << 16), "0" (sum & 0xffff0000)
+ );
+ return sum >> 16;
+}
+
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+ return ~do_csum(iph, ihl * 4);
+}
+EXPORT_SYMBOL(ip_fast_csum);
+
+__wsum csum_partial(const void *buff, int len, __wsum sum)
+{
+ __wsum result;
+
+ result = do_csum(buff, len);
+ result += sum;
+ if (sum > result)
+ result++;
+ return result;
+}
+EXPORT_SYMBOL(csum_partial);
+
+__sum16 ip_compute_csum(const void *buff, int len)
+{
+ return ~from32to16(do_csum(buff, len));
+}
+EXPORT_SYMBOL(ip_compute_csum);
+
+__wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
+{
+ copy_from_user(dst, src, len);
+ return csum_partial(dst, len, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy);
+
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+ int len, __wsum sum)
+{
+ sum = csum_partial(src, len, sum);
+ memcpy(dst, src, len);
+ return sum;
+}
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+
+__wsum csum_partial_copy_from_user(const void *src, void *dst,
+ int len, __wsum sum,
+ int *err_ptr)
+{
+ int missing;
+
+ missing = copy_from_user(dst, src, len);
+ if (missing) {
+ memset(dst + len - missing, 0, missing);
+ *err_ptr = -EFAULT;
+ }
+
+ return csum_partial(dst, len, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy_from_user);
+
+__wsum csum_and_copy_to_user(const void *src, void *dst,
+ int len, __wsum sum,
+ int *err_ptr)
+{
+ int missing;
+
+ missing = copy_to_user(dst, src, len);
+ if (missing) {
+ memset(dst + len - missing, 0, missing);
+ *err_ptr = -EFAULT;
+ }
+
+ return csum_partial(src, len, sum);
+}
+EXPORT_SYMBOL(csum_and_copy_to_user);
diff --git a/arch/mn10300/lib/delay.c b/arch/mn10300/lib/delay.c
new file mode 100644
index 00000000000..cce66bc0822
--- /dev/null
+++ b/arch/mn10300/lib/delay.c
@@ -0,0 +1,50 @@
+/* MN10300 Short delay interpolation routines
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <asm/div64.h>
+
+/*
+ * basic delay loop
+ */
+void __delay(unsigned long loops)
+{
+ int d0;
+
+ asm volatile(
+ " bra 1f \n"
+ " .align 4 \n"
+ "1: bra 2f \n"
+ " .align 4 \n"
+ "2: add -1,%0 \n"
+ " bne 2b \n"
+ : "=&d" (d0)
+ : "0" (loops));
+}
+EXPORT_SYMBOL(__delay);
+
+/*
+ * handle a delay specified in terms of microseconds
+ */
+void __udelay(unsigned long usecs)
+{
+ signed long ioclk, stop;
+
+ /* usecs * CLK / 1E6 */
+ stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000);
+ stop = TMTSCBC - stop;
+
+ do {
+ ioclk = TMTSCBC;
+ } while (stop < ioclk);
+}
+EXPORT_SYMBOL(__udelay);
diff --git a/arch/mn10300/lib/do_csum.S b/arch/mn10300/lib/do_csum.S
new file mode 100644
index 00000000000..e138994e166
--- /dev/null
+++ b/arch/mn10300/lib/do_csum.S
@@ -0,0 +1,162 @@
+/* Optimised simple memory checksum
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+ .section .text
+ .balign L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned int do_csum(const unsigned char *buff, size_t len)
+#
+###############################################################################
+ .globl do_csum
+ .type do_csum,@function
+do_csum:
+ movm [d2,d3],(sp)
+ mov d0,(12,sp)
+ mov d1,(16,sp)
+ mov d1,d2 # count
+ mov d0,a0 # buff
+ clr d1 # accumulator
+
+ cmp +0,d2
+ beq do_csum_done # return if zero-length buffer
+
+ # 4-byte align the buffer pointer
+ btst +3,a0
+ beq do_csum_now_4b_aligned
+
+ btst +1,a0
+ beq do_csum_addr_not_odd
+ movbu (a0),d0
+ inc a0
+ asl +8,d0
+ add d0,d1
+ addc +0,d1
+ add -1,d2
+do_csum_addr_not_odd:
+
+ cmp +2,d2
+ bcs do_csum_fewer_than_4
+ btst +2,a0
+ beq do_csum_now_4b_aligned
+ movhu (a0+),d0
+ add d0,d1
+ addc +0,d1
+ add -2,d2
+ cmp +4,d2
+ bcs do_csum_fewer_than_4
+
+do_csum_now_4b_aligned:
+ # we want to checksum as much as we can in chunks of 32 bytes
+ cmp +31,d2
+ bls do_csum_remainder # 4-byte aligned remainder
+
+ add -32,d2
+ mov +32,d3
+
+do_csum_loop:
+ mov (a0+),d0
+ add d0,d1
+ mov (a0+),e0
+ addc e0,d1
+ mov (a0+),e1
+ addc e1,d1
+ mov (a0+),e3
+ addc e3,d1
+ mov (a0+),d0
+ addc d0,d1
+ mov (a0+),e0
+ addc e0,d1
+ mov (a0+),e1
+ addc e1,d1
+ mov (a0+),e3
+ addc e3,d1
+ addc +0,d1
+
+ sub d3,d2
+ bcc do_csum_loop
+
+ add d3,d2
+ beq do_csum_done
+
+do_csum_remainder:
+ # cut 16-31 bytes down to 0-15
+ cmp +16,d2
+ bcs do_csum_fewer_than_16
+ mov (a0+),d0
+ add d0,d1
+ mov (a0+),e0
+ addc e0,d1
+ mov (a0+),e1
+ addc e1,d1
+ mov (a0+),e3
+ addc e3,d1
+ addc +0,d1
+ add -16,d2
+ beq do_csum_done
+
+do_csum_fewer_than_16:
+ # copy the remaining whole words
+ cmp +4,d2
+ bcs do_csum_fewer_than_4
+ cmp +8,d2
+ bcs do_csum_one_word
+ cmp +12,d2
+ bcs do_csum_two_words
+ mov (a0+),d0
+ add d0,d1
+ addc +0,d1
+do_csum_two_words:
+ mov (a0+),d0
+ add d0,d1
+ addc +0,d1
+do_csum_one_word:
+ mov (a0+),d0
+ add d0,d1
+ addc +0,d1
+
+do_csum_fewer_than_4:
+ and +3,d2
+ beq do_csum_done
+ xor_cmp d0,d0,+2,d2
+ bcs do_csum_fewer_than_2
+ movhu (a0+),d0
+do_csum_fewer_than_2:
+ and +1,d2
+ beq do_csum_add_last_bit
+ movbu (a0),d3
+ add d3,d0
+do_csum_add_last_bit:
+ add d0,d1
+ addc +0,d1
+
+do_csum_done:
+ # compress the checksum down to 16 bits
+ mov +0xffff0000,d2
+ and d1,d2
+ asl +16,d1
+ add d2,d1,d0
+ addc +0xffff,d0
+ lsr +16,d0
+
+ # flip the halves of the word result if the buffer was oddly aligned
+ mov (12,sp),d1
+ and +1,d1
+ beq do_csum_not_oddly_aligned
+ swaph d0,d0 # exchange bits 15:8 with 7:0
+
+do_csum_not_oddly_aligned:
+ ret [d2,d3],8
+
+do_csum_end:
+ .size do_csum, do_csum_end-do_csum
diff --git a/arch/mn10300/lib/internal.h b/arch/mn10300/lib/internal.h
new file mode 100644
index 00000000000..0014eee5f04
--- /dev/null
+++ b/arch/mn10300/lib/internal.h
@@ -0,0 +1,15 @@
+/* Internal definitions for the arch part of the kernel library
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+/*
+ * do_csum.S
+ */
+extern unsigned int do_csum(const unsigned char *, size_t);
diff --git a/arch/mn10300/lib/lshrdi3.c b/arch/mn10300/lib/lshrdi3.c
new file mode 100644
index 00000000000..e05e64e9ce9
--- /dev/null
+++ b/arch/mn10300/lib/lshrdi3.c
@@ -0,0 +1,60 @@
+/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC 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 Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define BITS_PER_UNIT 8
+
+typedef int SItype __attribute__((mode(SI)));
+typedef unsigned int USItype __attribute__((mode(SI)));
+typedef int DItype __attribute__((mode(DI)));
+typedef int word_type __attribute__((mode(__word__)));
+
+struct DIstruct {
+ SItype low;
+ SItype high;
+};
+
+union DIunion {
+ struct DIstruct s;
+ DItype ll;
+};
+
+DItype __lshrdi3(DItype u, word_type b)
+{
+ union DIunion w;
+ word_type bm;
+ union DIunion uu;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+
+ bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
+ if (bm <= 0) {
+ w.s.high = 0;
+ w.s.low = (USItype) uu.s.high >> -bm;
+ } else {
+ USItype carries = (USItype) uu.s.high << bm;
+ w.s.high = (USItype) uu.s.high >> b;
+ w.s.low = ((USItype) uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
diff --git a/arch/mn10300/lib/memcpy.S b/arch/mn10300/lib/memcpy.S
new file mode 100644
index 00000000000..25fb9bb2604
--- /dev/null
+++ b/arch/mn10300/lib/memcpy.S
@@ -0,0 +1,135 @@
+/* MN10300 Optimised simple memory to memory copy
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+ .section .text
+ .balign L1_CACHE_BYTES
+
+###############################################################################
+#
+# void *memcpy(void *dst, const void *src, size_t n)
+#
+###############################################################################
+ .globl memcpy
+ .type memcpy,@function
+memcpy:
+ movm [d2,d3],(sp)
+ mov d0,(12,sp)
+ mov d1,(16,sp)
+ mov (20,sp),d2 # count
+ mov d0,a0 # dst
+ mov d1,a1 # src
+ mov d0,e3 # the return value
+
+ cmp +0,d2
+ beq memcpy_done # return if zero-length copy
+
+ # see if the three parameters are all four-byte aligned
+ or d0,d1,d3
+ or d2,d3
+ and +3,d3
+ bne memcpy_1 # jump if not
+
+ # we want to transfer as much as we can in chunks of 32 bytes
+ cmp +31,d2
+ bls memcpy_4_remainder # 4-byte aligned remainder
+
+ movm [exreg1],(sp)
+ add -32,d2
+ mov +32,d3
+
+memcpy_4_loop:
+ mov (a1+),d0
+ mov (a1+),d1
+ mov (a1+),e0
+ mov (a1+),e1
+ mov (a1+),e4
+ mov (a1+),e5
+ mov (a1+),e6
+ mov (a1+),e7
+ mov d0,(a0+)
+ mov d1,(a0+)
+ mov e0,(a0+)
+ mov e1,(a0+)
+ mov e4,(a0+)
+ mov e5,(a0+)
+ mov e6,(a0+)
+ mov e7,(a0+)
+
+ sub d3,d2
+ bcc memcpy_4_loop
+
+ movm (sp),[exreg1]
+ add d3,d2
+ beq memcpy_4_no_remainder
+
+memcpy_4_remainder:
+ # cut 4-7 words down to 0-3
+ cmp +16,d2
+ bcs memcpy_4_three_or_fewer_words
+ mov (a1+),d0
+ mov (a1+),d1
+ mov (a1+),e0
+ mov (a1+),e1
+ mov d0,(a0+)
+ mov d1,(a0+)
+ mov e0,(a0+)
+ mov e1,(a0+)
+ add -16,d2
+ beq memcpy_4_no_remainder
+
+ # copy the remaining 1, 2 or 3 words
+memcpy_4_three_or_fewer_words:
+ cmp +8,d2
+ bcs memcpy_4_one_word
+ beq memcpy_4_two_words
+ mov (a1+),d0
+ mov d0,(a0+)
+memcpy_4_two_words:
+ mov (a1+),d0
+ mov d0,(a0+)
+memcpy_4_one_word:
+ mov (a1+),d0
+ mov d0,(a0+)
+
+memcpy_4_no_remainder:
+ # check we copied the correct amount
+ # TODO: REMOVE CHECK
+ sub e3,a0,d2
+ mov (20,sp),d1
+ cmp d2,d1
+ beq memcpy_done
+ break
+ break
+ break
+
+memcpy_done:
+ mov e3,a0
+ ret [d2,d3],8
+
+ # handle misaligned copying
+memcpy_1:
+ add -1,d2
+ mov +1,d3
+ setlb # setlb requires the next insns
+ # to occupy exactly 4 bytes
+
+ sub d3,d2
+ movbu (a1),d0
+ movbu d0,(a0)
+ add_add d3,a1,d3,a0
+ lcc
+
+ mov e3,a0
+ ret [d2,d3],8
+
+memcpy_end:
+ .size memcpy, memcpy_end-memcpy
diff --git a/arch/mn10300/lib/memmove.S b/arch/mn10300/lib/memmove.S
new file mode 100644
index 00000000000..20b07b62b77
--- /dev/null
+++ b/arch/mn10300/lib/memmove.S
@@ -0,0 +1,160 @@
+/* MN10300 Optimised simple memory to memory copy, with support for overlapping
+ * regions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+ .section .text
+ .balign L1_CACHE_BYTES
+
+###############################################################################
+#
+# void *memmove(void *dst, const void *src, size_t n)
+#
+###############################################################################
+ .globl memmove
+ .type memmove,@function
+memmove:
+ # fall back to memcpy if dst < src to work bottom up
+ cmp d1,d0
+ bcs memmove_memcpy
+
+ # work top down
+ movm [d2,d3],(sp)
+ mov d0,(12,sp)
+ mov d1,(16,sp)
+ mov (20,sp),d2 # count
+ add d0,d2,a0 # dst end
+ add d1,d2,a1 # src end
+ mov d0,e3 # the return value
+
+ cmp +0,d2
+ beq memmove_done # return if zero-length copy
+
+ # see if the three parameters are all four-byte aligned
+ or d0,d1,d3
+ or d2,d3
+ and +3,d3
+ bne memmove_1 # jump if not
+
+ # we want to transfer as much as we can in chunks of 32 bytes
+ add -4,a1
+ cmp +31,d2
+ bls memmove_4_remainder # 4-byte aligned remainder
+
+ add -32,d2
+ mov +32,d3
+
+memmove_4_loop:
+ mov (a1),d0
+ sub_sub +4,a1,+4,a0
+ mov d0,(a0)
+ mov (a1),d1
+ sub_sub +4,a1,+4,a0
+ mov d1,(a0)
+
+ mov (a1),d0
+ sub_sub +4,a1,+4,a0
+ mov d0,(a0)
+ mov (a1),d1
+ sub_sub +4,a1,+4,a0
+ mov d1,(a0)
+
+ mov (a1),d0
+ sub_sub +4,a1,+4,a0
+ mov d0,(a0)
+ mov (a1),d1
+ sub_sub +4,a1,+4,a0
+ mov d1,(a0)
+
+ mov (a1),d0
+ sub_sub +4,a1,+4,a0
+ mov d0,(a0)
+ mov (a1),d1
+ sub_sub +4,a1,+4,a0
+ mov d1,(a0)
+
+ sub d3,d2
+ bcc memmove_4_loop
+
+ add d3,d2
+ beq memmove_4_no_remainder
+
+memmove_4_remainder:
+ # cut 4-7 words down to 0-3
+ cmp +16,d2
+ bcs memmove_4_three_or_fewer_words
+ mov (a1),d0
+ sub_sub +4,a1,+4,a0
+ mov d0,(a0)
+ mov (a1),d1
+ sub_sub +4,a1,+4,a0
+ mov d1,(a0)
+ mov (a1),e0
+ sub_sub +4,a1,+4,a0
+ mov e0,(a0)
+ mov (a1),e1
+ sub_sub +4,a1,+4,a0
+ mov e1,(a0)
+ add -16,d2
+ beq memmove_4_no_remainder
+
+ # copy the remaining 1, 2 or 3 words
+memmove_4_three_or_fewer_words:
+ cmp +8,d2
+ bcs memmove_4_one_word
+ beq memmove_4_two_words
+ mov (a1),d0
+ sub_sub +4,a1,+4,a0
+ mov d0,(a0)
+memmove_4_two_words:
+ mov (a1),d0
+ sub_sub +4,a1,+4,a0
+ mov d0,(a0)
+memmove_4_one_word:
+ mov (a1),d0
+ sub_sub +4,a1,+4,a0
+ mov d0,(a0)
+
+memmove_4_no_remainder:
+ # check we copied the correct amount
+ # TODO: REMOVE CHECK
+ sub e3,a0,d2
+ beq memmove_done
+ break
+ break
+ break
+
+memmove_done:
+ mov e3,a0
+ ret [d2,d3],8
+
+ # handle misaligned copying
+memmove_1:
+ add -1,a1
+ add -1,d2
+ mov +1,d3
+ setlb # setlb requires the next insns
+ # to occupy exactly 4 bytes
+
+ sub d3,d2
+ movbu (a1),d0
+ sub_sub d3,a1,d3,a0
+ movbu d0,(a0)
+ lcc
+
+ mov e3,a0
+ ret [d2,d3],8
+
+memmove_memcpy:
+ jmp memcpy
+
+memmove_end:
+ .size memmove, memmove_end-memmove
diff --git a/arch/mn10300/lib/memset.S b/arch/mn10300/lib/memset.S
new file mode 100644
index 00000000000..bc02e39629b
--- /dev/null
+++ b/arch/mn10300/lib/memset.S
@@ -0,0 +1,121 @@
+/* Optimised simple memory fill
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+ .section .text
+ .balign L1_CACHE_BYTES
+
+###############################################################################
+#
+# void *memset(void *dst, int c, size_t n)
+#
+###############################################################################
+ .globl memset
+ .type memset,@function
+memset:
+ movm [d2,d3],(sp)
+ mov d0,(12,sp)
+ mov d1,(16,sp)
+ mov (20,sp),d2 # count
+ mov d0,a0 # dst
+ mov d0,e3 # the return value
+
+ cmp +0,d2
+ beq memset_done # return if zero-length fill
+
+ # see if the region parameters are four-byte aligned
+ or d0,d2,d3
+ and +3,d3
+ bne memset_1 # jump if not
+
+ extbu d1
+ mov_asl d1,d3,8,d1
+ or_asl d1,d3,8,d1
+ or_asl d1,d3,8,d1
+ or d3,d1
+
+ # we want to transfer as much as we can in chunks of 32 bytes
+ cmp +31,d2
+ bls memset_4_remainder # 4-byte aligned remainder
+
+ add -32,d2
+ mov +32,d3
+
+memset_4_loop:
+ mov d1,(a0+)
+ mov d1,(a0+)
+ mov d1,(a0+)
+ mov d1,(a0+)
+ mov d1,(a0+)
+ mov d1,(a0+)
+ mov d1,(a0+)
+ mov d1,(a0+)
+
+ sub d3,d2
+ bcc memset_4_loop
+
+ add d3,d2
+ beq memset_4_no_remainder
+
+memset_4_remainder:
+ # cut 4-7 words down to 0-3
+ cmp +16,d2
+ bcs memset_4_three_or_fewer_words
+ mov d1,(a0+)
+ mov d1,(a0+)
+ mov d1,(a0+)
+ mov d1,(a0+)
+ add -16,d2
+ beq memset_4_no_remainder
+
+ # copy the remaining 1, 2 or 3 words
+memset_4_three_or_fewer_words:
+ cmp +8,d2
+ bcs memset_4_one_word
+ beq memset_4_two_words
+ mov d1,(a0+)
+memset_4_two_words:
+ mov d1,(a0+)
+memset_4_one_word:
+ mov d1,(a0+)
+
+memset_4_no_remainder:
+ # check we set the correct amount
+ # TODO: REMOVE CHECK
+ sub e3,a0,d2
+ mov (20,sp),d1
+ cmp d2,d1
+ beq memset_done
+ break
+ break
+ break
+
+memset_done:
+ mov e3,a0
+ ret [d2,d3],8
+
+ # handle misaligned copying
+memset_1:
+ add -1,d2
+ mov +1,d3
+ setlb # setlb requires the next insns
+ # to occupy exactly 4 bytes
+
+ sub d3,d2
+ movbu d1,(a0)
+ inc a0
+ lcc
+
+ mov e3,a0
+ ret [d2,d3],8
+
+memset_end:
+ .size memset, memset_end-memset
diff --git a/arch/mn10300/lib/negdi2.c b/arch/mn10300/lib/negdi2.c
new file mode 100644
index 00000000000..eae4ecdd5f6
--- /dev/null
+++ b/arch/mn10300/lib/negdi2.c
@@ -0,0 +1,57 @@
+/* More subroutines needed by GCC output code on some machines. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+In addition to the permissions in the GNU General Public Licence, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public Licence restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GNU CC 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 Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* It is incorrect to include config.h here, because this file is being
+ compiled for the target, and hence definitions concerning only the host
+ do not apply. */
+
+#include <linux/types.h>
+
+union DWunion {
+ s64 ll;
+ struct {
+ s32 low;
+ s32 high;
+ } s;
+};
+
+s64 __negdi2(s64 u)
+{
+ union DWunion w;
+ union DWunion uu;
+
+ uu.ll = u;
+
+ w.s.low = -uu.s.low;
+ w.s.high = -uu.s.high - ((u32) w.s.low > 0);
+
+ return w.ll;
+}
diff --git a/arch/mn10300/lib/usercopy.c b/arch/mn10300/lib/usercopy.c
new file mode 100644
index 00000000000..a75b203059c
--- /dev/null
+++ b/arch/mn10300/lib/usercopy.c
@@ -0,0 +1,166 @@
+/* MN10300 Userspace accessor functions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/uaccess.h>
+
+unsigned long
+__generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+ if (access_ok(VERIFY_WRITE, to, n))
+ __copy_user(to, from, n);
+ return n;
+}
+
+unsigned long
+__generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+ if (access_ok(VERIFY_READ, from, n))
+ __copy_user_zeroing(to, from, n);
+ return n;
+}
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+#define __do_strncpy_from_user(dst, src, count, res) \
+do { \
+ int w; \
+ asm volatile( \
+ " mov %1,%0\n" \
+ " cmp 0,%1\n" \
+ " beq 2f\n" \
+ "0:\n" \
+ " movbu (%5),%2\n" \
+ "1:\n" \
+ " movbu %2,(%6)\n" \
+ " inc %5\n" \
+ " inc %6\n" \
+ " cmp 0,%2\n" \
+ " beq 2f\n" \
+ " add -1,%1\n" \
+ " bne 0b\n" \
+ "2:\n" \
+ " sub %1,%0\n" \
+ "3:\n" \
+ " .section .fixup,\"ax\"\n" \
+ "4:\n" \
+ " mov %3,%0\n" \
+ " jmp 3b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .balign 4\n" \
+ " .long 0b,4b\n" \
+ " .long 1b,4b\n" \
+ " .previous" \
+ :"=&r"(res), "=r"(count), "=&r"(w) \
+ :"i"(-EFAULT), "1"(count), "a"(src), "a"(dst) \
+ :"memory"); \
+} while (0)
+
+long
+__strncpy_from_user(char *dst, const char *src, long count)
+{
+ long res;
+ __do_strncpy_from_user(dst, src, count, res);
+ return res;
+}
+
+long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+ long res = -EFAULT;
+ if (access_ok(VERIFY_READ, src, 1))
+ __do_strncpy_from_user(dst, src, count, res);
+ return res;
+}
+
+
+/*
+ * Clear a userspace memory
+ */
+#define __do_clear_user(addr, size) \
+do { \
+ int w; \
+ asm volatile( \
+ " cmp 0,%0\n" \
+ " beq 1f\n" \
+ " clr %1\n" \
+ "0: movbu %1,(%3,%2)\n" \
+ " inc %3\n" \
+ " cmp %0,%3\n" \
+ " bne 0b\n" \
+ "1:\n" \
+ " sub %3,%0\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: jmp 2b\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .balign 4\n" \
+ " .long 0b,3b\n" \
+ ".previous\n" \
+ : "+r"(size), "=&r"(w) \
+ : "a"(addr), "d"(0) \
+ : "memory"); \
+} while (0)
+
+unsigned long
+__clear_user(void *to, unsigned long n)
+{
+ __do_clear_user(to, n);
+ return n;
+}
+
+unsigned long
+clear_user(void *to, unsigned long n)
+{
+ if (access_ok(VERIFY_WRITE, to, n))
+ __do_clear_user(to, n);
+ return n;
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+long strnlen_user(const char *s, long n)
+{
+ unsigned long res, w;
+
+ if (!__addr_ok(s))
+ return 0;
+
+ if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
+ n = current_thread_info()->addr_limit.seg - (u_long)s;
+
+ asm volatile(
+ "0: cmp %4,%0\n"
+ " beq 2f\n"
+ "1: movbu (%0,%3),%1\n"
+ " inc %0\n"
+ " cmp 0,%1\n"
+ " beq 3f\n"
+ " bra 0b\n"
+ "2: clr %0\n"
+ "3:\n"
+ ".section .fixup,\"ax\"\n"
+ "4: jmp 2b\n"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ " .balign 4\n"
+ " .long 1b,4b\n"
+ ".previous\n"
+ :"=d"(res), "=&r"(w)
+ :"0"(0), "a"(s), "r"(n)
+ :"memory");
+ return res;
+}
diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile
new file mode 100644
index 00000000000..28b9d983db0
--- /dev/null
+++ b/arch/mn10300/mm/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the MN10300-specific memory management code
+#
+
+obj-y := \
+ init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \
+ misalignment.o dma-alloc.o
+
+ifneq ($(CONFIG_MN10300_CACHE_DISABLED),y)
+obj-y += cache.o cache-mn10300.o
+ifeq ($(CONFIG_MN10300_CACHE_WBACK),y)
+obj-y += cache-flush-mn10300.o
+endif
+endif
diff --git a/arch/mn10300/mm/cache-flush-mn10300.S b/arch/mn10300/mm/cache-flush-mn10300.S
new file mode 100644
index 00000000000..c8ed1cbac10
--- /dev/null
+++ b/arch/mn10300/mm/cache-flush-mn10300.S
@@ -0,0 +1,192 @@
+/* MN10300 CPU core caching routines
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+
+ .am33_2
+ .globl mn10300_dcache_flush
+ .globl mn10300_dcache_flush_page
+ .globl mn10300_dcache_flush_range
+ .globl mn10300_dcache_flush_range2
+ .globl mn10300_dcache_flush_inv
+ .globl mn10300_dcache_flush_inv_page
+ .globl mn10300_dcache_flush_inv_range
+ .globl mn10300_dcache_flush_inv_range2
+
+###############################################################################
+#
+# void mn10300_dcache_flush(void)
+# Flush the entire data cache back to RAM
+#
+###############################################################################
+ ALIGN
+mn10300_dcache_flush:
+ movhu (CHCTR),d0
+ btst CHCTR_DCEN,d0
+ beq mn10300_dcache_flush_end
+
+ # read the addresses tagged in the cache's tag RAM and attempt to flush
+ # those addresses specifically
+ # - we rely on the hardware to filter out invalid tag entry addresses
+ mov DCACHE_TAG(0,0),a0 # dcache tag RAM access address
+ mov DCACHE_PURGE(0,0),a1 # dcache purge request address
+ mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of entries
+
+mn10300_dcache_flush_loop:
+ mov (a0),d0
+ and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
+ or L1_CACHE_TAG_VALID,d0 # retain valid entries in the
+ # cache
+ mov d0,(a1) # conditional purge
+
+mn10300_dcache_flush_skip:
+ add L1_CACHE_BYTES,a0
+ add L1_CACHE_BYTES,a1
+ add -1,d1
+ bne mn10300_dcache_flush_loop
+
+mn10300_dcache_flush_end:
+ ret [],0
+
+###############################################################################
+#
+# void mn10300_dcache_flush_page(unsigned start)
+# void mn10300_dcache_flush_range(unsigned start, unsigned end)
+# void mn10300_dcache_flush_range2(unsigned start, unsigned size)
+# Flush a range of addresses on a page in the dcache
+#
+###############################################################################
+ ALIGN
+mn10300_dcache_flush_page:
+ mov PAGE_SIZE,d1
+mn10300_dcache_flush_range2:
+ add d0,d1
+mn10300_dcache_flush_range:
+ movm [d2,d3],(sp)
+
+ movhu (CHCTR),d2
+ btst CHCTR_DCEN,d2
+ beq mn10300_dcache_flush_range_end
+
+ # round start addr down
+ and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
+ mov d0,a1
+
+ add L1_CACHE_BYTES,d1 # round end addr up
+ and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
+
+ # write a request to flush all instances of an address from the cache
+ mov DCACHE_PURGE(0,0),a0
+ mov a1,d0
+ and L1_CACHE_TAG_ENTRY,d0
+ add d0,a0 # starting dcache purge control
+ # reg address
+
+ sub a1,d1
+ lsr L1_CACHE_SHIFT,d1 # total number of entries to
+ # examine
+
+ or L1_CACHE_TAG_VALID,a1 # retain valid entries in the
+ # cache
+
+mn10300_dcache_flush_range_loop:
+ mov a1,(L1_CACHE_WAYDISP*0,a0) # conditionally purge this line
+ # all ways
+
+ add L1_CACHE_BYTES,a0
+ add L1_CACHE_BYTES,a1
+ and ~L1_CACHE_WAYDISP,a0 # make sure way stay on way 0
+ add -1,d1
+ bne mn10300_dcache_flush_range_loop
+
+mn10300_dcache_flush_range_end:
+ ret [d2,d3],8
+
+###############################################################################
+#
+# void mn10300_dcache_flush_inv(void)
+# Flush the entire data cache and invalidate all entries
+#
+###############################################################################
+ ALIGN
+mn10300_dcache_flush_inv:
+ movhu (CHCTR),d0
+ btst CHCTR_DCEN,d0
+ beq mn10300_dcache_flush_inv_end
+
+ # hit each line in the dcache with an unconditional purge
+ mov DCACHE_PURGE(0,0),a1 # dcache purge request address
+ mov L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1 # total number of entries
+
+mn10300_dcache_flush_inv_loop:
+ mov (a1),d0 # unconditional purge
+
+ add L1_CACHE_BYTES,a1
+ add -1,d1
+ bne mn10300_dcache_flush_inv_loop
+
+mn10300_dcache_flush_inv_end:
+ ret [],0
+
+###############################################################################
+#
+# void mn10300_dcache_flush_inv_page(unsigned start)
+# void mn10300_dcache_flush_inv_range(unsigned start, unsigned end)
+# void mn10300_dcache_flush_inv_range2(unsigned start, unsigned size)
+# Flush and invalidate a range of addresses on a page in the dcache
+#
+###############################################################################
+ ALIGN
+mn10300_dcache_flush_inv_page:
+ mov PAGE_SIZE,d1
+mn10300_dcache_flush_inv_range2:
+ add d0,d1
+mn10300_dcache_flush_inv_range:
+ movm [d2,d3],(sp)
+ movhu (CHCTR),d2
+ btst CHCTR_DCEN,d2
+ beq mn10300_dcache_flush_inv_range_end
+
+ and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start
+ # addr down
+ mov d0,a1
+
+ add L1_CACHE_BYTES,d1 # round end addr up
+ and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
+
+ # write a request to flush and invalidate all instances of an address
+ # from the cache
+ mov DCACHE_PURGE(0,0),a0
+ mov a1,d0
+ and L1_CACHE_TAG_ENTRY,d0
+ add d0,a0 # starting dcache purge control
+ # reg address
+
+ sub a1,d1
+ lsr L1_CACHE_SHIFT,d1 # total number of entries to
+ # examine
+
+mn10300_dcache_flush_inv_range_loop:
+ mov a1,(L1_CACHE_WAYDISP*0,a0) # conditionally purge this line
+ # in all ways
+
+ add L1_CACHE_BYTES,a0
+ add L1_CACHE_BYTES,a1
+ and ~L1_CACHE_WAYDISP,a0 # make sure way stay on way 0
+ add -1,d1
+ bne mn10300_dcache_flush_inv_range_loop
+
+mn10300_dcache_flush_inv_range_end:
+ ret [d2,d3],8
diff --git a/arch/mn10300/mm/cache-mn10300.S b/arch/mn10300/mm/cache-mn10300.S
new file mode 100644
index 00000000000..e839d0aedd6
--- /dev/null
+++ b/arch/mn10300/mm/cache-mn10300.S
@@ -0,0 +1,289 @@
+/* MN10300 CPU core caching routines
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+
+#define mn10300_dcache_inv_range_intr_interval \
+ +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
+
+#if mn10300_dcache_inv_range_intr_interval > 0xff
+#error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
+#endif
+
+ .am33_2
+
+ .globl mn10300_icache_inv
+ .globl mn10300_dcache_inv
+ .globl mn10300_dcache_inv_range
+ .globl mn10300_dcache_inv_range2
+ .globl mn10300_dcache_inv_page
+
+###############################################################################
+#
+# void mn10300_icache_inv(void)
+# Invalidate the entire icache
+#
+###############################################################################
+ ALIGN
+mn10300_icache_inv:
+ mov CHCTR,a0
+
+ movhu (a0),d0
+ btst CHCTR_ICEN,d0
+ beq mn10300_icache_inv_end
+
+ mov epsw,d1
+ and ~EPSW_IE,epsw
+ nop
+ nop
+
+ # disable the icache
+ and ~CHCTR_ICEN,d0
+ movhu d0,(a0)
+
+ # and wait for it to calm down
+ setlb
+ movhu (a0),d0
+ btst CHCTR_ICBUSY,d0
+ lne
+
+ # invalidate
+ or CHCTR_ICINV,d0
+ movhu d0,(a0)
+
+ # wait for the cache to finish
+ mov CHCTR,a0
+ setlb
+ movhu (a0),d0
+ btst CHCTR_ICBUSY,d0
+ lne
+
+ # and reenable it
+ and ~CHCTR_ICINV,d0
+ or CHCTR_ICEN,d0
+ movhu d0,(a0)
+ movhu (a0),d0
+
+ mov d1,epsw
+
+mn10300_icache_inv_end:
+ ret [],0
+
+###############################################################################
+#
+# void mn10300_dcache_inv(void)
+# Invalidate the entire dcache
+#
+###############################################################################
+ ALIGN
+mn10300_dcache_inv:
+ mov CHCTR,a0
+
+ movhu (a0),d0
+ btst CHCTR_DCEN,d0
+ beq mn10300_dcache_inv_end
+
+ mov epsw,d1
+ and ~EPSW_IE,epsw
+ nop
+ nop
+
+ # disable the dcache
+ and ~CHCTR_DCEN,d0
+ movhu d0,(a0)
+
+ # and wait for it to calm down
+ setlb
+ movhu (a0),d0
+ btst CHCTR_DCBUSY,d0
+ lne
+
+ # invalidate
+ or CHCTR_DCINV,d0
+ movhu d0,(a0)
+
+ # wait for the cache to finish
+ mov CHCTR,a0
+ setlb
+ movhu (a0),d0
+ btst CHCTR_DCBUSY,d0
+ lne
+
+ # and reenable it
+ and ~CHCTR_DCINV,d0
+ or CHCTR_DCEN,d0
+ movhu d0,(a0)
+ movhu (a0),d0
+
+ mov d1,epsw
+
+mn10300_dcache_inv_end:
+ ret [],0
+
+###############################################################################
+#
+# void mn10300_dcache_inv_range(unsigned start, unsigned end)
+# void mn10300_dcache_inv_range2(unsigned start, unsigned size)
+# void mn10300_dcache_inv_page(unsigned start)
+# Invalidate a range of addresses on a page in the dcache
+#
+###############################################################################
+ ALIGN
+mn10300_dcache_inv_page:
+ mov PAGE_SIZE,d1
+mn10300_dcache_inv_range2:
+ add d0,d1
+mn10300_dcache_inv_range:
+ movm [d2,d3,a2],(sp)
+ mov CHCTR,a2
+
+ movhu (a2),d2
+ btst CHCTR_DCEN,d2
+ beq mn10300_dcache_inv_range_end
+
+ and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 # round start
+ # addr down
+ mov d0,a1
+
+ add L1_CACHE_BYTES,d1 # round end addr up
+ and L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
+
+ clr d2 # we're going to clear tag ram
+ # entries
+
+ # read the tags from the tag RAM, and if they indicate a valid dirty
+ # cache line then invalidate that line
+ mov DCACHE_TAG(0,0),a0
+ mov a1,d0
+ and L1_CACHE_TAG_ENTRY,d0
+ add d0,a0 # starting dcache tag RAM
+ # access address
+
+ sub a1,d1
+ lsr L1_CACHE_SHIFT,d1 # total number of entries to
+ # examine
+
+ and ~(L1_CACHE_DISPARITY-1),a1 # determine comparator base
+
+mn10300_dcache_inv_range_outer_loop:
+ # disable interrupts
+ mov epsw,d3
+ and ~EPSW_IE,epsw
+ nop # note that reading CHCTR and
+ # AND'ing D0 occupy two delay
+ # slots after disabling
+ # interrupts
+
+ # disable the dcache
+ movhu (a2),d0
+ and ~CHCTR_DCEN,d0
+ movhu d0,(a2)
+
+ # and wait for it to calm down
+ setlb
+ movhu (a2),d0
+ btst CHCTR_DCBUSY,d0
+ lne
+
+mn10300_dcache_inv_range_loop:
+
+ # process the way 0 slot
+ mov (L1_CACHE_WAYDISP*0,a0),d0 # read the tag in the way 0 slot
+ btst L1_CACHE_TAG_VALID,d0
+ beq mn10300_dcache_inv_range_skip_0 # jump if this cacheline is not
+ # valid
+
+ xor a1,d0
+ lsr 12,d0
+ bne mn10300_dcache_inv_range_skip_0 # jump if not this cacheline
+
+ mov d2,(a0) # kill the tag
+
+mn10300_dcache_inv_range_skip_0:
+
+ # process the way 1 slot
+ mov (L1_CACHE_WAYDISP*1,a0),d0 # read the tag in the way 1 slot
+ btst L1_CACHE_TAG_VALID,d0
+ beq mn10300_dcache_inv_range_skip_1 # jump if this cacheline is not
+ # valid
+
+ xor a1,d0
+ lsr 12,d0
+ bne mn10300_dcache_inv_range_skip_1 # jump if not this cacheline
+
+ mov d2,(a0) # kill the tag
+
+mn10300_dcache_inv_range_skip_1:
+
+ # process the way 2 slot
+ mov (L1_CACHE_WAYDISP*2,a0),d0 # read the tag in the way 2 slot
+ btst L1_CACHE_TAG_VALID,d0
+ beq mn10300_dcache_inv_range_skip_2 # jump if this cacheline is not
+ # valid
+
+ xor a1,d0
+ lsr 12,d0
+ bne mn10300_dcache_inv_range_skip_2 # jump if not this cacheline
+
+ mov d2,(a0) # kill the tag
+
+mn10300_dcache_inv_range_skip_2:
+
+ # process the way 3 slot
+ mov (L1_CACHE_WAYDISP*3,a0),d0 # read the tag in the way 3 slot
+ btst L1_CACHE_TAG_VALID,d0
+ beq mn10300_dcache_inv_range_skip_3 # jump if this cacheline is not
+ # valid
+
+ xor a1,d0
+ lsr 12,d0
+ bne mn10300_dcache_inv_range_skip_3 # jump if not this cacheline
+
+ mov d2,(a0) # kill the tag
+
+mn10300_dcache_inv_range_skip_3:
+
+ # approx every N steps we re-enable the cache and see if there are any
+ # interrupts to be processed
+ # we also break out if we've reached the end of the loop
+ # (the bottom nibble of the count is zero in both cases)
+ add L1_CACHE_BYTES,a0
+ add L1_CACHE_BYTES,a1
+ add -1,d1
+ btst mn10300_dcache_inv_range_intr_interval,d1
+ bne mn10300_dcache_inv_range_loop
+
+ # wait for the cache to finish what it's doing
+ setlb
+ movhu (a2),d0
+ btst CHCTR_DCBUSY,d0
+ lne
+
+ # and reenable it
+ or CHCTR_DCEN,d0
+ movhu d0,(a2)
+ movhu (a2),d0
+
+ # re-enable interrupts
+ # - we don't bother with delay NOPs as we'll have enough instructions
+ # before we disable interrupts again to give the interrupts a chance
+ # to happen
+ mov d3,epsw
+
+ # go around again if the counter hasn't yet reached zero
+ add 0,d1
+ bne mn10300_dcache_inv_range_outer_loop
+
+mn10300_dcache_inv_range_end:
+ ret [d2,d3,a2],12
diff --git a/arch/mn10300/mm/cache.c b/arch/mn10300/mm/cache.c
new file mode 100644
index 00000000000..1b76719ec1c
--- /dev/null
+++ b/arch/mn10300/mm/cache.c
@@ -0,0 +1,121 @@
+/* MN10300 Cache flushing routines
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/threads.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+EXPORT_SYMBOL(mn10300_icache_inv);
+EXPORT_SYMBOL(mn10300_dcache_inv);
+EXPORT_SYMBOL(mn10300_dcache_inv_range);
+EXPORT_SYMBOL(mn10300_dcache_inv_range2);
+EXPORT_SYMBOL(mn10300_dcache_inv_page);
+
+#ifdef CONFIG_MN10300_CACHE_WBACK
+EXPORT_SYMBOL(mn10300_dcache_flush);
+EXPORT_SYMBOL(mn10300_dcache_flush_inv);
+EXPORT_SYMBOL(mn10300_dcache_flush_inv_range);
+EXPORT_SYMBOL(mn10300_dcache_flush_inv_range2);
+EXPORT_SYMBOL(mn10300_dcache_flush_inv_page);
+EXPORT_SYMBOL(mn10300_dcache_flush_range);
+EXPORT_SYMBOL(mn10300_dcache_flush_range2);
+EXPORT_SYMBOL(mn10300_dcache_flush_page);
+#endif
+
+/*
+ * write a page back from the dcache and invalidate the icache so that we can
+ * run code from it that we've just written into it
+ */
+void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+ mn10300_dcache_flush_page(page_to_phys(page));
+ mn10300_icache_inv();
+}
+EXPORT_SYMBOL(flush_icache_page);
+
+/*
+ * write some code we've just written back from the dcache and invalidate the
+ * icache so that we can run that code
+ */
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+#ifdef CONFIG_MN10300_CACHE_WBACK
+ unsigned long addr, size, off;
+ struct page *page;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *ppte, pte;
+
+ for (; start < end; start += size) {
+ /* work out how much of the page to flush */
+ off = start & (PAGE_SIZE - 1);
+
+ size = end - start;
+ if (size > PAGE_SIZE - off)
+ size = PAGE_SIZE - off;
+
+ /* get the physical address the page is mapped to from the page
+ * tables */
+ pgd = pgd_offset(current->mm, start);
+ if (!pgd || !pgd_val(*pgd))
+ continue;
+
+ pud = pud_offset(pgd, start);
+ if (!pud || !pud_val(*pud))
+ continue;
+
+ pmd = pmd_offset(pud, start);
+ if (!pmd || !pmd_val(*pmd))
+ continue;
+
+ ppte = pte_offset_map(pmd, start);
+ if (!ppte)
+ continue;
+ pte = *ppte;
+ pte_unmap(ppte);
+
+ if (pte_none(pte))
+ continue;
+
+ page = pte_page(pte);
+ if (!page)
+ continue;
+
+ addr = page_to_phys(page);
+
+ /* flush the dcache and invalidate the icache coverage on that
+ * region */
+ mn10300_dcache_flush_range2(addr + off, size);
+ }
+#endif
+
+ mn10300_icache_inv();
+}
+EXPORT_SYMBOL(flush_icache_range);
+
+/*
+ * allow userspace to flush the instruction cache
+ */
+asmlinkage long sys_cacheflush(unsigned long start, unsigned long end)
+{
+ if (end < start)
+ return -EINVAL;
+
+ flush_icache_range(start, end);
+ return 0;
+}
diff --git a/arch/mn10300/mm/dma-alloc.c b/arch/mn10300/mm/dma-alloc.c
new file mode 100644
index 00000000000..f3649d8f50e
--- /dev/null
+++ b/arch/mn10300/mm/dma-alloc.c
@@ -0,0 +1,56 @@
+/* MN10300 Dynamic DMA mapping support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * Derived from: arch/i386/kernel/pci-dma.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, int gfp)
+{
+ unsigned long addr;
+ void *ret;
+
+ /* ignore region specifiers */
+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+ if (dev == NULL || dev->coherent_dma_mask < 0xffffffff)
+ gfp |= GFP_DMA;
+
+ addr = __get_free_pages(gfp, get_order(size));
+ if (!addr)
+ return NULL;
+
+ /* map the coherent memory through the uncached memory window */
+ ret = (void *) (addr | 0x20000000);
+
+ /* fill the memory with obvious rubbish */
+ memset((void *) addr, 0xfb, size);
+
+ /* write back and evict all cache lines covering this region */
+ mn10300_dcache_flush_inv_range2(virt_to_phys((void *) addr), PAGE_SIZE);
+
+ *dma_handle = virt_to_bus((void *) addr);
+ return ret;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle)
+{
+ unsigned long addr = (unsigned long) vaddr & ~0x20000000;
+
+ free_pages(addr, get_order(size));
+}
+EXPORT_SYMBOL(dma_free_coherent);
diff --git a/arch/mn10300/mm/extable.c b/arch/mn10300/mm/extable.c
new file mode 100644
index 00000000000..25e5485ab87
--- /dev/null
+++ b/arch/mn10300/mm/extable.c
@@ -0,0 +1,26 @@
+/* MN10300 In-kernel exception handling
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+ const struct exception_table_entry *fixup;
+
+ fixup = search_exception_tables(regs->pc);
+ if (fixup) {
+ regs->pc = fixup->fixup;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c
new file mode 100644
index 00000000000..78f092ca031
--- /dev/null
+++ b/arch/mn10300/mm/fault.c
@@ -0,0 +1,405 @@
+/* MN10300 MMU Fault handler
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/vt_kern.h> /* For unblank_screen() */
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/hardirq.h>
+#include <asm/gdb-stub.h>
+#include <asm/cpu-regs.h>
+
+/*
+ * Unlock any spinlocks which will prevent us from getting the
+ * message out
+ */
+void bust_spinlocks(int yes)
+{
+ if (yes) {
+ oops_in_progress = 1;
+#ifdef CONFIG_SMP
+ /* Many serial drivers do __global_cli() */
+ global_irq_lock = 0;
+#endif
+ } else {
+ int loglevel_save = console_loglevel;
+#ifdef CONFIG_VT
+ unblank_screen();
+#endif
+ oops_in_progress = 0;
+ /*
+ * OK, the message is on the console. Now we call printk()
+ * without oops_in_progress set so that printk will give klogd
+ * a poke. Hold onto your hats...
+ */
+ console_loglevel = 15; /* NMI oopser may have shut the console
+ * up */
+ printk(" ");
+ console_loglevel = loglevel_save;
+ }
+}
+
+void do_BUG(const char *file, int line)
+{
+ bust_spinlocks(1);
+ printk(KERN_EMERG "------------[ cut here ]------------\n");
+ printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
+}
+
+#if 0
+static void print_pagetable_entries(pgd_t *pgdir, unsigned long address)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ pgd = pgdir + __pgd_offset(address);
+ printk(KERN_DEBUG "pgd entry %p: %016Lx\n",
+ pgd, (long long) pgd_val(*pgd));
+
+ if (!pgd_present(*pgd)) {
+ printk(KERN_DEBUG "... pgd not present!\n");
+ return;
+ }
+ pmd = pmd_offset(pgd, address);
+ printk(KERN_DEBUG "pmd entry %p: %016Lx\n",
+ pmd, (long long)pmd_val(*pmd));
+
+ if (!pmd_present(*pmd)) {
+ printk(KERN_DEBUG "... pmd not present!\n");
+ return;
+ }
+ pte = pte_offset(pmd, address);
+ printk(KERN_DEBUG "pte entry %p: %016Lx\n",
+ pte, (long long) pte_val(*pte));
+
+ if (!pte_present(*pte))
+ printk(KERN_DEBUG "... pte not present!\n");
+}
+#endif
+
+asmlinkage void monitor_signal(struct pt_regs *);
+
+/*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * fault_code:
+ * - LSW: either MMUFCR_IFC or MMUFCR_DFC as appropriate
+ * - MSW: 0 if data access, 1 if instruction access
+ * - bit 0: TLB miss flag
+ * - bit 1: initial write
+ * - bit 2: page invalid
+ * - bit 3: protection violation
+ * - bit 4: accessor (0=user 1=kernel)
+ * - bit 5: 0=read 1=write
+ * - bit 6-8: page protection spec
+ * - bit 9: illegal address
+ * - bit 16: 0=data 1=ins
+ *
+ */
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
+ unsigned long address)
+{
+ struct vm_area_struct *vma;
+ struct task_struct *tsk;
+ struct mm_struct *mm;
+ unsigned long page;
+ siginfo_t info;
+ int write, fault;
+
+#ifdef CONFIG_GDBSTUB
+ /* handle GDB stub causing a fault */
+ if (gdbstub_busy) {
+ gdbstub_exception(regs, TBR & TBR_INT_CODE);
+ return;
+ }
+#endif
+
+#if 0
+ printk(KERN_DEBUG "--- do_page_fault(%p,%s:%04lx,%08lx)\n",
+ regs,
+ fault_code & 0x10000 ? "ins" : "data",
+ fault_code & 0xffff, address);
+#endif
+
+ tsk = current;
+
+ /*
+ * We fault-in kernel-space virtual memory on-demand. The
+ * 'reference' page table is init_mm.pgd.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may
+ * be in an interrupt or a critical region, and should
+ * only copy the information from the master page table,
+ * nothing more.
+ *
+ * This verifies that the fault happens in kernel space
+ * and that the fault was a page not present (invalid) error
+ */
+ if (address >= VMALLOC_START && address < VMALLOC_END &&
+ (fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_SR &&
+ (fault_code & MMUFCR_xFC_PGINVAL) == MMUFCR_xFC_PGINVAL
+ )
+ goto vmalloc_fault;
+
+ mm = tsk->mm;
+ info.si_code = SEGV_MAPERR;
+
+ /*
+ * If we're in an interrupt or have no user
+ * context, we must not take the fault..
+ */
+ if (in_interrupt() || !mm)
+ goto no_context;
+
+ down_read(&mm->mmap_sem);
+
+ vma = find_vma(mm, address);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= address)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+
+ if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) {
+ /* accessing the stack below the stack pointer is always a
+ * bug */
+ if ((address & PAGE_MASK) + 2 * PAGE_SIZE < regs->sp) {
+#if 0
+ printk(KERN_WARNING
+ "[%d] ### Access below stack @%lx (sp=%lx)\n",
+ current->pid, address, regs->sp);
+ printk(KERN_WARNING
+ "vma [%08x - %08x]\n",
+ vma->vm_start, vma->vm_end);
+ show_registers(regs);
+ printk(KERN_WARNING
+ "[%d] ### Code: [%08lx]"
+ " %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ current->pid,
+ regs->pc,
+ ((u8 *) regs->pc)[0],
+ ((u8 *) regs->pc)[1],
+ ((u8 *) regs->pc)[2],
+ ((u8 *) regs->pc)[3],
+ ((u8 *) regs->pc)[4],
+ ((u8 *) regs->pc)[5],
+ ((u8 *) regs->pc)[6],
+ ((u8 *) regs->pc)[7]
+ );
+#endif
+ goto bad_area;
+ }
+ }
+
+ if (expand_stack(vma, address))
+ goto bad_area;
+
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+ info.si_code = SEGV_ACCERR;
+ write = 0;
+ switch (fault_code & (MMUFCR_xFC_PGINVAL|MMUFCR_xFC_TYPE)) {
+ default: /* 3: write, present */
+ case MMUFCR_xFC_TYPE_WRITE:
+#ifdef TEST_VERIFY_AREA
+ if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_SR)
+ printk(KERN_DEBUG "WP fault at %08lx\n", regs->pc);
+#endif
+ /* write to absent page */
+ case MMUFCR_xFC_PGINVAL | MMUFCR_xFC_TYPE_WRITE:
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ write++;
+ break;
+
+ /* read from protected page */
+ case MMUFCR_xFC_TYPE_READ:
+ goto bad_area;
+
+ /* read from absent page present */
+ case MMUFCR_xFC_PGINVAL | MMUFCR_xFC_TYPE_READ:
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto bad_area;
+ break;
+ }
+
+ /*
+ * If for any reason at all we couldn't handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+ * the fault.
+ */
+ fault = handle_mm_fault(mm, vma, address, write);
+ if (unlikely(fault & VM_FAULT_ERROR)) {
+ if (fault & VM_FAULT_OOM)
+ goto out_of_memory;
+ else if (fault & VM_FAULT_SIGBUS)
+ goto do_sigbus;
+ BUG();
+ }
+ if (fault & VM_FAULT_MAJOR)
+ current->maj_flt++;
+ else
+ current->min_flt++;
+
+ up_read(&mm->mmap_sem);
+ return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+ up_read(&mm->mmap_sem);
+ monitor_signal(regs);
+
+ /* User mode accesses just cause a SIGSEGV */
+ if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) {
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* info.si_code has been set above */
+ info.si_addr = (void *)address;
+ force_sig_info(SIGSEGV, &info, tsk);
+ return;
+ }
+
+no_context:
+ monitor_signal(regs);
+ /* Are we prepared to handle this kernel fault? */
+ if (fixup_exception(regs))
+ return;
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+
+ bust_spinlocks(1);
+
+ if (address < PAGE_SIZE)
+ printk(KERN_ALERT
+ "Unable to handle kernel NULL pointer dereference");
+ else
+ printk(KERN_ALERT
+ "Unable to handle kernel paging request");
+ printk(" at virtual address %08lx\n", address);
+ printk(" printing pc:\n");
+ printk(KERN_ALERT "%08lx\n", regs->pc);
+
+#ifdef CONFIG_GDBSTUB
+ gdbstub_intercept(
+ regs, fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR);
+#endif
+
+ page = PTBR;
+ page = ((unsigned long *) __va(page))[address >> 22];
+ printk(KERN_ALERT "*pde = %08lx\n", page);
+ if (page & 1) {
+ page &= PAGE_MASK;
+ address &= 0x003ff000;
+ page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
+ printk(KERN_ALERT "*pte = %08lx\n", page);
+ }
+
+ die("Oops", regs, fault_code);
+ do_exit(SIGKILL);
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+ up_read(&mm->mmap_sem);
+ monitor_signal(regs);
+ printk(KERN_ALERT "VM: killing process %s\n", tsk->comm);
+ if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
+ do_exit(SIGKILL);
+ goto no_context;
+
+do_sigbus:
+ up_read(&mm->mmap_sem);
+ monitor_signal(regs);
+
+ /*
+ * Send a sigbus, regardless of whether we were in kernel
+ * or user mode.
+ */
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *)address;
+ force_sig_info(SIGBUS, &info, tsk);
+
+ /* Kernel mode? Handle exceptions or die */
+ if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_SR)
+ goto no_context;
+ return;
+
+vmalloc_fault:
+ {
+ /*
+ * Synchronize this task's top level page-table
+ * with the 'reference' page table.
+ *
+ * Do _not_ use "tsk" here. We might be inside
+ * an interrupt in the middle of a task switch..
+ */
+ int index = pgd_index(address);
+ pgd_t *pgd, *pgd_k;
+ pud_t *pud, *pud_k;
+ pmd_t *pmd, *pmd_k;
+ pte_t *pte_k;
+
+ pgd_k = init_mm.pgd + index;
+
+ if (!pgd_present(*pgd_k))
+ goto no_context;
+
+ pud_k = pud_offset(pgd_k, address);
+ if (!pud_present(*pud_k))
+ goto no_context;
+
+ pmd_k = pmd_offset(pud_k, address);
+ if (!pmd_present(*pmd_k))
+ goto no_context;
+
+ pgd = (pgd_t *) PTBR + index;
+ pud = pud_offset(pgd, address);
+ pmd = pmd_offset(pud, address);
+ set_pmd(pmd, *pmd_k);
+
+ pte_k = pte_offset_kernel(pmd_k, address);
+ if (!pte_present(*pte_k))
+ goto no_context;
+ return;
+ }
+}
diff --git a/arch/mn10300/mm/init.c b/arch/mn10300/mm/init.c
new file mode 100644
index 00000000000..8c5d88c7b90
--- /dev/null
+++ b/arch/mn10300/mm/init.c
@@ -0,0 +1,160 @@
+/* MN10300 Memory management initialisation
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
+
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/dma.h>
+#include <asm/tlb.h>
+#include <asm/sections.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+unsigned long highstart_pfn, highend_pfn;
+
+/*
+ * set up paging
+ */
+void __init paging_init(void)
+{
+ unsigned long zones_size[MAX_NR_ZONES] = {0,};
+ pte_t *ppte;
+ int loop;
+
+ /* main kernel space -> RAM mapping is handled as 1:1 transparent by
+ * the MMU */
+ memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
+ memset(kernel_vmalloc_ptes, 0, sizeof(kernel_vmalloc_ptes));
+
+ /* load the VMALLOC area PTE table addresses into the kernel PGD */
+ ppte = kernel_vmalloc_ptes;
+ for (loop = VMALLOC_START / (PAGE_SIZE * PTRS_PER_PTE);
+ loop < VMALLOC_END / (PAGE_SIZE * PTRS_PER_PTE);
+ loop++
+ ) {
+ set_pgd(swapper_pg_dir + loop, __pgd(__pa(ppte) | _PAGE_TABLE));
+ ppte += PAGE_SIZE / sizeof(pte_t);
+ }
+
+ /* declare the sizes of the RAM zones (only use the normal zone) */
+ zones_size[ZONE_NORMAL] =
+ (contig_page_data.bdata->node_low_pfn) -
+ (contig_page_data.bdata->node_boot_start >> PAGE_SHIFT);
+
+ /* pass the memory from the bootmem allocator to the main allocator */
+ free_area_init(zones_size);
+
+ __flush_tlb_all();
+}
+
+/*
+ * transfer all the memory from the bootmem allocator to the runtime allocator
+ */
+void __init mem_init(void)
+{
+ int codesize, reservedpages, datasize, initsize;
+ int tmp;
+
+ if (!mem_map)
+ BUG();
+
+#define START_PFN (contig_page_data.bdata->node_boot_start >> PAGE_SHIFT)
+#define MAX_LOW_PFN (contig_page_data.bdata->node_low_pfn)
+
+ max_mapnr = num_physpages = MAX_LOW_PFN - START_PFN;
+ high_memory = (void *) __va(MAX_LOW_PFN * PAGE_SIZE);
+
+ /* clear the zero-page */
+ memset(empty_zero_page, 0, PAGE_SIZE);
+
+ /* this will put all low memory onto the freelists */
+ totalram_pages += free_all_bootmem();
+
+ reservedpages = 0;
+ for (tmp = 0; tmp < num_physpages; tmp++)
+ if (PageReserved(&mem_map[tmp]))
+ reservedpages++;
+
+ codesize = (unsigned long) &_etext - (unsigned long) &_stext;
+ datasize = (unsigned long) &_edata - (unsigned long) &_etext;
+ initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+ printk(KERN_INFO
+ "Memory: %luk/%luk available"
+ " (%dk kernel code, %dk reserved, %dk data, %dk init,"
+ " %ldk highmem)\n",
+ (unsigned long) nr_free_pages() << (PAGE_SHIFT - 10),
+ max_mapnr << (PAGE_SHIFT - 10),
+ codesize >> 10,
+ reservedpages << (PAGE_SHIFT - 10),
+ datasize >> 10,
+ initsize >> 10,
+ (unsigned long) (totalhigh_pages << (PAGE_SHIFT - 10))
+ );
+}
+
+/*
+ *
+ */
+void free_init_pages(char *what, unsigned long begin, unsigned long end)
+{
+ unsigned long addr;
+
+ for (addr = begin; addr < end; addr += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ init_page_count(virt_to_page(addr));
+ memset((void *) addr, 0xcc, PAGE_SIZE);
+ free_page(addr);
+ totalram_pages++;
+ }
+ printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+}
+
+/*
+ * recycle memory containing stuff only required for initialisation
+ */
+void free_initmem(void)
+{
+ free_init_pages("unused kernel memory",
+ (unsigned long) &__init_begin,
+ (unsigned long) &__init_end);
+}
+
+/*
+ * dispose of the memory on which the initial ramdisk resided
+ */
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+ free_init_pages("initrd memory", start, end);
+}
+#endif
diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c
new file mode 100644
index 00000000000..32aa89dc384
--- /dev/null
+++ b/arch/mn10300/mm/misalignment.c
@@ -0,0 +1,661 @@
+/* MN10300 Misalignment fixup handler
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/smp.h>
+#include <asm/pgalloc.h>
+#include <asm/cpu-regs.h>
+#include <asm/busctl-regs.h>
+#include <asm/fpu.h>
+#include <asm/gdb-stub.h>
+#include <asm/asm-offsets.h>
+
+#if 0
+#define kdebug(FMT, ...) printk(KERN_DEBUG FMT, ##__VA_ARGS__)
+#else
+#define kdebug(FMT, ...) do {} while (0)
+#endif
+
+static int misalignment_addr(unsigned long *registers, unsigned params,
+ unsigned opcode, unsigned disp,
+ void **_address, unsigned long **_postinc);
+
+static int misalignment_reg(unsigned long *registers, unsigned params,
+ unsigned opcode, unsigned disp,
+ unsigned long **_register);
+
+static inline unsigned int_log2(unsigned x)
+{
+ unsigned y;
+ asm("bsch %1,%0" : "=r"(y) : "r"(x), "0"(0));
+ return y;
+}
+#define log2(x) int_log2(x)
+
+static const unsigned Dreg_index[] = {
+ REG_D0 >> 2, REG_D1 >> 2, REG_D2 >> 2, REG_D3 >> 2
+};
+
+static const unsigned Areg_index[] = {
+ REG_A0 >> 2, REG_A1 >> 2, REG_A2 >> 2, REG_A3 >> 2
+};
+
+static const unsigned Rreg_index[] = {
+ REG_E0 >> 2, REG_E1 >> 2, REG_E2 >> 2, REG_E3 >> 2,
+ REG_E4 >> 2, REG_E5 >> 2, REG_E6 >> 2, REG_E7 >> 2,
+ REG_A0 >> 2, REG_A1 >> 2, REG_A2 >> 2, REG_A3 >> 2,
+ REG_D0 >> 2, REG_D1 >> 2, REG_D2 >> 2, REG_D3 >> 2
+};
+
+enum format_id {
+ FMT_S0,
+ FMT_S1,
+ FMT_S2,
+ FMT_S4,
+ FMT_D0,
+ FMT_D1,
+ FMT_D2,
+ FMT_D4,
+ FMT_D6,
+ FMT_D7,
+ FMT_D8,
+ FMT_D9,
+};
+
+struct {
+ u_int8_t opsz, dispsz;
+} format_tbl[16] = {
+ [FMT_S0] = { 8, 0 },
+ [FMT_S1] = { 8, 8 },
+ [FMT_S2] = { 8, 16 },
+ [FMT_S4] = { 8, 32 },
+ [FMT_D0] = { 16, 0 },
+ [FMT_D1] = { 16, 8 },
+ [FMT_D2] = { 16, 16 },
+ [FMT_D4] = { 16, 32 },
+ [FMT_D6] = { 24, 0 },
+ [FMT_D7] = { 24, 8 },
+ [FMT_D8] = { 24, 24 },
+ [FMT_D9] = { 24, 32 },
+};
+
+enum value_id {
+ DM0, /* data reg in opcode in bits 0-1 */
+ DM1, /* data reg in opcode in bits 2-3 */
+ DM2, /* data reg in opcode in bits 4-5 */
+ AM0, /* addr reg in opcode in bits 0-1 */
+ AM1, /* addr reg in opcode in bits 2-3 */
+ AM2, /* addr reg in opcode in bits 4-5 */
+ RM0, /* reg in opcode in bits 0-3 */
+ RM1, /* reg in opcode in bits 2-5 */
+ RM2, /* reg in opcode in bits 4-7 */
+ RM4, /* reg in opcode in bits 8-11 */
+ RM6, /* reg in opcode in bits 12-15 */
+
+ RD0, /* reg in displacement in bits 0-3 */
+ RD2, /* reg in displacement in bits 4-7 */
+
+ SP, /* stack pointer */
+
+ SD8, /* 8-bit signed displacement */
+ SD16, /* 16-bit signed displacement */
+ SD24, /* 24-bit signed displacement */
+ SIMM4_2, /* 4-bit signed displacement in opcode bits 4-7 */
+ SIMM8, /* 8-bit signed immediate */
+ IMM24, /* 24-bit unsigned immediate */
+ IMM32, /* 32-bit unsigned immediate */
+ IMM32_HIGH8, /* 32-bit unsigned immediate, high 8-bits in opcode */
+
+ DN0 = DM0,
+ DN1 = DM1,
+ DN2 = DM2,
+ AN0 = AM0,
+ AN1 = AM1,
+ AN2 = AM2,
+ RN0 = RM0,
+ RN1 = RM1,
+ RN2 = RM2,
+ RN4 = RM4,
+ RN6 = RM6,
+ DI = DM1,
+ RI = RM2,
+
+};
+
+struct mn10300_opcode {
+ const char *name;
+ u_int32_t opcode;
+ u_int32_t opmask;
+ unsigned exclusion;
+
+ enum format_id format;
+
+ unsigned cpu_mask;
+#define AM33 330
+
+ unsigned params[2];
+#define MEM(ADDR) (0x80000000 | (ADDR))
+#define MEM2(ADDR1, ADDR2) (0x80000000 | (ADDR1) << 8 | (ADDR2))
+#define MEMINC(ADDR) (0x81000000 | (ADDR))
+#define MEMINC2(ADDR, INC) (0x81000000 | (ADDR) << 8 | (INC))
+};
+
+/* LIBOPCODES EXCERPT
+ Assemble Matsushita MN10300 instructions.
+ Copyright 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public Licence as published by
+ the Free Software Foundation; either version 2 of the Licence, 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 Licence for more details.
+
+ You should have received a copy of the GNU General Public Licence
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+static const struct mn10300_opcode mn10300_opcodes[] = {
+{ "mov", 0x60, 0xf0, 0, FMT_S0, 0, {DM1, MEM(AN0)}},
+{ "mov", 0x70, 0xf0, 0, FMT_S0, 0, {MEM(AM0), DN1}},
+{ "mov", 0xf000, 0xfff0, 0, FMT_D0, 0, {MEM(AM0), AN1}},
+{ "mov", 0xf010, 0xfff0, 0, FMT_D0, 0, {AM1, MEM(AN0)}},
+{ "mov", 0xf300, 0xffc0, 0, FMT_D0, 0, {MEM2(DI, AM0), DN2}},
+{ "mov", 0xf340, 0xffc0, 0, FMT_D0, 0, {DM2, MEM2(DI, AN0)}},
+{ "mov", 0xf380, 0xffc0, 0, FMT_D0, 0, {MEM2(DI, AM0), AN2}},
+{ "mov", 0xf3c0, 0xffc0, 0, FMT_D0, 0, {AM2, MEM2(DI, AN0)}},
+{ "mov", 0xf80000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8, AM0), DN1}},
+{ "mov", 0xf81000, 0xfff000, 0, FMT_D1, 0, {DM1, MEM2(SD8, AN0)}},
+{ "mov", 0xf82000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8,AM0), AN1}},
+{ "mov", 0xf83000, 0xfff000, 0, FMT_D1, 0, {AM1, MEM2(SD8, AN0)}},
+{ "mov", 0xf8f000, 0xfffc00, 0, FMT_D1, AM33, {MEM2(SD8, AM0), SP}},
+{ "mov", 0xf8f400, 0xfffc00, 0, FMT_D1, AM33, {SP, MEM2(SD8, AN0)}},
+{ "mov", 0xf90a00, 0xffff00, 0, FMT_D6, AM33, {MEM(RM0), RN2}},
+{ "mov", 0xf91a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEM(RN0)}},
+{ "mov", 0xf96a00, 0xffff00, 0x12, FMT_D6, AM33, {MEMINC(RM0), RN2}},
+{ "mov", 0xf97a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEMINC(RN0)}},
+{ "mov", 0xfa000000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), DN1}},
+{ "mov", 0xfa100000, 0xfff00000, 0, FMT_D2, 0, {DM1, MEM2(SD16, AN0)}},
+{ "mov", 0xfa200000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), AN1}},
+{ "mov", 0xfa300000, 0xfff00000, 0, FMT_D2, 0, {AM1, MEM2(SD16, AN0)}},
+{ "mov", 0xfb0a0000, 0xffff0000, 0, FMT_D7, AM33, {MEM2(SD8, RM0), RN2}},
+{ "mov", 0xfb1a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEM2(SD8, RN0)}},
+{ "mov", 0xfb6a0000, 0xffff0000, 0x22, FMT_D7, AM33, {MEMINC2 (RM0, SIMM8), RN2}},
+{ "mov", 0xfb7a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEMINC2 (RN0, SIMM8)}},
+{ "mov", 0xfb8e0000, 0xffff000f, 0, FMT_D7, AM33, {MEM2(RI, RM0), RD2}},
+{ "mov", 0xfb9e0000, 0xffff000f, 0, FMT_D7, AM33, {RD2, MEM2(RI, RN0)}},
+{ "mov", 0xfc000000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), DN1}},
+{ "mov", 0xfc100000, 0xfff00000, 0, FMT_D4, 0, {DM1, MEM2(IMM32,AN0)}},
+{ "mov", 0xfc200000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), AN1}},
+{ "mov", 0xfc300000, 0xfff00000, 0, FMT_D4, 0, {AM1, MEM2(IMM32,AN0)}},
+{ "mov", 0xfd0a0000, 0xffff0000, 0, FMT_D8, AM33, {MEM2(SD24, RM0), RN2}},
+{ "mov", 0xfd1a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEM2(SD24, RN0)}},
+{ "mov", 0xfd6a0000, 0xffff0000, 0x22, FMT_D8, AM33, {MEMINC2 (RM0, IMM24), RN2}},
+{ "mov", 0xfd7a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEMINC2 (RN0, IMM24)}},
+{ "mov", 0xfe0a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}},
+{ "mov", 0xfe1a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}},
+{ "mov", 0xfe6a0000, 0xffff0000, 0x22, FMT_D9, AM33, {MEMINC2 (RM0, IMM32_HIGH8), RN2}},
+{ "mov", 0xfe7a0000, 0xffff0000, 0, FMT_D9, AM33, {RN2, MEMINC2 (RM0, IMM32_HIGH8)}},
+
+{ "movhu", 0xf060, 0xfff0, 0, FMT_D0, 0, {MEM(AM0), DN1}},
+{ "movhu", 0xf070, 0xfff0, 0, FMT_D0, 0, {DM1, MEM(AN0)}},
+{ "movhu", 0xf480, 0xffc0, 0, FMT_D0, 0, {MEM2(DI, AM0), DN2}},
+{ "movhu", 0xf4c0, 0xffc0, 0, FMT_D0, 0, {DM2, MEM2(DI, AN0)}},
+{ "movhu", 0xf86000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8, AM0), DN1}},
+{ "movhu", 0xf87000, 0xfff000, 0, FMT_D1, 0, {DM1, MEM2(SD8, AN0)}},
+{ "movhu", 0xf94a00, 0xffff00, 0, FMT_D6, AM33, {MEM(RM0), RN2}},
+{ "movhu", 0xf95a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEM(RN0)}},
+{ "movhu", 0xf9ea00, 0xffff00, 0x12, FMT_D6, AM33, {MEMINC(RM0), RN2}},
+{ "movhu", 0xf9fa00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEMINC(RN0)}},
+{ "movhu", 0xfa600000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), DN1}},
+{ "movhu", 0xfa700000, 0xfff00000, 0, FMT_D2, 0, {DM1, MEM2(SD16, AN0)}},
+{ "movhu", 0xfb4a0000, 0xffff0000, 0, FMT_D7, AM33, {MEM2(SD8, RM0), RN2}},
+{ "movhu", 0xfb5a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEM2(SD8, RN0)}},
+{ "movhu", 0xfbce0000, 0xffff000f, 0, FMT_D7, AM33, {MEM2(RI, RM0), RD2}},
+{ "movhu", 0xfbde0000, 0xffff000f, 0, FMT_D7, AM33, {RD2, MEM2(RI, RN0)}},
+{ "movhu", 0xfbea0000, 0xffff0000, 0x22, FMT_D7, AM33, {MEMINC2 (RM0, SIMM8), RN2}},
+{ "movhu", 0xfbfa0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEMINC2 (RN0, SIMM8)}},
+{ "movhu", 0xfc600000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), DN1}},
+{ "movhu", 0xfc700000, 0xfff00000, 0, FMT_D4, 0, {DM1, MEM2(IMM32,AN0)}},
+{ "movhu", 0xfd4a0000, 0xffff0000, 0, FMT_D8, AM33, {MEM2(SD24, RM0), RN2}},
+{ "movhu", 0xfd5a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEM2(SD24, RN0)}},
+{ "movhu", 0xfdea0000, 0xffff0000, 0x22, FMT_D8, AM33, {MEMINC2 (RM0, IMM24), RN2}},
+{ "movhu", 0xfdfa0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEMINC2 (RN0, IMM24)}},
+{ "movhu", 0xfe4a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}},
+{ "movhu", 0xfe5a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}},
+{ "movhu", 0xfeea0000, 0xffff0000, 0x22, FMT_D9, AM33, {MEMINC2 (RM0, IMM32_HIGH8), RN2}},
+{ "movhu", 0xfefa0000, 0xffff0000, 0, FMT_D9, AM33, {RN2, MEMINC2 (RM0, IMM32_HIGH8)}},
+{ 0, 0, 0, 0, 0, 0, {0}},
+};
+
+/*
+ * fix up misalignment problems where possible
+ */
+asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code)
+{
+ const struct exception_table_entry *fixup;
+ const struct mn10300_opcode *pop;
+ unsigned long *registers = (unsigned long *) regs;
+ unsigned long data, *store, *postinc;
+ mm_segment_t seg;
+ siginfo_t info;
+ uint32_t opcode, disp, noc, xo, xm;
+ uint8_t *pc, byte;
+ void *address;
+ unsigned tmp, npop;
+
+ kdebug("MISALIGN at %lx\n", regs->pc);
+
+ if (in_interrupt())
+ die("Misalignment trap in interrupt context", regs, code);
+
+ if (regs->epsw & EPSW_IE)
+ asm volatile("or %0,epsw" : : "i"(EPSW_IE));
+
+ seg = get_fs();
+ set_fs(KERNEL_DS);
+
+ fixup = search_exception_tables(regs->pc);
+
+ /* first thing to do is to match the opcode */
+ pc = (u_int8_t *) regs->pc;
+
+ if (__get_user(byte, pc) != 0)
+ goto fetch_error;
+ opcode = byte;
+ noc = 8;
+
+ for (pop = mn10300_opcodes; pop->name; pop++) {
+ npop = log2(pop->opcode | pop->opmask);
+ if (npop <= 0 || npop > 31)
+ continue;
+ npop = (npop + 8) & ~7;
+
+ got_more_bits:
+ if (npop == noc) {
+ if ((opcode & pop->opmask) == pop->opcode)
+ goto found_opcode;
+ } else if (npop > noc) {
+ xo = pop->opcode >> (npop - noc);
+ xm = pop->opmask >> (npop - noc);
+
+ if ((opcode & xm) != xo)
+ continue;
+
+ /* we've got a partial match (an exact match on the
+ * first N bytes), so we need to get some more data */
+ pc++;
+ if (__get_user(byte, pc) != 0)
+ goto fetch_error;
+ opcode = opcode << 8 | byte;
+ noc += 8;
+ goto got_more_bits;
+ } else {
+ /* there's already been a partial match as long as the
+ * complete match we're now considering, so this one
+ * should't match */
+ continue;
+ }
+ }
+
+ /* didn't manage to find a fixup */
+ if (!user_mode(regs))
+ printk(KERN_CRIT "MISALIGN: %lx: unsupported instruction %x\n",
+ regs->pc, opcode);
+
+failed:
+ set_fs(seg);
+ if (die_if_no_fixup("misalignment error", regs, code))
+ return;
+
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRALN;
+ info.si_addr = (void *) regs->pc;
+ force_sig_info(SIGBUS, &info, current);
+ return;
+
+ /* error reading opcodes */
+fetch_error:
+ if (!user_mode(regs))
+ printk(KERN_CRIT
+ "MISALIGN: %p: fault whilst reading instruction data\n",
+ pc);
+ goto failed;
+
+bad_addr_mode:
+ if (!user_mode(regs))
+ printk(KERN_CRIT
+ "MISALIGN: %lx: unsupported addressing mode %x\n",
+ regs->pc, opcode);
+ goto failed;
+
+bad_reg_mode:
+ if (!user_mode(regs))
+ printk(KERN_CRIT
+ "MISALIGN: %lx: unsupported register mode %x\n",
+ regs->pc, opcode);
+ goto failed;
+
+unsupported_instruction:
+ if (!user_mode(regs))
+ printk(KERN_CRIT
+ "MISALIGN: %lx: unsupported instruction %x (%s)\n",
+ regs->pc, opcode, pop->name);
+ goto failed;
+
+transfer_failed:
+ set_fs(seg);
+ if (fixup) {
+ regs->pc = fixup->fixup;
+ return;
+ }
+ if (die_if_no_fixup("misalignment fixup", regs, code))
+ return;
+
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = 0;
+ info.si_addr = (void *) regs->pc;
+ force_sig_info(SIGSEGV, &info, current);
+ return;
+
+ /* we matched the opcode */
+found_opcode:
+ kdebug("MISALIGN: %lx: %x==%x { %x, %x }\n",
+ regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]);
+
+ tmp = format_tbl[pop->format].opsz;
+ if (tmp > noc)
+ BUG(); /* match was less complete than it ought to have been */
+
+ if (tmp < noc) {
+ tmp = noc - tmp;
+ opcode >>= tmp;
+ pc -= tmp >> 3;
+ }
+
+ /* grab the extra displacement (note it's LSB first) */
+ disp = 0;
+ tmp = format_tbl[pop->format].dispsz >> 3;
+ while (tmp > 0) {
+ tmp--;
+ disp <<= 8;
+
+ pc++;
+ if (__get_user(byte, pc) != 0)
+ goto fetch_error;
+ disp |= byte;
+ }
+
+ set_fs(KERNEL_XDS);
+ if (fixup || regs->epsw & EPSW_nSL)
+ set_fs(seg);
+
+ tmp = (pop->params[0] ^ pop->params[1]) & 0x80000000;
+ if (!tmp) {
+ if (!user_mode(regs))
+ printk(KERN_CRIT
+ "MISALIGN: %lx:"
+ " insn not move to/from memory %x\n",
+ regs->pc, opcode);
+ goto failed;
+ }
+
+ if (pop->params[0] & 0x80000000) {
+ /* move memory to register */
+ if (!misalignment_addr(registers, pop->params[0], opcode, disp,
+ &address, &postinc))
+ goto bad_addr_mode;
+
+ if (!misalignment_reg(registers, pop->params[1], opcode, disp,
+ &store))
+ goto bad_reg_mode;
+
+ if (strcmp(pop->name, "mov") == 0) {
+ kdebug("FIXUP: mov (%p),DARn\n", address);
+ if (copy_from_user(&data, (void *) address, 4) != 0)
+ goto transfer_failed;
+ if (pop->params[0] & 0x1000000)
+ *postinc += 4;
+ } else if (strcmp(pop->name, "movhu") == 0) {
+ kdebug("FIXUP: movhu (%p),DARn\n", address);
+ data = 0;
+ if (copy_from_user(&data, (void *) address, 2) != 0)
+ goto transfer_failed;
+ if (pop->params[0] & 0x1000000)
+ *postinc += 2;
+ } else {
+ goto unsupported_instruction;
+ }
+
+ *store = data;
+ } else {
+ /* move register to memory */
+ if (!misalignment_reg(registers, pop->params[0], opcode, disp,
+ &store))
+ goto bad_reg_mode;
+
+ if (!misalignment_addr(registers, pop->params[1], opcode, disp,
+ &address, &postinc))
+ goto bad_addr_mode;
+
+ data = *store;
+
+ if (strcmp(pop->name, "mov") == 0) {
+ kdebug("FIXUP: mov %lx,(%p)\n", data, address);
+ if (copy_to_user((void *) address, &data, 4) != 0)
+ goto transfer_failed;
+ if (pop->params[1] & 0x1000000)
+ *postinc += 4;
+ } else if (strcmp(pop->name, "movhu") == 0) {
+ kdebug("FIXUP: movhu %hx,(%p)\n",
+ (uint16_t) data, address);
+ if (copy_to_user((void *) address, &data, 2) != 0)
+ goto transfer_failed;
+ if (pop->params[1] & 0x1000000)
+ *postinc += 2;
+ } else {
+ goto unsupported_instruction;
+ }
+ }
+
+ tmp = format_tbl[pop->format].opsz + format_tbl[pop->format].dispsz;
+ regs->pc += tmp >> 3;
+
+ set_fs(seg);
+ return;
+}
+
+/*
+ * determine the address that was being accessed
+ */
+static int misalignment_addr(unsigned long *registers, unsigned params,
+ unsigned opcode, unsigned disp,
+ void **_address, unsigned long **_postinc)
+{
+ unsigned long *postinc = NULL, address = 0, tmp;
+
+ params &= 0x7fffffff;
+
+ do {
+ switch (params & 0xff) {
+ case DM0:
+ postinc = &registers[Dreg_index[opcode & 0x03]];
+ address += *postinc;
+ break;
+ case DM1:
+ postinc = &registers[Dreg_index[opcode >> 2 & 0x0c]];
+ address += *postinc;
+ break;
+ case DM2:
+ postinc = &registers[Dreg_index[opcode >> 4 & 0x30]];
+ address += *postinc;
+ break;
+ case AM0:
+ postinc = &registers[Areg_index[opcode & 0x03]];
+ address += *postinc;
+ break;
+ case AM1:
+ postinc = &registers[Areg_index[opcode >> 2 & 0x0c]];
+ address += *postinc;
+ break;
+ case AM2:
+ postinc = &registers[Areg_index[opcode >> 4 & 0x30]];
+ address += *postinc;
+ break;
+ case RM0:
+ postinc = &registers[Rreg_index[opcode & 0x0f]];
+ address += *postinc;
+ break;
+ case RM1:
+ postinc = &registers[Rreg_index[opcode >> 2 & 0x0f]];
+ address += *postinc;
+ break;
+ case RM2:
+ postinc = &registers[Rreg_index[opcode >> 4 & 0x0f]];
+ address += *postinc;
+ break;
+ case RM4:
+ postinc = &registers[Rreg_index[opcode >> 8 & 0x0f]];
+ address += *postinc;
+ break;
+ case RM6:
+ postinc = &registers[Rreg_index[opcode >> 12 & 0x0f]];
+ address += *postinc;
+ break;
+ case RD0:
+ postinc = &registers[Rreg_index[disp & 0x0f]];
+ address += *postinc;
+ break;
+ case RD2:
+ postinc = &registers[Rreg_index[disp >> 4 & 0x0f]];
+ address += *postinc;
+ break;
+
+ case SD8:
+ case SIMM8:
+ address += (int32_t) (int8_t) (disp & 0xff);
+ break;
+ case SD16:
+ address += (int32_t) (int16_t) (disp & 0xffff);
+ break;
+ case SD24:
+ tmp = disp << 8;
+ asm("asr 8,%0" : "=r"(tmp) : "0"(tmp));
+ address += tmp;
+ break;
+ case SIMM4_2:
+ tmp = opcode >> 4 & 0x0f;
+ tmp <<= 28;
+ asm("asr 28,%0" : "=r"(tmp) : "0"(tmp));
+ address += tmp;
+ break;
+ case IMM24:
+ address += disp & 0x00ffffff;
+ break;
+ case IMM32:
+ case IMM32_HIGH8:
+ address += disp;
+ break;
+ default:
+ return 0;
+ }
+ } while ((params >>= 8));
+
+ *_address = (void *) address;
+ *_postinc = postinc;
+ return 1;
+}
+
+/*
+ * determine the register that is acting as source/dest
+ */
+static int misalignment_reg(unsigned long *registers, unsigned params,
+ unsigned opcode, unsigned disp,
+ unsigned long **_register)
+{
+ params &= 0x7fffffff;
+
+ if (params & 0xffffff00)
+ return 0;
+
+ switch (params & 0xff) {
+ case DM0:
+ *_register = &registers[Dreg_index[opcode & 0x03]];
+ break;
+ case DM1:
+ *_register = &registers[Dreg_index[opcode >> 2 & 0x03]];
+ break;
+ case DM2:
+ *_register = &registers[Dreg_index[opcode >> 4 & 0x03]];
+ break;
+ case AM0:
+ *_register = &registers[Areg_index[opcode & 0x03]];
+ break;
+ case AM1:
+ *_register = &registers[Areg_index[opcode >> 2 & 0x03]];
+ break;
+ case AM2:
+ *_register = &registers[Areg_index[opcode >> 4 & 0x03]];
+ break;
+ case RM0:
+ *_register = &registers[Rreg_index[opcode & 0x0f]];
+ break;
+ case RM1:
+ *_register = &registers[Rreg_index[opcode >> 2 & 0x0f]];
+ break;
+ case RM2:
+ *_register = &registers[Rreg_index[opcode >> 4 & 0x0f]];
+ break;
+ case RM4:
+ *_register = &registers[Rreg_index[opcode >> 8 & 0x0f]];
+ break;
+ case RM6:
+ *_register = &registers[Rreg_index[opcode >> 12 & 0x0f]];
+ break;
+ case RD0:
+ *_register = &registers[Rreg_index[disp & 0x0f]];
+ break;
+ case RD2:
+ *_register = &registers[Rreg_index[disp >> 4 & 0x0f]];
+ break;
+ case SP:
+ *_register = &registers[REG_SP >> 2];
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/arch/mn10300/mm/mmu-context.c b/arch/mn10300/mm/mmu-context.c
new file mode 100644
index 00000000000..31c9d27a75a
--- /dev/null
+++ b/arch/mn10300/mm/mmu-context.c
@@ -0,0 +1,80 @@
+/* MN10300 MMU context allocation and management
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+
+/*
+ * list of the MMU contexts last allocated on each CPU
+ */
+unsigned long mmu_context_cache[NR_CPUS] = {
+ [0 ... NR_CPUS - 1] = MMU_CONTEXT_FIRST_VERSION * 2 - 1,
+};
+
+/*
+ * flush the specified TLB entry
+ */
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
+{
+ unsigned long pteu, cnx, flags;
+
+ addr &= PAGE_MASK;
+
+ /* make sure the context doesn't migrate and defend against
+ * interference from vmalloc'd regions */
+ local_irq_save(flags);
+
+ cnx = mm_context(vma->vm_mm);
+
+ if (cnx != MMU_NO_CONTEXT) {
+ pteu = addr | (cnx & 0x000000ffUL);
+ IPTEU = pteu;
+ DPTEU = pteu;
+ if (IPTEL & xPTEL_V)
+ IPTEL = 0;
+ if (DPTEL & xPTEL_V)
+ DPTEL = 0;
+ }
+
+ local_irq_restore(flags);
+}
+
+/*
+ * preemptively set a TLB entry
+ */
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
+{
+ unsigned long pteu, ptel, cnx, flags;
+
+ addr &= PAGE_MASK;
+ ptel = pte_val(pte) & ~(xPTEL_UNUSED1 | xPTEL_UNUSED2);
+
+ /* make sure the context doesn't migrate and defend against
+ * interference from vmalloc'd regions */
+ local_irq_save(flags);
+
+ cnx = mm_context(vma->vm_mm);
+
+ if (cnx != MMU_NO_CONTEXT) {
+ pteu = addr | (cnx & 0x000000ffUL);
+ if (!(pte_val(pte) & _PAGE_NX)) {
+ IPTEU = pteu;
+ if (IPTEL & xPTEL_V)
+ IPTEL = ptel;
+ }
+ DPTEU = pteu;
+ if (DPTEL & xPTEL_V)
+ DPTEL = ptel;
+ }
+
+ local_irq_restore(flags);
+}
diff --git a/arch/mn10300/mm/pgtable.c b/arch/mn10300/mm/pgtable.c
new file mode 100644
index 00000000000..a477038752b
--- /dev/null
+++ b/arch/mn10300/mm/pgtable.c
@@ -0,0 +1,197 @@
+/* MN10300 Page table management
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Modified by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/spinlock.h>
+#include <linux/quicklist.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+
+void show_mem(void)
+{
+ unsigned long i;
+ int free = 0, total = 0, reserved = 0, shared = 0;
+
+ int cached = 0;
+ printk(KERN_INFO "Mem-info:\n");
+ show_free_areas();
+ i = max_mapnr;
+ while (i-- > 0) {
+ total++;
+ if (PageReserved(mem_map + i))
+ reserved++;
+ else if (PageSwapCache(mem_map + i))
+ cached++;
+ else if (!page_count(mem_map + i))
+ free++;
+ else
+ shared += page_count(mem_map + i) - 1;
+ }
+ printk(KERN_INFO "%d pages of RAM\n", total);
+ printk(KERN_INFO "%d free pages\n", free);
+ printk(KERN_INFO "%d reserved pages\n", reserved);
+ printk(KERN_INFO "%d pages shared\n", shared);
+ printk(KERN_INFO "%d pages swap cached\n", cached);
+}
+
+/*
+ * Associate a large virtual page frame with a given physical page frame
+ * and protection flags for that frame. pfn is for the base of the page,
+ * vaddr is what the page gets mapped to - both must be properly aligned.
+ * The pmd must already be instantiated. Assumes PAE mode.
+ */
+void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ if (vaddr & (PMD_SIZE-1)) { /* vaddr is misaligned */
+ printk(KERN_ERR "set_pmd_pfn: vaddr misaligned\n");
+ return; /* BUG(); */
+ }
+ if (pfn & (PTRS_PER_PTE-1)) { /* pfn is misaligned */
+ printk(KERN_ERR "set_pmd_pfn: pfn misaligned\n");
+ return; /* BUG(); */
+ }
+ pgd = swapper_pg_dir + pgd_index(vaddr);
+ if (pgd_none(*pgd)) {
+ printk(KERN_ERR "set_pmd_pfn: pgd_none\n");
+ return; /* BUG(); */
+ }
+ pud = pud_offset(pgd, vaddr);
+ pmd = pmd_offset(pud, vaddr);
+ set_pmd(pmd, pfn_pmd(pfn, flags));
+ /*
+ * It's enough to flush this one mapping.
+ * (PGE mappings get flushed as well)
+ */
+ __flush_tlb_one(vaddr);
+}
+
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+ pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+ if (pte)
+ clear_page(pte);
+ return pte;
+}
+
+struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ struct page *pte;
+
+#ifdef CONFIG_HIGHPTE
+ pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT, 0);
+#else
+ pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+#endif
+ if (pte)
+ clear_highpage(pte);
+ return pte;
+}
+
+/*
+ * List of all pgd's needed for non-PAE so it can invalidate entries
+ * in both cached and uncached pgd's; not needed for PAE since the
+ * kernel pmd is shared. If PAE were not to share the pmd a similar
+ * tactic would be needed. This is essentially codepath-based locking
+ * against pageattr.c; it is the unique case in which a valid change
+ * of kernel pagetables can't be lazily synchronized by vmalloc faults.
+ * vmalloc faults work because attached pagetables are never freed.
+ * If the locking proves to be non-performant, a ticketing scheme with
+ * checks at dup_mmap(), exec(), and other mmlist addition points
+ * could be used. The locking scheme was chosen on the basis of
+ * manfred's recommendations and having no core impact whatsoever.
+ * -- wli
+ */
+DEFINE_SPINLOCK(pgd_lock);
+struct page *pgd_list;
+
+static inline void pgd_list_add(pgd_t *pgd)
+{
+ struct page *page = virt_to_page(pgd);
+ page->index = (unsigned long) pgd_list;
+ if (pgd_list)
+ set_page_private(pgd_list, (unsigned long) &page->index);
+ pgd_list = page;
+ set_page_private(page, (unsigned long) &pgd_list);
+}
+
+static inline void pgd_list_del(pgd_t *pgd)
+{
+ struct page *next, **pprev, *page = virt_to_page(pgd);
+ next = (struct page *) page->index;
+ pprev = (struct page **) page_private(page);
+ *pprev = next;
+ if (next)
+ set_page_private(next, (unsigned long) pprev);
+}
+
+void pgd_ctor(void *pgd)
+{
+ unsigned long flags;
+
+ if (PTRS_PER_PMD == 1)
+ spin_lock_irqsave(&pgd_lock, flags);
+
+ memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
+ swapper_pg_dir + USER_PTRS_PER_PGD,
+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+
+ if (PTRS_PER_PMD > 1)
+ return;
+
+ pgd_list_add(pgd);
+ spin_unlock_irqrestore(&pgd_lock, flags);
+ memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+}
+
+/* never called when PTRS_PER_PMD > 1 */
+void pgd_dtor(void *pgd)
+{
+ unsigned long flags; /* can be called from interrupt context */
+
+ spin_lock_irqsave(&pgd_lock, flags);
+ pgd_list_del(pgd);
+ spin_unlock_irqrestore(&pgd_lock, flags);
+}
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+ return quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
+}
+
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+ quicklist_free(0, pgd_dtor, pgd);
+}
+
+void __init pgtable_cache_init(void)
+{
+}
+
+void check_pgt_cache(void)
+{
+ quicklist_trim(0, pgd_dtor, 25, 16);
+}
diff --git a/arch/mn10300/mm/tlb-mn10300.S b/arch/mn10300/mm/tlb-mn10300.S
new file mode 100644
index 00000000000..789208094e9
--- /dev/null
+++ b/arch/mn10300/mm/tlb-mn10300.S
@@ -0,0 +1,207 @@
+###############################################################################
+#
+# TLB loading functions
+#
+# Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+# Modified by David Howells (dhowells@redhat.com)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public Licence
+# as published by the Free Software Foundation; either version
+# 2 of the Licence, or (at your option) any later version.
+#
+###############################################################################
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/intctl-regs.h>
+#include <asm/frame.inc>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+###############################################################################
+#
+# Instruction TLB Miss handler entry point
+#
+###############################################################################
+ .type itlb_miss,@function
+ENTRY(itlb_miss)
+ and ~EPSW_NMID,epsw
+#ifdef CONFIG_GDBSTUB
+ movm [d2,d3,a2],(sp)
+#else
+ or EPSW_nAR,epsw # switch D0-D3 & A0-A3 to the alternate
+ # register bank
+ nop
+ nop
+ nop
+#endif
+
+ mov (IPTEU),d3
+ mov (PTBR),a2
+ mov d3,d2
+ and 0xffc00000,d2
+ lsr 20,d2
+ mov (a2,d2),a2 # PTD *ptd = PGD[addr 31..22]
+ btst _PAGE_VALID,a2
+ beq itlb_miss_fault # jump if doesn't point anywhere
+
+ and ~(PAGE_SIZE-1),a2
+ mov d3,d2
+ and 0x003ff000,d2
+ lsr 10,d2
+ add d2,a2
+ mov (a2),d2 # get pte from PTD[addr 21..12]
+ btst _PAGE_VALID,d2
+ beq itlb_miss_fault # jump if doesn't point to a page
+ # (might be a swap id)
+ bset _PAGE_ACCESSED,(0,a2)
+ and ~(xPTEL_UNUSED1|xPTEL_UNUSED2),d2
+itlb_miss_set:
+ mov d2,(IPTEL) # change the TLB
+#ifdef CONFIG_GDBSTUB
+ movm (sp),[d2,d3,a2]
+#endif
+ rti
+
+itlb_miss_fault:
+ mov _PAGE_VALID,d2 # force address error handler to be
+ # invoked
+ bra itlb_miss_set
+
+ .size itlb_miss, . - itlb_miss
+
+###############################################################################
+#
+# Data TLB Miss handler entry point
+#
+###############################################################################
+ .type dtlb_miss,@function
+ENTRY(dtlb_miss)
+ and ~EPSW_NMID,epsw
+#ifdef CONFIG_GDBSTUB
+ movm [d2,d3,a2],(sp)
+#else
+ or EPSW_nAR,epsw # switch D0-D3 & A0-A3 to the alternate
+ # register bank
+ nop
+ nop
+ nop
+#endif
+
+ mov (DPTEU),d3
+ mov (PTBR),a2
+ mov d3,d2
+ and 0xffc00000,d2
+ lsr 20,d2
+ mov (a2,d2),a2 # PTD *ptd = PGD[addr 31..22]
+ btst _PAGE_VALID,a2
+ beq dtlb_miss_fault # jump if doesn't point anywhere
+
+ and ~(PAGE_SIZE-1),a2
+ mov d3,d2
+ and 0x003ff000,d2
+ lsr 10,d2
+ add d2,a2
+ mov (a2),d2 # get pte from PTD[addr 21..12]
+ btst _PAGE_VALID,d2
+ beq dtlb_miss_fault # jump if doesn't point to a page
+ # (might be a swap id)
+ bset _PAGE_ACCESSED,(0,a2)
+ and ~(xPTEL_UNUSED1|xPTEL_UNUSED2),d2
+dtlb_miss_set:
+ mov d2,(DPTEL) # change the TLB
+#ifdef CONFIG_GDBSTUB
+ movm (sp),[d2,d3,a2]
+#endif
+ rti
+
+dtlb_miss_fault:
+ mov _PAGE_VALID,d2 # force address error handler to be
+ # invoked
+ bra dtlb_miss_set
+ .size dtlb_miss, . - dtlb_miss
+
+###############################################################################
+#
+# Instruction TLB Address Error handler entry point
+#
+###############################################################################
+ .type itlb_aerror,@function
+ENTRY(itlb_aerror)
+ and ~EPSW_NMID,epsw
+ add -4,sp
+ SAVE_ALL
+ add -4,sp # need to pass three params
+
+ # calculate the fault code
+ movhu (MMUFCR_IFC),d1
+ or 0x00010000,d1 # it's an instruction fetch
+
+ # determine the page address
+ mov (IPTEU),a2
+ mov a2,d0
+ and PAGE_MASK,d0
+ mov d0,(12,sp)
+
+ clr d0
+ mov d0,(IPTEL)
+
+ and ~EPSW_NMID,epsw
+ or EPSW_IE,epsw
+ mov fp,d0
+ call do_page_fault[],0 # do_page_fault(regs,code,addr
+
+ jmp ret_from_exception
+ .size itlb_aerror, . - itlb_aerror
+
+###############################################################################
+#
+# Data TLB Address Error handler entry point
+#
+###############################################################################
+ .type dtlb_aerror,@function
+ENTRY(dtlb_aerror)
+ and ~EPSW_NMID,epsw
+ add -4,sp
+ mov d1,(sp)
+
+ movhu (MMUFCR_DFC),d1 # is it the initial valid write
+ # to this page?
+ and MMUFCR_xFC_INITWR,d1
+ beq dtlb_pagefault # jump if not
+
+ mov (DPTEL),d1 # set the dirty bit
+ # (don't replace with BSET!)
+ or _PAGE_DIRTY,d1
+ mov d1,(DPTEL)
+ mov (sp),d1
+ add 4,sp
+ rti
+
+ ALIGN
+dtlb_pagefault:
+ mov (sp),d1
+ SAVE_ALL
+ add -4,sp # need to pass three params
+
+ # calculate the fault code
+ movhu (MMUFCR_DFC),d1
+
+ # determine the page address
+ mov (DPTEU),a2
+ mov a2,d0
+ and PAGE_MASK,d0
+ mov d0,(12,sp)
+
+ clr d0
+ mov d0,(DPTEL)
+
+ and ~EPSW_NMID,epsw
+ or EPSW_IE,epsw
+ mov fp,d0
+ call do_page_fault[],0 # do_page_fault(regs,code,addr
+
+ jmp ret_from_exception
+ .size dtlb_aerror, . - dtlb_aerror
diff --git a/arch/mn10300/oprofile/Kconfig b/arch/mn10300/oprofile/Kconfig
new file mode 100644
index 00000000000..19d37730b66
--- /dev/null
+++ b/arch/mn10300/oprofile/Kconfig
@@ -0,0 +1,23 @@
+
+menu "Profiling support"
+ depends on EXPERIMENTAL
+
+config PROFILING
+ bool "Profiling support (EXPERIMENTAL)"
+ help
+ Say Y here to enable the extended profiling support mechanisms used
+ by profilers such as OProfile.
+
+
+config OPROFILE
+ tristate "OProfile system profiling (EXPERIMENTAL)"
+ depends on PROFILING
+ help
+ OProfile is a profiling system capable of profiling the
+ whole system, include the kernel, kernel modules, libraries,
+ and applications.
+
+ If unsure, say N.
+
+endmenu
+
diff --git a/arch/mn10300/oprofile/Makefile b/arch/mn10300/oprofile/Makefile
new file mode 100644
index 00000000000..918dbe60ebb
--- /dev/null
+++ b/arch/mn10300/oprofile/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the MN10300-specific profiling code
+#
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
+ oprof.o cpu_buffer.o buffer_sync.o \
+ event_buffer.o oprofile_files.o \
+ oprofilefs.o oprofile_stats.o \
+ timer_int.o )
+
+oprofile-y := $(DRIVER_OBJS) op_model_null.o
+
diff --git a/arch/mn10300/oprofile/op_model_null.c b/arch/mn10300/oprofile/op_model_null.c
new file mode 100644
index 00000000000..cd4ab374bc4
--- /dev/null
+++ b/arch/mn10300/oprofile/op_model_null.c
@@ -0,0 +1,22 @@
+/* Null profiling driver
+ *
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * Licence. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/oprofile.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+
+int __init oprofile_arch_init(struct oprofile_operations *ops)
+{
+ return -ENODEV;
+}
+
+void oprofile_arch_exit(void)
+{
+}
+
diff --git a/arch/mn10300/proc-mn103e010/Makefile b/arch/mn10300/proc-mn103e010/Makefile
new file mode 100644
index 00000000000..ac2c9784cd2
--- /dev/null
+++ b/arch/mn10300/proc-mn103e010/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the MN103E010 processor chip specific code
+#
+obj-y := proc-init.o
+
diff --git a/arch/mn10300/proc-mn103e010/proc-init.c b/arch/mn10300/proc-mn103e010/proc-init.c
new file mode 100644
index 00000000000..9a482efafa8
--- /dev/null
+++ b/arch/mn10300/proc-mn103e010/proc-init.c
@@ -0,0 +1,75 @@
+/* MN103E010 Processor initialisation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <asm/rtc.h>
+
+/*
+ * initialise the on-silicon processor peripherals
+ */
+asmlinkage void __init processor_init(void)
+{
+ int loop;
+
+ /* set up the exception table first */
+ for (loop = 0x000; loop < 0x400; loop += 8)
+ __set_intr_stub(loop, __common_exception);
+
+ __set_intr_stub(EXCEP_ITLBMISS, itlb_miss);
+ __set_intr_stub(EXCEP_DTLBMISS, dtlb_miss);
+ __set_intr_stub(EXCEP_IAERROR, itlb_aerror);
+ __set_intr_stub(EXCEP_DAERROR, dtlb_aerror);
+ __set_intr_stub(EXCEP_BUSERROR, raw_bus_error);
+ __set_intr_stub(EXCEP_DOUBLE_FAULT, double_fault);
+ __set_intr_stub(EXCEP_SYSCALL0, system_call);
+
+ __set_intr_stub(EXCEP_NMI, nmi_handler);
+ __set_intr_stub(EXCEP_WDT, nmi_handler);
+ __set_intr_stub(EXCEP_IRQ_LEVEL0, irq_handler);
+ __set_intr_stub(EXCEP_IRQ_LEVEL1, irq_handler);
+ __set_intr_stub(EXCEP_IRQ_LEVEL2, irq_handler);
+ __set_intr_stub(EXCEP_IRQ_LEVEL3, irq_handler);
+ __set_intr_stub(EXCEP_IRQ_LEVEL4, irq_handler);
+ __set_intr_stub(EXCEP_IRQ_LEVEL5, irq_handler);
+ __set_intr_stub(EXCEP_IRQ_LEVEL6, irq_handler);
+
+ IVAR0 = EXCEP_IRQ_LEVEL0;
+ IVAR1 = EXCEP_IRQ_LEVEL1;
+ IVAR2 = EXCEP_IRQ_LEVEL2;
+ IVAR3 = EXCEP_IRQ_LEVEL3;
+ IVAR4 = EXCEP_IRQ_LEVEL4;
+ IVAR5 = EXCEP_IRQ_LEVEL5;
+ IVAR6 = EXCEP_IRQ_LEVEL6;
+
+ mn10300_dcache_flush_inv();
+ mn10300_icache_inv();
+
+ /* disable all interrupts and set to priority 6 (lowest) */
+ for (loop = 0; loop < NR_IRQS; loop++)
+ GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
+
+ /* clear the timers */
+ TM0MD = 0;
+ TM1MD = 0;
+ TM2MD = 0;
+ TM3MD = 0;
+ TM4MD = 0;
+ TM5MD = 0;
+ TM6MD = 0;
+ TM6MDA = 0;
+ TM6MDB = 0;
+ TM7MD = 0;
+ TM8MD = 0;
+ TM9MD = 0;
+ TM10MD = 0;
+ TM11MD = 0;
+
+ calibrate_clock();
+}
diff --git a/arch/mn10300/unit-asb2303/Makefile b/arch/mn10300/unit-asb2303/Makefile
new file mode 100644
index 00000000000..38a5bb43b0b
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/Makefile
@@ -0,0 +1,6 @@
+###############################################################################
+#
+# Makefile for the ASB2303 board
+#
+###############################################################################
+obj-y := unit-init.o smc91111.o flash.o leds.o
diff --git a/arch/mn10300/unit-asb2303/flash.c b/arch/mn10300/unit-asb2303/flash.c
new file mode 100644
index 00000000000..17fe083fcb6
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/flash.c
@@ -0,0 +1,100 @@
+/* Handle mapping of the flash on the ASB2303 board
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+#define ASB2303_PROM_ADDR 0xA0000000 /* Boot PROM */
+#define ASB2303_PROM_SIZE (2 * 1024 * 1024)
+#define ASB2303_FLASH_ADDR 0xA4000000 /* System Flash */
+#define ASB2303_FLASH_SIZE (32 * 1024 * 1024)
+#define ASB2303_CONFIG_ADDR 0xA6000000 /* System Config EEPROM */
+#define ASB2303_CONFIG_SIZE (8 * 1024)
+
+/*
+ * default MTD partition table for both main flash devices, expected to be
+ * overridden by RedBoot
+ */
+static struct mtd_partition asb2303_partitions[] = {
+ {
+ .name = "Bootloader",
+ .size = 0x00040000,
+ .offset = 0,
+ .mask_flags = MTD_CAP_ROM /* force read-only */
+ }, {
+ .name = "Kernel",
+ .size = 0x00400000,
+ .offset = 0x00040000,
+ }, {
+ .name = "Filesystem",
+ .size = MTDPART_SIZ_FULL,
+ .offset = 0x00440000
+ }
+};
+
+/*
+ * the ASB2303 Boot PROM definition
+ */
+static struct physmap_flash_data asb2303_bootprom_data = {
+ .width = 2,
+ .nr_parts = 1,
+ .parts = asb2303_partitions,
+};
+
+static struct resource asb2303_bootprom_resource = {
+ .start = ASB2303_PROM_ADDR,
+ .end = ASB2303_PROM_ADDR + ASB2303_PROM_SIZE,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device asb2303_bootprom = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev.platform_data = &asb2303_bootprom_data,
+ .num_resources = 1,
+ .resource = &asb2303_bootprom_resource,
+};
+
+/*
+ * the ASB2303 System Flash definition
+ */
+static struct physmap_flash_data asb2303_sysflash_data = {
+ .width = 4,
+ .nr_parts = 1,
+ .parts = asb2303_partitions,
+};
+
+static struct resource asb2303_sysflash_resource = {
+ .start = ASB2303_FLASH_ADDR,
+ .end = ASB2303_FLASH_ADDR + ASB2303_FLASH_SIZE,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device asb2303_sysflash = {
+ .name = "physmap-flash",
+ .id = 1,
+ .dev.platform_data = &asb2303_sysflash_data,
+ .num_resources = 1,
+ .resource = &asb2303_sysflash_resource,
+};
+
+/*
+ * register the ASB2303 flashes
+ */
+static int __init asb2303_mtd_init(void)
+{
+ platform_device_register(&asb2303_bootprom);
+ platform_device_register(&asb2303_sysflash);
+ return 0;
+}
+
+module_init(asb2303_mtd_init);
diff --git a/arch/mn10300/unit-asb2303/leds.c b/arch/mn10300/unit-asb2303/leds.c
new file mode 100644
index 00000000000..cd4bc78ccfc
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/leds.c
@@ -0,0 +1,52 @@
+/* ASB2303 peripheral 7-segment LEDs x1 support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/intctl-regs.h>
+#include <asm/rtc-regs.h>
+#include <asm/unit/leds.h>
+
+#if 0
+static const u8 asb2303_led_hex_tbl[16] = {
+ 0x80, 0xf2, 0x48, 0x60, 0x32, 0x24, 0x04, 0xf0,
+ 0x00, 0x20, 0x10, 0x06, 0x8c, 0x42, 0x0c, 0x1c
+};
+#endif
+
+static const u8 asb2303_led_chase_tbl[6] = {
+ ~0x02, /* top - segA */
+ ~0x04, /* right top - segB */
+ ~0x08, /* right bottom - segC */
+ ~0x10, /* bottom - segD */
+ ~0x20, /* left bottom - segE */
+ ~0x40, /* left top - segF */
+};
+
+static unsigned asb2303_led_chase;
+
+void peripheral_leds_display_exception(enum exception_code code)
+{
+ ASB2303_GPIO0DEF = 0x5555; /* configure as an output port */
+ ASB2303_7SEGLEDS = 0x6d; /* triple horizontal bar */
+}
+
+void peripheral_leds_led_chase(void)
+{
+ ASB2303_GPIO0DEF = 0x5555; /* configure as an output port */
+ ASB2303_7SEGLEDS = asb2303_led_chase_tbl[asb2303_led_chase];
+ asb2303_led_chase++;
+ if (asb2303_led_chase >= 6)
+ asb2303_led_chase = 0;
+}
diff --git a/arch/mn10300/unit-asb2303/smc91111.c b/arch/mn10300/unit-asb2303/smc91111.c
new file mode 100644
index 00000000000..30875dd6563
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/smc91111.c
@@ -0,0 +1,52 @@
+/* ASB2303 initialisation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/timex.h>
+#include <asm/processor.h>
+#include <asm/intctl-regs.h>
+#include <asm/unit/smc91111.h>
+
+static struct resource smc91c111_resources[] = {
+ [0] = {
+ .start = SMC91111_BASE,
+ .end = SMC91111_BASE_END,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = SMC91111_IRQ,
+ .end = SMC91111_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91c111_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91c111_resources),
+ .resource = smc91c111_resources,
+};
+
+/*
+ * add platform devices
+ */
+static int __init unit_device_init(void)
+{
+ platform_device_register(&smc91c111_device);
+ return 0;
+}
+
+device_initcall(unit_device_init);
diff --git a/arch/mn10300/unit-asb2303/unit-init.c b/arch/mn10300/unit-asb2303/unit-init.c
new file mode 100644
index 00000000000..14b2c817cff
--- /dev/null
+++ b/arch/mn10300/unit-asb2303/unit-init.c
@@ -0,0 +1,60 @@
+/* ASB2303 initialisation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <asm/intctl-regs.h>
+
+/*
+ * initialise some of the unit hardware before gdbstub is set up
+ */
+asmlinkage void __init unit_init(void)
+{
+ /* set up the external interrupts */
+ SET_XIRQ_TRIGGER(0, XIRQ_TRIGGER_HILEVEL);
+ SET_XIRQ_TRIGGER(2, XIRQ_TRIGGER_LOWLEVEL);
+ SET_XIRQ_TRIGGER(3, XIRQ_TRIGGER_HILEVEL);
+ SET_XIRQ_TRIGGER(4, XIRQ_TRIGGER_LOWLEVEL);
+ SET_XIRQ_TRIGGER(5, XIRQ_TRIGGER_LOWLEVEL);
+}
+
+/*
+ * initialise the rest of the unit hardware after gdbstub is ready
+ */
+void __init unit_setup(void)
+{
+}
+
+/*
+ * initialise the external interrupts used by a unit of this type
+ */
+void __init unit_init_IRQ(void)
+{
+ unsigned int extnum;
+
+ for (extnum = 0; extnum < NR_XIRQS; extnum++) {
+ switch (GET_XIRQ_TRIGGER(extnum)) {
+ case XIRQ_TRIGGER_HILEVEL:
+ case XIRQ_TRIGGER_LOWLEVEL:
+ set_irq_handler(XIRQ2IRQ(extnum), handle_level_irq);
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/arch/mn10300/unit-asb2305/Makefile b/arch/mn10300/unit-asb2305/Makefile
new file mode 100644
index 00000000000..0551022225b
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/Makefile
@@ -0,0 +1,8 @@
+###############################################################################
+#
+# Makefile for the ASB2305 board
+#
+###############################################################################
+obj-y := unit-init.o leds.o
+
+obj-$(CONFIG_PCI) += pci.o pci-asb2305.o pci-irq.o pci-iomap.o
diff --git a/arch/mn10300/unit-asb2305/leds.c b/arch/mn10300/unit-asb2305/leds.c
new file mode 100644
index 00000000000..e99dcc9cee1
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/leds.c
@@ -0,0 +1,124 @@
+/* ASB2305 Peripheral 7-segment LEDs x4 support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/cpu/intctl-regs.h>
+#include <asm/cpu/rtc-regs.h>
+#include <asm/unit/leds.h>
+
+static const u8 asb2305_led_hex_tbl[16] = {
+ 0x80, 0xf2, 0x48, 0x60, 0x32, 0x24, 0x04, 0xf0,
+ 0x00, 0x20, 0x10, 0x06, 0x8c, 0x42, 0x0c, 0x1c
+};
+
+static const u32 asb2305_led_chase_tbl[6] = {
+ ~0x02020202, /* top - segA */
+ ~0x04040404, /* right top - segB */
+ ~0x08080808, /* right bottom - segC */
+ ~0x10101010, /* bottom - segD */
+ ~0x20202020, /* left bottom - segE */
+ ~0x40404040, /* left top - segF */
+};
+
+static unsigned asb2305_led_chase;
+
+void peripheral_leds7x4_display_dec(unsigned int val, unsigned int points)
+{
+ u32 leds;
+
+ leds = asb2305_led_hex_tbl[(val/1000) % 10];
+ leds <<= 8;
+ leds |= asb2305_led_hex_tbl[(val/100) % 10];
+ leds <<= 8;
+ leds |= asb2305_led_hex_tbl[(val/10) % 10];
+ leds <<= 8;
+ leds |= asb2305_led_hex_tbl[val % 10];
+ leds |= points^0x01010101;
+
+ ASB2305_7SEGLEDS = leds;
+}
+
+void peripheral_leds7x4_display_hex(unsigned int val, unsigned int points)
+{
+ u32 leds;
+
+ leds = asb2305_led_hex_tbl[(val/1000) % 10];
+ leds <<= 8;
+ leds |= asb2305_led_hex_tbl[(val/100) % 10];
+ leds <<= 8;
+ leds |= asb2305_led_hex_tbl[(val/10) % 10];
+ leds <<= 8;
+ leds |= asb2305_led_hex_tbl[val % 10];
+ leds |= points^0x01010101;
+
+ ASB2305_7SEGLEDS = leds;
+}
+
+void peripheral_leds_display_exception(enum exception_code code)
+{
+ u32 leds;
+
+ leds = asb2305_led_hex_tbl[(code/0x100) % 0x10];
+ leds <<= 8;
+ leds |= asb2305_led_hex_tbl[(code/0x10) % 0x10];
+ leds <<= 8;
+ leds |= asb2305_led_hex_tbl[code % 0x10];
+ leds |= 0x6d010101;
+
+ ASB2305_7SEGLEDS = leds;
+}
+
+void peripheral_leds7x4_display_minssecs(unsigned int time, unsigned int points)
+{
+ u32 leds;
+
+ leds = asb2305_led_hex_tbl[(time/600) % 6];
+ leds <<= 8;
+ leds |= asb2305_led_hex_tbl[(time/60) % 10];
+ leds <<= 8;
+ leds |= asb2305_led_hex_tbl[(time/10) % 6];
+ leds <<= 8;
+ leds |= asb2305_led_hex_tbl[time % 10];
+ leds |= points^0x01010101;
+
+ ASB2305_7SEGLEDS = leds;
+}
+
+void peripheral_leds7x4_display_rtc(void)
+{
+ unsigned int clock;
+ u8 mins, secs;
+
+ mins = RTMCR;
+ secs = RTSCR;
+
+ clock = ((mins & 0xf0) >> 4);
+ clock *= 10;
+ clock += (mins & 0x0f);
+ clock *= 6;
+
+ clock += ((secs & 0xf0) >> 4);
+ clock *= 10;
+ clock += (secs & 0x0f);
+
+ peripheral_leds7x4_display_minssecs(clock, 0);
+}
+
+void peripheral_leds_led_chase(void)
+{
+ ASB2305_7SEGLEDS = asb2305_led_chase_tbl[asb2305_led_chase];
+ asb2305_led_chase++;
+ if (asb2305_led_chase >= 6)
+ asb2305_led_chase = 0;
+}
diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c
new file mode 100644
index 00000000000..d100ca78846
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.c
@@ -0,0 +1,303 @@
+/* ASB2305 PCI resource stuff
+ *
+ * Copyright (C) 2001 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from arch/i386/pci-i386.c
+ * - Copyright 1997--2000 Martin Mares <mj@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include "pci-asb2305.h"
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void pcibios_align_resource(void *data, struct resource *res,
+ resource_size_t size, resource_size_t align)
+{
+#if 0
+ struct pci_dev *dev = data;
+
+ printk(KERN_DEBUG
+ "### PCIBIOS_ALIGN_RESOURCE(%s,,{%08lx-%08lx,%08lx},%lx)\n",
+ pci_name(dev),
+ res->start,
+ res->end,
+ res->flags,
+ size
+ );
+#endif
+
+ if (res->flags & IORESOURCE_IO) {
+ unsigned long start = res->start;
+
+ if (start & 0x300) {
+ start = (start + 0x3ff) & ~0x3ff;
+ res->start = start;
+ }
+ }
+}
+
+
+/*
+ * Handle resources of PCI devices. If the world were perfect, we could
+ * just allocate all the resource regions and do nothing more. It isn't.
+ * On the other hand, we cannot just re-allocate all devices, as it would
+ * require us to know lots of host bridge internals. So we attempt to
+ * keep as much of the original configuration as possible, but tweak it
+ * when it's found to be wrong.
+ *
+ * Known BIOS problems we have to work around:
+ * - I/O or memory regions not configured
+ * - regions configured, but not enabled in the command register
+ * - bogus I/O addresses above 64K used
+ * - expansion ROMs left enabled (this may sound harmless, but given
+ * the fact the PCI specs explicitly allow address decoders to be
+ * shared between expansion ROMs and other resource regions, it's
+ * at least dangerous)
+ *
+ * Our solution:
+ * (1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ * This gives us fixed barriers on where we can allocate.
+ * (2) Allocate resources for all enabled devices. If there is
+ * a collision, just mark the resource as unallocated. Also
+ * disable expansion ROMs during this step.
+ * (3) Try to allocate resources for disabled devices. If the
+ * resources were assigned correctly, everything goes well,
+ * if they weren't, they won't disturb allocation of other
+ * resources.
+ * (4) Assign new addresses to resources which were either
+ * not configured at all or misconfigured. If explicitly
+ * requested by the user, configure expansion ROM address
+ * as well.
+ */
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+ struct pci_bus *bus;
+ struct pci_dev *dev;
+ int idx;
+ struct resource *r, *pr;
+
+ /* Depth-First Search on bus tree */
+ list_for_each_entry(bus, bus_list, node) {
+ dev = bus->self;
+ if (dev) {
+ for (idx = PCI_BRIDGE_RESOURCES;
+ idx < PCI_NUM_RESOURCES;
+ idx++) {
+ r = &dev->resource[idx];
+ if (!r->flags)
+ continue;
+ pr = pci_find_parent_resource(dev, r);
+ if (!r->start ||
+ !pr ||
+ request_resource(pr, r) < 0) {
+ printk(KERN_ERR "PCI:"
+ " Cannot allocate resource"
+ " region %d of bridge %s\n",
+ idx, pci_name(dev));
+ /* Something is wrong with the region.
+ * Invalidate the resource to prevent
+ * child resource allocations in this
+ * range. */
+ r->flags = 0;
+ }
+ }
+ }
+ pcibios_allocate_bus_resources(&bus->children);
+ }
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+ struct pci_dev *dev = NULL;
+ int idx, disabled;
+ u16 command;
+ struct resource *r, *pr;
+
+ for_each_pci_dev(dev) {
+ pci_read_config_word(dev, PCI_COMMAND, &command);
+ for (idx = 0; idx < 6; idx++) {
+ r = &dev->resource[idx];
+ if (r->parent) /* Already allocated */
+ continue;
+ if (!r->start) /* Address not assigned */
+ continue;
+ if (r->flags & IORESOURCE_IO)
+ disabled = !(command & PCI_COMMAND_IO);
+ else
+ disabled = !(command & PCI_COMMAND_MEMORY);
+ if (pass == disabled) {
+ DBG("PCI[%s]: Resource %08lx-%08lx"
+ " (f=%lx, d=%d, p=%d)\n",
+ pci_name(dev), r->start, r->end, r->flags,
+ disabled, pass);
+ pr = pci_find_parent_resource(dev, r);
+ if (!pr || request_resource(pr, r) < 0) {
+ printk(KERN_ERR "PCI:"
+ " Cannot allocate resource"
+ " region %d of device %s\n",
+ idx, pci_name(dev));
+ /* We'll assign a new address later */
+ r->end -= r->start;
+ r->start = 0;
+ }
+ }
+ }
+ if (!pass) {
+ r = &dev->resource[PCI_ROM_RESOURCE];
+ if (r->flags & IORESOURCE_ROM_ENABLE) {
+ /* Turn the ROM off, leave the resource region,
+ * but keep it unregistered. */
+ u32 reg;
+ DBG("PCI: Switching off ROM of %s\n",
+ pci_name(dev));
+ r->flags &= ~IORESOURCE_ROM_ENABLE;
+ pci_read_config_dword(
+ dev, dev->rom_base_reg, &reg);
+ pci_write_config_dword(
+ dev, dev->rom_base_reg,
+ reg & ~PCI_ROM_ADDRESS_ENABLE);
+ }
+ }
+ }
+}
+
+static int __init pcibios_assign_resources(void)
+{
+ struct pci_dev *dev = NULL;
+ struct resource *r, *pr;
+
+ if (!(pci_probe & PCI_ASSIGN_ROMS)) {
+ /* Try to use BIOS settings for ROMs, otherwise let
+ pci_assign_unassigned_resources() allocate the new
+ addresses. */
+ for_each_pci_dev(dev) {
+ r = &dev->resource[PCI_ROM_RESOURCE];
+ if (!r->flags || !r->start)
+ continue;
+ pr = pci_find_parent_resource(dev, r);
+ if (!pr || request_resource(pr, r) < 0) {
+ r->end -= r->start;
+ r->start = 0;
+ }
+ }
+ }
+
+ pci_assign_unassigned_resources();
+
+ return 0;
+}
+
+fs_initcall(pcibios_assign_resources);
+
+void __init pcibios_resource_survey(void)
+{
+ DBG("PCI: Allocating resources\n");
+ pcibios_allocate_bus_resources(&pci_root_buses);
+ pcibios_allocate_resources(0);
+ pcibios_allocate_resources(1);
+}
+
+int pcibios_enable_resources(struct pci_dev *dev, int mask)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+
+ for (idx = 0; idx < 6; idx++) {
+ /* Only set up the requested stuff */
+ if (!(mask & (1 << idx)))
+ continue;
+
+ r = &dev->resource[idx];
+
+ if (!r->start && r->end) {
+ printk(KERN_ERR
+ "PCI: Device %s not available because of"
+ " resource collisions\n",
+ pci_name(dev));
+ return -EINVAL;
+ }
+
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+
+ if (dev->resource[PCI_ROM_RESOURCE].start)
+ cmd |= PCI_COMMAND_MEMORY;
+
+ if (cmd != old_cmd)
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+ return 0;
+}
+
+/*
+ * If we set up a device for bus mastering, we need to check the latency
+ * timer as certain crappy BIOSes forget to set it properly.
+ */
+unsigned int pcibios_max_latency = 255;
+
+void pcibios_set_master(struct pci_dev *dev)
+{
+ u8 lat;
+
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+
+ if (lat < 16)
+ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+ else if (lat > pcibios_max_latency)
+ lat = pcibios_max_latency;
+ else
+ return;
+
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ unsigned long prot;
+
+ /* Leave vm_pgoff as-is, the PCI space address is the physical
+ * address on this platform.
+ */
+ vma->vm_flags |= VM_LOCKED | VM_IO;
+
+ prot = pgprot_val(vma->vm_page_prot);
+ prot &= ~_PAGE_CACHE;
+ vma->vm_page_prot = __pgprot(prot);
+
+ /* Write-combine setting is ignored */
+ if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
+
+ return 0;
+}
diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h
new file mode 100644
index 00000000000..84634fa3bce
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.h
@@ -0,0 +1,82 @@
+/* ASB2305 Arch-specific PCI declarations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * Derived from: arch/i386/kernel/pci-i386.h: (c) 1999 Martin Mares <mj@ucw.cz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef _PCI_ASB2305_H
+#define _PCI_ASB2305_H
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#define PCI_PROBE_BIOS 1
+#define PCI_PROBE_CONF1 2
+#define PCI_PROBE_CONF2 4
+#define PCI_NO_SORT 0x100
+#define PCI_BIOS_SORT 0x200
+#define PCI_NO_CHECKS 0x400
+#define PCI_ASSIGN_ROMS 0x1000
+#define PCI_BIOS_IRQ_SCAN 0x2000
+
+extern unsigned int pci_probe;
+
+/* pci-asb2305.c */
+
+extern unsigned int pcibios_max_latency;
+
+extern void pcibios_resource_survey(void);
+extern int pcibios_enable_resources(struct pci_dev *dev, int mask);
+
+/* pci.c */
+
+extern int pcibios_last_bus;
+extern struct pci_bus *pci_root_bus;
+extern struct pci_ops *pci_root_ops;
+
+extern struct irq_routing_table *pcibios_get_irq_routing_table(void);
+extern int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
+
+/* pci-irq.c */
+
+struct irq_info {
+ u8 bus, devfn; /* Bus, device and function */
+ struct {
+ u8 link; /* IRQ line ID, chipset dependent,
+ * 0=not routed */
+ u16 bitmap; /* Available IRQs */
+ } __attribute__((packed)) irq[4];
+ u8 slot; /* Slot number, 0=onboard */
+ u8 rfu;
+} __attribute__((packed));
+
+struct irq_routing_table {
+ u32 signature; /* PIRQ_SIGNATURE should be here */
+ u16 version; /* PIRQ_VERSION */
+ u16 size; /* Table size in bytes */
+ u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
+ u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
+ u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
+ u32 miniport_data; /* Crap */
+ u8 rfu[11];
+ u8 checksum; /* Modulo 256 checksum must give zero */
+ struct irq_info slots[0];
+} __attribute__((packed));
+
+extern unsigned int pcibios_irq_mask;
+
+extern void pcibios_irq_init(void);
+extern void pcibios_fixup_irqs(void);
+extern void pcibios_enable_irq(struct pci_dev *dev);
+
+#endif /* PCI_ASB2305_H */
diff --git a/arch/mn10300/unit-asb2305/pci-iomap.c b/arch/mn10300/unit-asb2305/pci-iomap.c
new file mode 100644
index 00000000000..dbceae4307d
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/pci-iomap.c
@@ -0,0 +1,31 @@
+/* ASB2305 PCI I/O mapping handler
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+
+/*
+ * Create a virtual mapping cookie for a PCI BAR (memory or IO)
+ */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+ unsigned long start = pci_resource_start(dev, bar);
+ unsigned long len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
+ return NULL;
+
+ if ((flags & IORESOURCE_IO) || (flags & IORESOURCE_MEM))
+ return (void __iomem *) start;
+
+ return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
diff --git a/arch/mn10300/unit-asb2305/pci-irq.c b/arch/mn10300/unit-asb2305/pci-irq.c
new file mode 100644
index 00000000000..58cfb44f0ac
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/pci-irq.c
@@ -0,0 +1,51 @@
+/* PCI IRQ routing on the MN103E010 based ASB2305
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ *
+ * This is simple: All PCI interrupts route through the CPU's XIRQ1 pin [IRQ 35]
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include "pci-asb2305.h"
+
+void __init pcibios_irq_init(void)
+{
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+ struct pci_dev *dev = NULL;
+ u8 line, pin;
+
+ while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (pin) {
+ dev->irq = XIRQ1;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+ dev->irq);
+ }
+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
+ }
+}
+
+void __init pcibios_penalize_isa_irq(int irq)
+{
+}
+
+void pcibios_enable_irq(struct pci_dev *dev)
+{
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+}
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c
new file mode 100644
index 00000000000..1a86425fec4
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/pci.c
@@ -0,0 +1,545 @@
+/* ASB2305 PCI support
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * Derived from arch/i386/kernel/pci-pc.c
+ * (c) 1999--2000 Martin Mares <mj@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include "pci-asb2305.h"
+
+unsigned int pci_probe = 1;
+
+int pcibios_last_bus = -1;
+struct pci_bus *pci_root_bus;
+struct pci_ops *pci_root_ops;
+
+/*
+ * Functions for accessing PCI configuration space
+ */
+
+#define CONFIG_CMD(bus, devfn, where) \
+ (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+#define MEM_PAGING_REG (*(volatile __u32 *) 0xBFFFFFF4)
+#define CONFIG_ADDRESS (*(volatile __u32 *) 0xBFFFFFF8)
+#define CONFIG_DATAL(X) (*(volatile __u32 *) 0xBFFFFFFC)
+#define CONFIG_DATAW(X) (*(volatile __u16 *) (0xBFFFFFFC + ((X) & 2)))
+#define CONFIG_DATAB(X) (*(volatile __u8 *) (0xBFFFFFFC + ((X) & 3)))
+
+#define BRIDGEREGB(X) (*(volatile __u8 *) (0xBE040000 + (X)))
+#define BRIDGEREGW(X) (*(volatile __u16 *) (0xBE040000 + (X)))
+#define BRIDGEREGL(X) (*(volatile __u32 *) (0xBE040000 + (X)))
+
+static inline int __query(const struct pci_bus *bus, unsigned int devfn)
+{
+#if 0
+ return bus->number == 0 && (devfn == PCI_DEVFN(0, 0));
+ return bus->number == 1;
+ return bus->number == 0 &&
+ (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(3, 0));
+#endif
+ return 1;
+}
+
+/*
+ * translate Linuxcentric addresses to PCI bus addresses
+ */
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ if (res->flags & IORESOURCE_IO) {
+ region->start = (res->start & 0x00ffffff);
+ region->end = (res->end & 0x00ffffff);
+ }
+
+ if (res->flags & IORESOURCE_MEM) {
+ region->start = (res->start & 0x03ffffff) | MEM_PAGING_REG;
+ region->end = (res->end & 0x03ffffff) | MEM_PAGING_REG;
+ }
+
+#if 0
+ printk(KERN_DEBUG "RES->BUS: %lx-%lx => %lx-%lx\n",
+ res->start, res->end, region->start, region->end);
+#endif
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+/*
+ * translate PCI bus addresses to Linuxcentric addresses
+ */
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ if (res->flags & IORESOURCE_IO) {
+ res->start = (region->start & 0x00ffffff) | 0xbe000000;
+ res->end = (region->end & 0x00ffffff) | 0xbe000000;
+ }
+
+ if (res->flags & IORESOURCE_MEM) {
+ res->start = (region->start & 0x03ffffff) | 0xb8000000;
+ res->end = (region->end & 0x03ffffff) | 0xb8000000;
+ }
+
+#if 0
+ printk(KERN_INFO "BUS->RES: %lx-%lx => %lx-%lx\n",
+ region->start, region->end, res->start, res->end);
+#endif
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
+/*
+ *
+ */
+static int pci_ampci_read_config_byte(struct pci_bus *bus, unsigned int devfn,
+ int where, u32 *_value)
+{
+ u32 rawval, value;
+
+ if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+ value = BRIDGEREGB(where);
+ __pcbdebug("=> %02hx", &BRIDGEREGL(where), value);
+ } else {
+ CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+ rawval = CONFIG_ADDRESS;
+ value = CONFIG_DATAB(where);
+ if (__query(bus, devfn))
+ __pcidebug("=> %02hx", bus, devfn, where, value);
+ }
+
+ *_value = value;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_read_config_word(struct pci_bus *bus, unsigned int devfn,
+ int where, u32 *_value)
+{
+ u32 rawval, value;
+
+ if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+ value = BRIDGEREGW(where);
+ __pcbdebug("=> %04hx", &BRIDGEREGL(where), value);
+ } else {
+ CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+ rawval = CONFIG_ADDRESS;
+ value = CONFIG_DATAW(where);
+ if (__query(bus, devfn))
+ __pcidebug("=> %04hx", bus, devfn, where, value);
+ }
+
+ *_value = value;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
+ int where, u32 *_value)
+{
+ u32 rawval, value;
+
+ if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+ value = BRIDGEREGL(where);
+ __pcbdebug("=> %08x", &BRIDGEREGL(where), value);
+ } else {
+ CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+ rawval = CONFIG_ADDRESS;
+ value = CONFIG_DATAL(where);
+ if (__query(bus, devfn))
+ __pcidebug("=> %08x", bus, devfn, where, value);
+ }
+
+ *_value = value;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_write_config_byte(struct pci_bus *bus, unsigned int devfn,
+ int where, u8 value)
+{
+ u32 rawval;
+
+ if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+ __pcbdebug("<= %02x", &BRIDGEREGB(where), value);
+ BRIDGEREGB(where) = value;
+ } else {
+ if (bus->number == 0 &&
+ (devfn == PCI_DEVFN(2, 0) && devfn == PCI_DEVFN(3, 0))
+ )
+ __pcidebug("<= %02x", bus, devfn, where, value);
+ CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+ rawval = CONFIG_ADDRESS;
+ CONFIG_DATAB(where) = value;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_write_config_word(struct pci_bus *bus, unsigned int devfn,
+ int where, u16 value)
+{
+ u32 rawval;
+
+ if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+ __pcbdebug("<= %04hx", &BRIDGEREGW(where), value);
+ BRIDGEREGW(where) = value;
+ } else {
+ if (__query(bus, devfn))
+ __pcidebug("<= %04hx", bus, devfn, where, value);
+ CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+ rawval = CONFIG_ADDRESS;
+ CONFIG_DATAW(where) = value;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
+ int where, u32 value)
+{
+ u32 rawval;
+
+ if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
+ __pcbdebug("<= %08x", &BRIDGEREGL(where), value);
+ BRIDGEREGL(where) = value;
+ } else {
+ if (__query(bus, devfn))
+ __pcidebug("<= %08x", bus, devfn, where, value);
+ CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
+ rawval = CONFIG_ADDRESS;
+ CONFIG_DATAL(where) = value;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_ampci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ switch (size) {
+ case 1:
+ return pci_ampci_read_config_byte(bus, devfn, where, val);
+ case 2:
+ return pci_ampci_read_config_word(bus, devfn, where, val);
+ case 4:
+ return pci_ampci_read_config_dword(bus, devfn, where, val);
+ default:
+ BUG();
+ return -EOPNOTSUPP;
+ }
+}
+
+static int pci_ampci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ switch (size) {
+ case 1:
+ return pci_ampci_write_config_byte(bus, devfn, where, val);
+ case 2:
+ return pci_ampci_write_config_word(bus, devfn, where, val);
+ case 4:
+ return pci_ampci_write_config_dword(bus, devfn, where, val);
+ default:
+ BUG();
+ return -EOPNOTSUPP;
+ }
+}
+
+static struct pci_ops pci_direct_ampci = {
+ pci_ampci_read_config,
+ pci_ampci_write_config,
+};
+
+/*
+ * Before we decide to use direct hardware access mechanisms, we try to do some
+ * trivial checks to ensure it at least _seems_ to be working -- we just test
+ * whether bus 00 contains a host bridge (this is similar to checking
+ * techniques used in XFree86, but ours should be more reliable since we
+ * attempt to make use of direct access hints provided by the PCI BIOS).
+ *
+ * This should be close to trivial, but it isn't, because there are buggy
+ * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
+ */
+static int __init pci_sanity_check(struct pci_ops *o)
+{
+ struct pci_bus bus; /* Fake bus and device */
+ u32 x;
+
+ bus.number = 0;
+
+ if ((!o->read(&bus, 0, PCI_CLASS_DEVICE, 2, &x) &&
+ (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) ||
+ (!o->read(&bus, 0, PCI_VENDOR_ID, 2, &x) &&
+ (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)))
+ return 1;
+
+ printk(KERN_ERROR "PCI: Sanity check failed\n");
+ return 0;
+}
+
+static int __init pci_check_direct(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ /*
+ * Check if access works.
+ */
+ if (pci_sanity_check(&pci_direct_ampci)) {
+ local_irq_restore(flags);
+ printk(KERN_INFO "PCI: Using configuration ampci\n");
+ request_mem_region(0xBE040000, 256, "AMPCI bridge");
+ request_mem_region(0xBFFFFFF4, 12, "PCI ampci");
+ return 0;
+ }
+
+ local_irq_restore(flags);
+ return -ENODEV;
+}
+
+static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
+{
+ unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM;
+ struct resource *devr = &dev->resource[idx];
+
+ if (dev->bus) {
+ for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
+ struct resource *busr = dev->bus->resource[i];
+
+ if (!busr || (busr->flags ^ devr->flags) & type_mask)
+ continue;
+
+ if (devr->start &&
+ devr->start >= busr->start &&
+ devr->end <= busr->end)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
+{
+ struct pci_bus_region region;
+ int i;
+ int limit;
+
+ if (dev->bus->number != 0)
+ return;
+
+ limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ?
+ PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES;
+
+ for (i = 0; i < limit; i++) {
+ if (!dev->resource[i].flags)
+ continue;
+
+ region.start = dev->resource[i].start;
+ region.end = dev->resource[i].end;
+ pcibios_bus_to_resource(dev, &dev->resource[i], &region);
+ if (is_valid_resource(dev, i))
+ pci_claim_resource(dev, i);
+ }
+}
+
+/*
+ * Called after each bus is probed, but before its children
+ * are examined.
+ */
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+
+ if (bus->self) {
+ pci_read_bridge_bases(bus);
+ pcibios_fixup_device_resources(bus->self);
+ }
+
+ list_for_each_entry(dev, &bus->devices, bus_list)
+ pcibios_fixup_device_resources(dev);
+}
+
+/*
+ * Initialization. Try all known PCI access methods. Note that we support
+ * using both PCI BIOS and direct access: in such cases, we use I/O ports
+ * to access config space, but we still keep BIOS order of cards to be
+ * compatible with 2.0.X. This should go away some day.
+ */
+static int __init pcibios_init(void)
+{
+ ioport_resource.start = 0xA0000000;
+ ioport_resource.end = 0xDFFFFFFF;
+ iomem_resource.start = 0xA0000000;
+ iomem_resource.end = 0xDFFFFFFF;
+
+ if (!pci_probe)
+ return 0;
+
+ if (pci_check_direct() < 0) {
+ printk(KERN_WARNING "PCI: No PCI bus detected\n");
+ return 0;
+ }
+
+ printk(KERN_INFO "PCI: Probing PCI hardware [mempage %08x]\n",
+ MEM_PAGING_REG);
+
+ {
+#if 0
+ static struct pci_bus am33_root_bus = {
+ .children = LIST_HEAD_INIT(am33_root_bus.children),
+ .devices = LIST_HEAD_INIT(am33_root_bus.devices),
+ .number = 0,
+ .secondary = 0,
+ .resource = { &ioport_resource, &iomem_resource },
+ };
+
+ am33_root_bus.ops = pci_root_ops;
+ list_add_tail(&am33_root_bus.node, &pci_root_buses);
+
+ am33_root_bus.subordinate = pci_do_scan_bus(0);
+
+ pci_root_bus = &am33_root_bus;
+#else
+ pci_root_bus = pci_scan_bus(0, &pci_direct_ampci, NULL);
+#endif
+ }
+
+ pcibios_irq_init();
+ pcibios_fixup_irqs();
+#if 0
+ pcibios_resource_survey();
+#endif
+ return 0;
+}
+
+arch_initcall(pcibios_init);
+
+char *__init pcibios_setup(char *str)
+{
+ if (!strcmp(str, "off")) {
+ pci_probe = 0;
+ return NULL;
+
+ } else if (!strncmp(str, "lastbus=", 8)) {
+ pcibios_last_bus = simple_strtol(str+8, NULL, 0);
+ return NULL;
+ }
+
+ return str;
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+ int err;
+
+ err = pcibios_enable_resources(dev, mask);
+ if (err == 0)
+ pcibios_enable_irq(dev);
+ return err;
+}
+
+/*
+ * disable the ethernet chipset
+ */
+static void __init unit_disable_pcnet(struct pci_bus *bus, struct pci_ops *o)
+{
+ u32 x;
+
+ bus->number = 0;
+
+ o->read (bus, PCI_DEVFN(2, 0), PCI_COMMAND, 2, &x);
+ x |= PCI_COMMAND_MASTER |
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
+ o->write(bus, PCI_DEVFN(2, 0), PCI_COMMAND, 2, x);
+ o->read (bus, PCI_DEVFN(2, 0), PCI_COMMAND, 2, &x);
+ o->write(bus, PCI_DEVFN(2, 0), PCI_BASE_ADDRESS_0, 4, 0x00030001);
+ o->read (bus, PCI_DEVFN(2, 0), PCI_BASE_ADDRESS_0, 4, &x);
+
+#define RDP (*(volatile u32 *) 0xBE030010)
+#define RAP (*(volatile u32 *) 0xBE030014)
+#define __set_RAP(X) do { RAP = (X); x = RAP; } while (0)
+#define __set_RDP(X) do { RDP = (X); x = RDP; } while (0)
+#define __get_RDP() ({ RDP & 0xffff; })
+
+ __set_RAP(0);
+ __set_RDP(0x0004); /* CSR0 = STOP */
+
+ __set_RAP(88); /* check CSR88 indicates an Am79C973 */
+ BUG_ON(__get_RDP() != 0x5003);
+
+ for (x = 0; x < 100; x++)
+ asm volatile("nop");
+
+ __set_RDP(0x0004); /* CSR0 = STOP */
+}
+
+/*
+ * initialise the unit hardware
+ */
+asmlinkage void __init unit_pci_init(void)
+{
+ struct pci_bus bus; /* Fake bus and device */
+ struct pci_ops *o = &pci_direct_ampci;
+ u32 x;
+
+ set_intr_level(XIRQ1, GxICR_LEVEL_3);
+
+ memset(&bus, 0, sizeof(bus));
+
+ MEM_PAGING_REG = 0xE8000000;
+
+ /* we need to set up the bridge _now_ or we won't be able to access the
+ * PCI config registers
+ */
+ BRIDGEREGW(PCI_COMMAND) |=
+ PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
+ PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER;
+ BRIDGEREGW(PCI_STATUS) = 0xF800;
+ BRIDGEREGB(PCI_LATENCY_TIMER) = 0x10;
+ BRIDGEREGL(PCI_BASE_ADDRESS_0) = 0x80000000;
+ BRIDGEREGB(PCI_INTERRUPT_LINE) = 1;
+ BRIDGEREGL(0x48) = 0x98000000; /* AMPCI base addr */
+ BRIDGEREGB(0x41) = 0x00; /* secondary bus
+ * number */
+ BRIDGEREGB(0x42) = 0x01; /* subordinate bus
+ * number */
+ BRIDGEREGB(0x44) = 0x01;
+ BRIDGEREGL(0x50) = 0x00000001;
+ BRIDGEREGL(0x58) = 0x00001002;
+ BRIDGEREGL(0x5C) = 0x00000011;
+
+ /* we also need to set up the PCI-PCI bridge */
+ bus.number = 0;
+
+ /* IO: 0x00000000-0x00020000 */
+ o->read (&bus, PCI_DEVFN(3, 0), PCI_COMMAND, 2, &x);
+ x |= PCI_COMMAND_MASTER |
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
+ o->write(&bus, PCI_DEVFN(3, 0), PCI_COMMAND, 2, x);
+
+ o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE, 1, &x);
+ o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16, 4, &x);
+ o->read (&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE, 4, &x);
+ o->read (&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE, 4, &x);
+
+ o->write(&bus, PCI_DEVFN(3, 0), PCI_IO_BASE, 1, 0x01);
+ o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE, 1, &x);
+ o->write(&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16, 4, 0x00020000);
+ o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16, 4, &x);
+ o->write(&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE, 4, 0xEBB0EA00);
+ o->read (&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE, 4, &x);
+ o->write(&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE, 4, 0xE9F0E800);
+ o->read (&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE, 4, &x);
+
+ unit_disable_pcnet(&bus, o);
+}
diff --git a/arch/mn10300/unit-asb2305/unit-init.c b/arch/mn10300/unit-asb2305/unit-init.c
new file mode 100644
index 00000000000..6a352414a35
--- /dev/null
+++ b/arch/mn10300/unit-asb2305/unit-init.c
@@ -0,0 +1,61 @@
+/* ASB2305 Initialisation
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/cpu/intctl-regs.h>
+#include <asm/cpu/rtc-regs.h>
+#include <asm/cpu/serial-regs.h>
+#include <asm/unit/serial.h>
+
+/*
+ * initialise some of the unit hardware before gdbstub is set up
+ */
+asmlinkage void __init unit_init(void)
+{
+#ifndef CONFIG_GDBSTUB_ON_TTYSx
+ /* set the 16550 interrupt line to level 3 if not being used for GDB */
+ set_intr_level(XIRQ0, GxICR_LEVEL_3);
+#endif
+}
+
+/*
+ * initialise the rest of the unit hardware after gdbstub is ready
+ */
+void __init unit_setup(void)
+{
+#ifdef CONFIG_PCI
+ unit_pci_init();
+#endif
+}
+
+/*
+ * initialise the external interrupts used by a unit of this type
+ */
+void __init unit_init_IRQ(void)
+{
+ unsigned int extnum;
+
+ for (extnum = 0; extnum < NR_XIRQS; extnum++) {
+ switch (GET_XIRQ_TRIGGER(extnum)) {
+ case XIRQ_TRIGGER_HILEVEL:
+ case XIRQ_TRIGGER_LOWLEVEL:
+ set_irq_handler(XIRQ2IRQ(extnum), handle_level_irq);
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 028d8a0fdbf..bc7a19da624 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -7,6 +7,7 @@ mainmenu "Linux/PA-RISC Kernel Configuration"
config PARISC
def_bool y
+ select HAVE_IDE
select HAVE_OPROFILE
help
The PA-RISC microprocessor is designed by Hewlett-Packard and used
@@ -75,6 +76,9 @@ config IRQ_PER_CPU
bool
default y
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
# unless you want to implement ACPI on PA-RISC ... ;-)
config PM
bool
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
index 9166bd11726..bc989e522a0 100644
--- a/arch/parisc/Kconfig.debug
+++ b/arch/parisc/Kconfig.debug
@@ -2,15 +2,6 @@ menu "Kernel hacking"
source "lib/Kconfig.debug"
-config DEBUG_RWLOCK
- bool "Read-write spinlock debugging"
- depends on DEBUG_KERNEL && SMP
- help
- If you say Y here then read-write lock processing will count how many
- times it has tried to get the lock and issue an error message after
- too many attempts. If you suspect a rwlock problem or a kernel
- hacker asks for this option then say Y. Otherwise say N.
-
config DEBUG_RODATA
bool "Write protect kernel read-only data structures"
depends on DEBUG_KERNEL
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
index ea071218a3e..ddacc72e38f 100644
--- a/arch/parisc/configs/a500_defconfig
+++ b/arch/parisc/configs/a500_defconfig
@@ -1050,7 +1050,6 @@ CONFIG_SCHED_DEBUG=y
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_FAULT_INJECTION is not set
-# CONFIG_DEBUG_RWLOCK is not set
# CONFIG_DEBUG_RODATA is not set
#
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
index 3e025df2dc8..0c5b9dabb47 100644
--- a/arch/parisc/hpux/sys_hpux.c
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -219,10 +219,10 @@ asmlinkage long hpux_statfs(const char __user *path,
error = user_path_walk(path, &nd);
if (!error) {
struct hpux_statfs tmp;
- error = vfs_statfs_hpux(nd.dentry, &tmp);
+ error = vfs_statfs_hpux(nd.path.dentry, &tmp);
if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
error = -EFAULT;
- path_release(&nd);
+ path_put(&nd.path);
}
return error;
}
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index c44b8c51f5d..39e7c5a5946 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -190,7 +190,7 @@ c_stop (struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index aa875fa4348..eb80f5e33d7 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -315,11 +315,13 @@ static void __init setup_bootmem(void)
#define PDC_CONSOLE_IO_IODC_SIZE 32768
reserve_bootmem_node(NODE_DATA(0), 0UL,
- (unsigned long)(PAGE0->mem_free + PDC_CONSOLE_IO_IODC_SIZE));
+ (unsigned long)(PAGE0->mem_free +
+ PDC_CONSOLE_IO_IODC_SIZE), BOOTMEM_DEFAULT);
reserve_bootmem_node(NODE_DATA(0), __pa((unsigned long)_text),
- (unsigned long)(_end - _text));
+ (unsigned long)(_end - _text), BOOTMEM_DEFAULT);
reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
- ((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT));
+ ((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT),
+ BOOTMEM_DEFAULT);
#ifndef CONFIG_DISCONTIGMEM
@@ -328,7 +330,8 @@ static void __init setup_bootmem(void)
for (i = 0; i < npmem_holes; i++) {
reserve_bootmem_node(NODE_DATA(0),
(pmem_holes[i].start_pfn << PAGE_SHIFT),
- (pmem_holes[i].pages << PAGE_SHIFT));
+ (pmem_holes[i].pages << PAGE_SHIFT),
+ BOOTMEM_DEFAULT);
}
#endif
@@ -346,7 +349,8 @@ static void __init setup_bootmem(void)
initrd_below_start_ok = 1;
printk(KERN_INFO "initrd: reserving %08lx-%08lx (mem_max %08lx)\n", __pa(initrd_start), __pa(initrd_start) + initrd_reserve, mem_max);
- reserve_bootmem_node(NODE_DATA(0),__pa(initrd_start), initrd_reserve);
+ reserve_bootmem_node(NODE_DATA(0), __pa(initrd_start),
+ initrd_reserve, BOOTMEM_DEFAULT);
}
}
#endif
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index b94d4502a47..5b8d8382b76 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -87,6 +87,7 @@ config ARCH_NO_VIRT_TO_BUS
config PPC
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
select HAVE_KPROBES
@@ -97,6 +98,7 @@ config EARLY_PRINTK
config COMPAT
bool
default y if PPC64
+ select COMPAT_BINFMT_ELF
config SYSVIPC_COMPAT
bool
@@ -256,6 +258,9 @@ config IOMMU_VMERGE
Most drivers don't have this problem; it is safe to say Y here.
+config IOMMU_HELPER
+ def_bool PPC64
+
config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
@@ -268,6 +273,12 @@ config HOTPLUG_CPU
config ARCH_ENABLE_MEMORY_HOTPLUG
def_bool y
+config ARCH_HAS_WALK_MEMORY
+ def_bool y
+
+config ARCH_ENABLE_MEMORY_HOTREMOVE
+ def_bool y
+
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
depends on (PPC_PRPMC2800 || PPC_MULTIPLATFORM) && EXPERIMENTAL
@@ -431,29 +442,6 @@ config SECCOMP
If unsure, say Y. Only embedded should say N here.
-config WANT_DEVICE_TREE
- bool
- default n
-
-config DEVICE_TREE
- string "Static device tree source file"
- depends on WANT_DEVICE_TREE
- help
- This specifies the device tree source (.dts) file to be
- compiled and included when building the bootwrapper. If a
- relative filename is given, then it will be relative to
- arch/powerpc/boot/dts. If you are not using the bootwrapper,
- or do not need to build a dts into the bootwrapper, this
- field is ignored.
-
- For example, this is required when building a cuImage target
- for an older U-Boot, which cannot pass a device tree itself.
- Such a kernel will not work with a newer U-Boot that tries to
- pass a device tree (unless you tell it not to). If your U-Boot
- does not mention a device tree in "help bootm", then use the
- cuImage target and specify a device tree here. Otherwise, use
- the uImage target and leave this field blank.
-
endmenu
config ISA_DMA_API
@@ -509,7 +497,7 @@ config PCI
bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
|| PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
|| PPC_PS3 || 44x
- default y if !40x && !CPM2 && !8xx && !PPC_83xx \
+ default y if !40x && !CPM2 && !8xx && !PPC_MPC512x && !PPC_83xx \
&& !PPC_85xx && !PPC_86xx
default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
default PCI_QSPAN if !4xx && !CPM2 && 8xx
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index f70df9b64f8..6845482f009 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -151,14 +151,11 @@ core-$(CONFIG_XMON) += arch/powerpc/xmon/
drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
# Default to zImage, override when needed
-defaultimage-y := zImage
-defaultimage-$(CONFIG_DEFAULT_UIMAGE) := uImage
-KBUILD_IMAGE := $(defaultimage-y)
-all: $(KBUILD_IMAGE)
+all: zImage
CPPFLAGS_vmlinux.lds := -Upowerpc
-BOOT_TARGETS = zImage zImage.initrd uImage
+BOOT_TARGETS = zImage zImage.initrd uImage treeImage.% cuImage.%
PHONY += $(BOOT_TARGETS)
@@ -180,7 +177,7 @@ define archhelp
endef
install: vdso_install
- $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
+ $(Q)$(MAKE) $(build)=$(boot) install
vdso_install:
ifeq ($(CONFIG_PPC64),y)
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 122a2707899..63d07ccbb9d 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -60,8 +60,9 @@ src-wlib := string.S crt0.S stdio.c main.c \
src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c \
cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
- cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c cuboot-bamboo.c \
- fixed-head.S ep88xc.c cuboot-hpc2.c ep405.c cuboot-taishan.c \
+ cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c \
+ cuboot-bamboo.c cuboot-mpc7448hpc2.c cuboot-taishan.c \
+ fixed-head.S ep88xc.c ep405.c \
cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
cuboot-warp.c cuboot-85xx-cpm2.c
src-boot := $(src-wlib) $(src-plat) empty.c
@@ -123,6 +124,8 @@ targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds
+dtstree := $(srctree)/$(src)/dts
+
wrapper :=$(srctree)/$(src)/wrapper
wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree dtc) \
$(wrapper) FORCE
@@ -144,6 +147,8 @@ HOSTCFLAGS += -I$(src)/dtc-src/ -I$(src)/libfdt/
targets += dtc-src/dtc-parser.tab.c
targets += dtc-src/dtc-lexer.lex.c
+clean-files += dtc-src/dtc-parser.tab.h
+
ifdef DTC_GENPARSER
BISON = bison
FLEX = flex
@@ -181,7 +186,7 @@ quiet_cmd_wrap = WRAP $@
image-$(CONFIG_PPC_PSERIES) += zImage.pseries
image-$(CONFIG_PPC_MAPLE) += zImage.pseries
image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries
-image-$(CONFIG_PPC_PS3) += zImage.ps3
+image-$(CONFIG_PPC_PS3) += zImage-dtb.ps3
image-$(CONFIG_PPC_CELLEB) += zImage.pseries
image-$(CONFIG_PPC_CHRP) += zImage.chrp
image-$(CONFIG_PPC_EFIKA) += zImage.chrp
@@ -191,33 +196,69 @@ image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800
image-$(CONFIG_PPC_ISERIES) += zImage.iseries
image-$(CONFIG_DEFAULT_UIMAGE) += uImage
-ifneq ($(CONFIG_DEVICE_TREE),"")
-image-$(CONFIG_PPC_8xx) += cuImage.8xx
-image-$(CONFIG_PPC_EP88XC) += zImage.ep88xc
-image-$(CONFIG_EP405) += zImage.ep405
-image-$(CONFIG_8260) += cuImage.pq2
-image-$(CONFIG_EP8248E) += zImage.ep8248e
-image-$(CONFIG_PPC_MPC52xx) += cuImage.52xx
-image-$(CONFIG_STORCENTER) += cuImage.824x
-image-$(CONFIG_PPC_83xx) += cuImage.83xx
-image-$(CONFIG_PPC_85xx) += cuImage.85xx
-ifeq ($(CONFIG_CPM2),y)
-image-$(CONFIG_PPC_85xx) += cuImage.85xx-cpm2
-endif
-image-$(CONFIG_MPC7448HPC2) += cuImage.hpc2
+#
+# Targets which embed a device tree blob
+#
+# Theses are default targets to build images which embed device tree blobs.
+# They are only required on boards which do not have FDT support in firmware.
+# Boards with newish u-boot firmare can use the uImage target above
+#
+
+# Board ports in arch/powerpc/platform/40x/Kconfig
+image-$(CONFIG_EP405) += zImage-dtb.ep405
+image-$(CONFIG_WALNUT) += treeImage.walnut
+
+# Board ports in arch/powerpc/platform/44x/Kconfig
image-$(CONFIG_EBONY) += treeImage.ebony cuImage.ebony
image-$(CONFIG_BAMBOO) += treeImage.bamboo cuImage.bamboo
image-$(CONFIG_SEQUOIA) += cuImage.sequoia
image-$(CONFIG_RAINIER) += cuImage.rainier
-image-$(CONFIG_WALNUT) += treeImage.walnut
image-$(CONFIG_TAISHAN) += cuImage.taishan
image-$(CONFIG_KATMAI) += cuImage.katmai
image-$(CONFIG_WARP) += cuImage.warp
-endif
-ifneq ($(CONFIG_REDBOOT),"")
-image-$(CONFIG_PPC_8xx) += zImage.redboot-8xx
-endif
+# Board ports in arch/powerpc/platform/8xx/Kconfig
+image-$(CONFIG_PPC_MPC86XADS) += cuImage.mpc866ads
+image-$(CONFIG_PPC_MPC885ADS) += cuImage.mpc885ads
+image-$(CONFIG_PPC_EP88XC) += zImage-dtb.ep88xc
+image-$(CONFIG_PPC_ADDER875) += cuImage.adder875-uboot \
+ zImage-dtb.adder875-redboot
+
+# Board ports in arch/powerpc/platform/52xx/Kconfig
+image-$(CONFIG_PPC_LITE5200) += cuImage.lite5200 cuImage.lite5200b
+
+# Board ports in arch/powerpc/platform/82xx/Kconfig
+image-$(CONFIG_MPC8272_ADS) += cuImage.mpc8272ads
+image-$(CONFIG_PQ2FADS) += cuImage.pq2fads
+image-$(CONFIG_EP8248E) += zImage-dtb.ep8248e
+
+# Board ports in arch/powerpc/platform/83xx/Kconfig
+image-$(CONFIG_MPC832x_MDS) += cuImage.mpc832x_mds
+image-$(CONFIG_MPC832x_RDB) += cuImage.mpc832x_rdb
+image-$(CONFIG_MPC834x_ITX) += cuImage.mpc8349emitx \
+ cuImage.mpc8349emitxgp
+image-$(CONFIG_MPC834x_MDS) += cuImage.mpc834x_mds
+image-$(CONFIG_MPC836x_MDS) += cuImage.mpc836x_mds
+
+# Board ports in arch/powerpc/platform/85xx/Kconfig
+image-$(CONFIG_MPC8540_ADS) += cuImage.mpc8540ads
+image-$(CONFIG_MPC8560_ADS) += cuImage.mpc8560ads
+image-$(CONFIG_MPC85xx_CDS) += cuImage.mpc8541cds \
+ cuImage.mpc8548cds \
+ cuImage.mpc8555cds
+image-$(CONFIG_MPC85xx_MDS) += cuImage.mpc8568mds
+image-$(CONFIG_MPC85xx_DS) += cuImage.mpc8544ds \
+ cuImage.mpc8572ds
+image-$(CONFIG_TQM8540) += cuImage.tqm8540
+image-$(CONFIG_TQM8541) += cuImage.tqm8541
+image-$(CONFIG_TQM8555) += cuImage.tqm8555
+image-$(CONFIG_TQM8560) += cuImage.tqm8560
+image-$(CONFIG_SBC8548) += cuImage.tqm8548
+image-$(CONFIG_SBC8560) += cuImage.tqm8560
+
+# Board ports in arch/powerpc/platform/embedded6xx/Kconfig
+image-$(CONFIG_STORCENTER) += cuImage.storcenter
+image-$(CONFIG_MPC7448HPC2) += cuImage.mpc7448hpc2
# For 32-bit powermacs, build the COFF and miboot images
# as well as the ELF images.
@@ -233,24 +274,20 @@ targets += $(image-y) $(initrd-y)
$(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz
-# If CONFIG_WANT_DEVICE_TREE is set and CONFIG_DEVICE_TREE isn't an
-# empty string, define 'dts' to be path to the dts
-# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them
-ifeq ($(CONFIG_WANT_DEVICE_TREE),y)
-ifneq ($(CONFIG_DEVICE_TREE),"")
-dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\
- ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%)
-endif
-endif
-
# Don't put the ramdisk on the pattern rule; when its missing make will try
# the pattern rule with less dependencies that also matches (even with the
# hard dependency listed).
-$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(dts)
- $(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz)
+$(obj)/zImage.initrd.%: vmlinux $(wrapperbits)
+ $(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz)
-$(obj)/zImage.%: vmlinux $(wrapperbits) $(dts)
- $(call if_changed,wrap,$*,$(dts))
+$(obj)/zImage.%: vmlinux $(wrapperbits)
+ $(call if_changed,wrap,$*)
+
+$(obj)/zImage-dtb.initrd.%: vmlinux $(wrapperbits) $(dtstree)/%.dts
+ $(call if_changed,wrap,$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz)
+
+$(obj)/zImage-dtb.%: vmlinux $(wrapperbits) $(dtstree)/%.dts
+ $(call if_changed,wrap,$*,$(dtstree)/$*.dts)
# This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
# prefix
@@ -260,24 +297,17 @@ $(obj)/vmlinux.strip: vmlinux
$(obj)/zImage.iseries: vmlinux
$(STRIP) -s -R .comment $< -o $@
-$(obj)/zImage.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts
- $(STRIP) -s -R .comment $< -o vmlinux.strip
- $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
-
-$(obj)/zImage.initrd.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz
- $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz)
-
$(obj)/uImage: vmlinux $(wrapperbits)
$(call if_changed,wrap,uboot)
-$(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits)
- $(call if_changed,wrap,cuboot-$*,$(dts))
+$(obj)/cuImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+ $(call if_changed,wrap,cuboot-$*,$(dtstree)/$*.dts)
-$(obj)/treeImage.initrd.%: vmlinux $(dts) $(wrapperbits)
- $(call if_changed,wrap,treeboot-$*,$(dts),,$(obj)/ramdisk.image.gz)
+$(obj)/treeImage.initrd.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+ $(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts,,$(obj)/ramdisk.image.gz)
-$(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits)
- $(call if_changed,wrap,treeboot-$*,$(dts))
+$(obj)/treeImage.%: vmlinux $(dtstree)/%.dts $(wrapperbits)
+ $(call if_changed,wrap,treeboot-$*,$(dtstree)/$*.dts)
# If there isn't a platform selected then just strip the vmlinux.
ifeq (,$(image-y))
diff --git a/arch/powerpc/boot/cuboot-hpc2.c b/arch/powerpc/boot/cuboot-mpc7448hpc2.c
index 1b8953259d7..1b8953259d7 100644
--- a/arch/powerpc/boot/cuboot-hpc2.c
+++ b/arch/powerpc/boot/cuboot-mpc7448hpc2.c
diff --git a/arch/powerpc/boot/dts/adder875-redboot.dts b/arch/powerpc/boot/dts/adder875-redboot.dts
index 930bfb3894e..28e9cd3d7a2 100644
--- a/arch/powerpc/boot/dts/adder875-redboot.dts
+++ b/arch/powerpc/boot/dts/adder875-redboot.dts
@@ -151,6 +151,7 @@
compatible = "fsl,mpc875-brg",
"fsl,cpm1-brg",
"fsl,cpm-brg";
+ clock-frequency = <50000000>;
reg = <0x9f0 0x10>;
};
diff --git a/arch/powerpc/boot/dts/adder875-uboot.dts b/arch/powerpc/boot/dts/adder875-uboot.dts
index 0197242dacf..54fb60ec03e 100644
--- a/arch/powerpc/boot/dts/adder875-uboot.dts
+++ b/arch/powerpc/boot/dts/adder875-uboot.dts
@@ -150,6 +150,7 @@
compatible = "fsl,mpc875-brg",
"fsl,cpm1-brg",
"fsl,cpm-brg";
+ clock-frequency = <50000000>;
reg = <0x9f0 0x10>;
};
diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts
new file mode 100644
index 00000000000..94ad7b2b241
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc5121ads.dts
@@ -0,0 +1,122 @@
+/*
+ * MPC5121E MDS Device Tree Source
+ *
+ * Copyright 2007 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/ {
+ model = "mpc5121ads";
+ compatible = "fsl,mpc5121ads";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,5121@0 {
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-line-size = <0x20>; // 32 bytes
+ i-cache-line-size = <0x20>; // 32 bytes
+ d-cache-size = <0x8000>; // L1, 32K
+ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <49500000>;// 49.5 MHz (csb/4)
+ bus-frequency = <198000000>; // 198 MHz csb bus
+ clock-frequency = <396000000>; // 396 MHz ppc core
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x10000000>; // 256MB at 0
+ };
+
+ localbus@80000020 {
+ compatible = "fsl,mpc5121ads-localbus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ reg = <0x80000020 0x40>;
+
+ ranges = <0x0 0x0 0xfc000000 0x04000000
+ 0x2 0x0 0x82000000 0x00008000>;
+
+ flash@0,0 {
+ compatible = "cfi-flash";
+ reg = <0 0x0 0x4000000>;
+ bank-width = <4>;
+ device-width = <1>;
+ };
+
+ board-control@2,0 {
+ compatible = "fsl,mpc5121ads-cpld";
+ reg = <0x2 0x0 0x8000>;
+ };
+ };
+
+ soc@80000000 {
+ compatible = "fsl,mpc5121-immr";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <2>;
+ ranges = <0x0 0x80000000 0x400000>;
+ reg = <0x80000000 0x400000>;
+ bus-frequency = <66000000>; // 66 MHz ips bus
+
+
+ // IPIC
+ // interrupts cell = <intr #, sense>
+ // sense values match linux IORESOURCE_IRQ_* defines:
+ // sense == 8: Level, low assertion
+ // sense == 2: Edge, high-to-low change
+ //
+ ipic: interrupt-controller@c00 {
+ compatible = "fsl,mpc5121-ipic", "fsl,ipic";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0xc00 0x100>;
+ };
+
+ // 512x PSCs are not 52xx PSCs compatible
+ // PSC3 serial port A aka ttyPSC0
+ serial@11300 {
+ device_type = "serial";
+ compatible = "fsl,mpc5121-psc-uart";
+ // Logical port assignment needed until driver
+ // learns to use aliases
+ port-number = <0>;
+ cell-index = <3>;
+ reg = <0x11300 0x100>;
+ interrupts = <0x28 0x8>; // actually the fifo irq
+ interrupt-parent = < &ipic >;
+ };
+
+ // PSC4 serial port B aka ttyPSC1
+ serial@11400 {
+ device_type = "serial";
+ compatible = "fsl,mpc5121-psc-uart";
+ // Logical port assignment needed until driver
+ // learns to use aliases
+ port-number = <1>;
+ cell-index = <4>;
+ reg = <0x11400 0x100>;
+ interrupts = <0x28 0x8>; // actually the fifo irq
+ interrupt-parent = < &ipic >;
+ };
+
+ pscsfifo@11f00 {
+ compatible = "fsl,mpc5121-psc-fifo";
+ reg = <0x11f00 0x100>;
+ interrupts = <0x28 0x8>;
+ interrupt-parent = < &ipic >;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts
index 2d6653fe72f..e1f0dca8ac3 100644
--- a/arch/powerpc/boot/dts/mpc8313erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8313erdb.dts
@@ -118,6 +118,10 @@
interrupts = <14 0x8>;
interrupt-parent = <&ipic>;
dfsrr;
+ rtc@68 {
+ compatible = "dallas,ds1339";
+ reg = <0x68>;
+ };
};
i2c@3100 {
diff --git a/arch/powerpc/boot/dts/mpc8315erdb.dts b/arch/powerpc/boot/dts/mpc8315erdb.dts
index b582032ba3d..d7a1ececa30 100644
--- a/arch/powerpc/boot/dts/mpc8315erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8315erdb.dts
@@ -96,7 +96,7 @@
#address-cells = <1>;
#size-cells = <1>;
device_type = "soc";
- compatible = "simple-bus";
+ compatible = "fsl,mpc8315-immr", "simple-bus";
ranges = <0 0xe0000000 0x00100000>;
reg = <0xe0000000 0x00000200>;
bus-frequency = <0>;
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts
index 7480edae85e..0199c5c548d 100644
--- a/arch/powerpc/boot/dts/mpc834x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
@@ -332,7 +332,7 @@
0xc000 0x0 0x0 0x3 &ipic 23 0x8
0xc000 0x0 0x0 0x4 &ipic 20 0x8>;
interrupt-parent = <&ipic>;
- interrupts = <66 0x8>;
+ interrupts = <67 0x8>;
bus-range = <0 0>;
ranges = <0x02000000 0x0 0xb0000000 0xb0000000 0x0 0x10000000
0x42000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts
index 813c259abbe..db37214aee3 100644
--- a/arch/powerpc/boot/dts/mpc8572ds.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds.dts
@@ -42,6 +42,18 @@
bus-frequency = <0>;
clock-frequency = <0>;
};
+
+ PowerPC,8572@1 {
+ device_type = "cpu";
+ reg = <1>;
+ d-cache-line-size = <20>; // 32 bytes
+ i-cache-line-size = <20>; // 32 bytes
+ d-cache-size = <8000>; // L1, 32K
+ i-cache-size = <8000>; // L1, 32K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+ };
};
memory {
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
index 8848e637293..d84a012c2aa 100644
--- a/arch/powerpc/boot/dts/mpc885ads.dts
+++ b/arch/powerpc/boot/dts/mpc885ads.dts
@@ -166,6 +166,7 @@
compatible = "fsl,mpc885-brg",
"fsl,cpm1-brg",
"fsl,cpm-brg";
+ clock-frequency = <0>;
reg = <9f0 10>;
};
diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts
index d9046c1adcb..5c13d46f441 100644
--- a/arch/powerpc/boot/dts/sequoia.dts
+++ b/arch/powerpc/boot/dts/sequoia.dts
@@ -138,6 +138,14 @@
interrupts = <15 8>;
};
+ USB0: ehci@e0000300 {
+ compatible = "ibm,usb-ehci-440epx", "usb-ehci";
+ interrupt-parent = <&UIC0>;
+ interrupts = <1a 4>;
+ reg = <0 e0000300 90 0 e0000390 70>;
+ big-endian;
+ };
+
POB0: opb {
compatible = "ibm,opb-440epx", "ibm,opb";
#address-cells = <1>;
diff --git a/arch/powerpc/boot/dts/storcenter.dts b/arch/powerpc/boot/dts/storcenter.dts
index 2204874ac5f..5893816c0bc 100644
--- a/arch/powerpc/boot/dts/storcenter.dts
+++ b/arch/powerpc/boot/dts/storcenter.dts
@@ -15,7 +15,7 @@
/ {
model = "StorCenter";
- compatible = "storcenter";
+ compatible = "iomega,storcenter";
#address-cells = <1>;
#size-cells = <1>;
@@ -62,12 +62,12 @@
#size-cells = <0>;
compatible = "fsl-i2c";
reg = <0x3000 0x100>;
- interrupts = <5 2>;
+ interrupts = <17 2>;
interrupt-parent = <&mpic>;
rtc@68 {
compatible = "dallas,ds1337";
- reg = <68>;
+ reg = <0x68>;
};
};
@@ -78,7 +78,7 @@
reg = <0x4500 0x20>;
clock-frequency = <97553800>; /* Hz */
current-speed = <115200>;
- interrupts = <9 2>;
+ interrupts = <25 2>;
interrupt-parent = <&mpic>;
};
@@ -89,7 +89,7 @@
reg = <0x4600 0x20>;
clock-frequency = <97553800>; /* Hz */
current-speed = <9600>;
- interrupts = <10 2>;
+ interrupts = <26 2>;
interrupt-parent = <&mpic>;
};
@@ -136,6 +136,6 @@
};
chosen {
- linux,stdout-path = "/soc/serial@4500";
+ linux,stdout-path = &serial0;
};
};
diff --git a/arch/powerpc/boot/ps3-hvcall.S b/arch/powerpc/boot/ps3-hvcall.S
index 585965f7e6a..d6068f1829c 100644
--- a/arch/powerpc/boot/ps3-hvcall.S
+++ b/arch/powerpc/boot/ps3-hvcall.S
@@ -145,7 +145,7 @@
.macro STORE_REGS_5_2
lwz r11, 16(r1)
std r4, 0(r11)
- lwz r11, 24(r1)
+ lwz r11, 20(r1)
std r5, 0(r11)
.endm
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 763a0c46f44..c3178155311 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -158,6 +158,29 @@ miboot|uboot)
cuboot*)
binary=y
gzip=
+ case "$platform" in
+ *-mpc885ads|*-adder875*|*-ep88xc)
+ platformo=$object/cuboot-8xx.o
+ ;;
+ *5200*|*-motionpro)
+ platformo=$object/cuboot-52xx.o
+ ;;
+ *-pq2fads|*-ep8248e|*-mpc8272*|*-storcenter)
+ platformo=$object/cuboot-pq2.o
+ ;;
+ *-mpc824*)
+ platformo=$object/cuboot-824x.o
+ ;;
+ *-mpc83*)
+ platformo=$object/cuboot-83xx.o
+ ;;
+ *-tqm8541|*-mpc8560*|*-tqm8560|*-tqm8555*)
+ platformo=$object/cuboot-85xx-cpm2.o
+ ;;
+ *-mpc85*)
+ platformo=$object/cuboot-85xx.o
+ ;;
+ esac
;;
ps3)
platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o"
diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig
index 31bdbf3f756..a9807f083bc 100644
--- a/arch/powerpc/configs/mpc83xx_defconfig
+++ b/arch/powerpc/configs/mpc83xx_defconfig
@@ -186,7 +186,7 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
-# CONFIG_MATH_EMULATION is not set
+CONFIG_MATH_EMULATION=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
@@ -416,14 +416,14 @@ CONFIG_PHYLIB=y
# MII PHY device drivers
#
CONFIG_MARVELL_PHY=y
-# CONFIG_DAVICOM_PHY is not set
+CONFIG_DAVICOM_PHY=y
# CONFIG_QSEMI_PHY is not set
# CONFIG_LXT_PHY is not set
# CONFIG_CICADA_PHY is not set
-# CONFIG_VITESSE_PHY is not set
+CONFIG_VITESSE_PHY=y
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
+CONFIG_ICPLUS_PHY=y
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -436,7 +436,7 @@ CONFIG_MII=y
CONFIG_NETDEV_1000=y
CONFIG_GIANFAR=y
# CONFIG_GFAR_NAPI is not set
-# CONFIG_UCC_GETH is not set
+CONFIG_UCC_GETH=y
CONFIG_NETDEV_10000=y
#
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 58dbfeff9b4..c1baf9d5903 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -2,6 +2,8 @@
# Makefile for the linux kernel.
#
+CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'
+
ifeq ($(CONFIG_PPC64),y)
CFLAGS_prom_init.o += -mno-minimal-toc
endif
@@ -15,7 +17,7 @@ obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
init_task.o process.o systbl.o idle.o \
signal.o
obj-y += vdso32/
-obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
+obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \
signal_64.o ptrace32.o \
paca.o cpu_setup_ppc970.o \
cpu_setup_pa6t.o \
@@ -102,3 +104,5 @@ quiet_cmd_systbl_chk = CALL $<
PHONY += systbl_chk
systbl_chk: $(src)/systbl_chk.sh $(obj)/systbl_chk.i
$(call cmd,systbl_chk)
+
+clean-files := vmlinux.lds
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index ed083feaf6f..4b749c41646 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -22,6 +22,7 @@
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/suspend.h>
+#include <linux/hrtimer.h>
#ifdef CONFIG_PPC64
#include <linux/time.h>
#include <linux/hardirq.h>
@@ -312,7 +313,7 @@ int main(void)
DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
- DEFINE(CLOCK_REALTIME_RES, TICK_NSEC);
+ DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
#ifdef CONFIG_BUG
DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
diff --git a/arch/powerpc/kernel/binfmt_elf32.c b/arch/powerpc/kernel/binfmt_elf32.c
deleted file mode 100644
index 1d45d7782d4..00000000000
--- a/arch/powerpc/kernel/binfmt_elf32.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * binfmt_elf32.c: Support 32-bit PPC ELF binaries on Power3 and followons.
- * based on the SPARC64 version.
- * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com)
- * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz)
- *
- * Copyright (C) 2000,2001 Ken Aaker (kdaaker@rchland.vnet.ibm.com), IBM Corp
- * Copyright (C) 2001 Anton Blanchard (anton@au.ibm.com), IBM
- *
- * 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 <asm/processor.h>
-#include <linux/module.h>
-#include <linux/compat.h>
-#include <linux/elfcore-compat.h>
-
-#undef ELF_ARCH
-#undef ELF_CLASS
-#define ELF_CLASS ELFCLASS32
-#define ELF_ARCH EM_PPC
-
-#undef elfhdr
-#undef elf_phdr
-#undef elf_note
-#undef elf_addr_t
-#define elfhdr elf32_hdr
-#define elf_phdr elf32_phdr
-#define elf_note elf32_note
-#define elf_addr_t Elf32_Off
-
-#define elf_prstatus compat_elf_prstatus
-#define elf_prpsinfo compat_elf_prpsinfo
-
-#define elf_core_copy_regs compat_elf_core_copy_regs
-static inline void compat_elf_core_copy_regs(compat_elf_gregset_t *elf_regs,
- struct pt_regs *regs)
-{
- PPC_ELF_CORE_COPY_REGS((*elf_regs), regs);
-}
-
-#define elf_core_copy_task_regs compat_elf_core_copy_task_regs
-static int compat_elf_core_copy_task_regs(struct task_struct *tsk,
- compat_elf_gregset_t *elf_regs)
-{
- struct pt_regs *regs = tsk->thread.regs;
- if (regs)
- compat_elf_core_copy_regs(elf_regs, regs);
- return 1;
-}
-
-#include <linux/time.h>
-
-#undef cputime_to_timeval
-#define cputime_to_timeval cputime_to_compat_timeval
-static __inline__ void
-cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
-{
- unsigned long jiffies = cputime_to_jiffies(cputime);
- value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
- value->tv_sec = jiffies / HZ;
-}
-
-#define init_elf_binfmt init_elf32_binfmt
-
-#include "../../../fs/binfmt_elf.c"
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index a4c2771b5e6..2a8f5cc5184 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -959,6 +959,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
+ .num_pmcs = 4,
+ .oprofile_cpu_type = "ppc/e300",
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.platform = "ppc603",
},
{ /* e300c4 (e300c1, plus one IU) */
@@ -971,6 +974,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
.machine_check = machine_check_generic,
+ .num_pmcs = 4,
+ .oprofile_cpu_type = "ppc/e300",
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.platform = "ppc603",
},
{ /* default match, we assume split I/D cache & TB (non-601)... */
@@ -1435,7 +1441,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.dcache_bsize = 32,
.num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500",
- .oprofile_type = PPC_OPROFILE_BOOKE,
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.machine_check = machine_check_e500,
.platform = "ppc8540",
},
@@ -1453,7 +1459,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.dcache_bsize = 32,
.num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500",
- .oprofile_type = PPC_OPROFILE_BOOKE,
+ .oprofile_type = PPC_OPROFILE_FSL_EMB,
.machine_check = machine_check_e500,
.platform = "ppc8548",
},
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c
index 84239076a5b..3a317cb0636 100644
--- a/arch/powerpc/kernel/dma_64.c
+++ b/arch/powerpc/kernel/dma_64.c
@@ -31,8 +31,8 @@ static inline unsigned long device_to_mask(struct device *dev)
static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
- return iommu_alloc_coherent(dev->archdata.dma_data, size, dma_handle,
- device_to_mask(dev), flag,
+ return iommu_alloc_coherent(dev, dev->archdata.dma_data, size,
+ dma_handle, device_to_mask(dev), flag,
dev->archdata.numa_node);
}
@@ -52,7 +52,7 @@ static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr,
size_t size,
enum dma_data_direction direction)
{
- return iommu_map_single(dev->archdata.dma_data, vaddr, size,
+ return iommu_map_single(dev, dev->archdata.dma_data, vaddr, size,
device_to_mask(dev), direction);
}
@@ -68,7 +68,7 @@ static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- return iommu_map_sg(dev->archdata.dma_data, sglist, nelems,
+ return iommu_map_sg(dev, sglist, nelems,
device_to_mask(dev), direction);
}
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index a3c406aca66..8f1f4e539c4 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -31,6 +31,7 @@
#include <linux/string.h>
#include <linux/dma-mapping.h>
#include <linux/bitops.h>
+#include <linux/iommu-helper.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/iommu.h>
@@ -81,17 +82,19 @@ static int __init setup_iommu(char *str)
__setup("protect4gb=", setup_protect4gb);
__setup("iommu=", setup_iommu);
-static unsigned long iommu_range_alloc(struct iommu_table *tbl,
+static unsigned long iommu_range_alloc(struct device *dev,
+ struct iommu_table *tbl,
unsigned long npages,
unsigned long *handle,
unsigned long mask,
unsigned int align_order)
{
- unsigned long n, end, i, start;
+ unsigned long n, end, start;
unsigned long limit;
int largealloc = npages > 15;
int pass = 0;
unsigned long align_mask;
+ unsigned long boundary_size;
align_mask = 0xffffffffffffffffl >> (64 - align_order);
@@ -136,14 +139,17 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
start &= mask;
}
- n = find_next_zero_bit(tbl->it_map, limit, start);
-
- /* Align allocation */
- n = (n + align_mask) & ~align_mask;
-
- end = n + npages;
+ if (dev)
+ boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+ 1 << IOMMU_PAGE_SHIFT);
+ else
+ boundary_size = ALIGN(1UL << 32, 1 << IOMMU_PAGE_SHIFT);
+ /* 4GB boundary for iseries_hv_alloc and iseries_hv_map */
- if (unlikely(end >= limit)) {
+ n = iommu_area_alloc(tbl->it_map, limit, start, npages,
+ tbl->it_offset, boundary_size >> IOMMU_PAGE_SHIFT,
+ align_mask);
+ if (n == -1) {
if (likely(pass < 2)) {
/* First failure, just rescan the half of the table.
* Second failure, rescan the other half of the table.
@@ -158,14 +164,7 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
}
}
- for (i = n; i < end; i++)
- if (test_bit(i, tbl->it_map)) {
- start = i+1;
- goto again;
- }
-
- for (i = n; i < end; i++)
- __set_bit(i, tbl->it_map);
+ end = n + npages;
/* Bump the hint to a new block for small allocs. */
if (largealloc) {
@@ -184,16 +183,17 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
return n;
}
-static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page,
- unsigned int npages, enum dma_data_direction direction,
- unsigned long mask, unsigned int align_order)
+static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
+ void *page, unsigned int npages,
+ enum dma_data_direction direction,
+ unsigned long mask, unsigned int align_order)
{
unsigned long entry, flags;
dma_addr_t ret = DMA_ERROR_CODE;
spin_lock_irqsave(&(tbl->it_lock), flags);
- entry = iommu_range_alloc(tbl, npages, NULL, mask, align_order);
+ entry = iommu_range_alloc(dev, tbl, npages, NULL, mask, align_order);
if (unlikely(entry == DMA_ERROR_CODE)) {
spin_unlock_irqrestore(&(tbl->it_lock), flags);
@@ -224,7 +224,6 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
unsigned int npages)
{
unsigned long entry, free_entry;
- unsigned long i;
entry = dma_addr >> IOMMU_PAGE_SHIFT;
free_entry = entry - tbl->it_offset;
@@ -246,9 +245,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
}
ppc_md.tce_free(tbl, entry, npages);
-
- for (i = 0; i < npages; i++)
- __clear_bit(free_entry+i, tbl->it_map);
+ iommu_area_free(tbl->it_map, free_entry, npages);
}
static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
@@ -270,16 +267,18 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
spin_unlock_irqrestore(&(tbl->it_lock), flags);
}
-int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
+int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, unsigned long mask,
enum dma_data_direction direction)
{
+ struct iommu_table *tbl = dev->archdata.dma_data;
dma_addr_t dma_next = 0, dma_addr;
unsigned long flags;
struct scatterlist *s, *outs, *segstart;
int outcount, incount, i;
unsigned int align;
unsigned long handle;
+ unsigned int max_seg_size;
BUG_ON(direction == DMA_NONE);
@@ -298,6 +297,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
spin_lock_irqsave(&(tbl->it_lock), flags);
+ max_seg_size = dma_get_max_seg_size(dev);
for_each_sg(sglist, s, nelems, i) {
unsigned long vaddr, npages, entry, slen;
@@ -314,7 +314,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && slen >= PAGE_SIZE &&
(vaddr & ~PAGE_MASK) == 0)
align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
- entry = iommu_range_alloc(tbl, npages, &handle,
+ entry = iommu_range_alloc(dev, tbl, npages, &handle,
mask >> IOMMU_PAGE_SHIFT, align);
DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen);
@@ -344,7 +344,8 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
/* We cannot merge if:
* - allocated dma_addr isn't contiguous to previous allocation
*/
- if (novmerge || (dma_addr != dma_next)) {
+ if (novmerge || (dma_addr != dma_next) ||
+ (outs->dma_length + s->length > max_seg_size)) {
/* Can't merge: create a new segment */
segstart = s;
outcount++;
@@ -452,9 +453,6 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
{
unsigned long sz;
- unsigned long start_index, end_index;
- unsigned long entries_per_4g;
- unsigned long index;
static int welcomed = 0;
struct page *page;
@@ -476,6 +474,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
#ifdef CONFIG_CRASH_DUMP
if (ppc_md.tce_get) {
+ unsigned long index;
unsigned long tceval;
unsigned long tcecount = 0;
@@ -506,23 +505,6 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
#endif
- /*
- * DMA cannot cross 4 GB boundary. Mark last entry of each 4
- * GB chunk as reserved.
- */
- if (protect4gb) {
- entries_per_4g = 0x100000000l >> IOMMU_PAGE_SHIFT;
-
- /* Mark the last bit before a 4GB boundary as used */
- start_index = tbl->it_offset | (entries_per_4g - 1);
- start_index -= tbl->it_offset;
-
- end_index = tbl->it_size;
-
- for (index = start_index; index < end_index - 1; index += entries_per_4g)
- __set_bit(index, tbl->it_map);
- }
-
if (!welcomed) {
printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
novmerge ? "disabled" : "enabled");
@@ -570,9 +552,9 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name)
* need not be page aligned, the dma_addr_t returned will point to the same
* byte within the page as vaddr.
*/
-dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
- size_t size, unsigned long mask,
- enum dma_data_direction direction)
+dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
+ void *vaddr, size_t size, unsigned long mask,
+ enum dma_data_direction direction)
{
dma_addr_t dma_handle = DMA_ERROR_CODE;
unsigned long uaddr;
@@ -589,7 +571,7 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
((unsigned long)vaddr & ~PAGE_MASK) == 0)
align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
- dma_handle = iommu_alloc(tbl, vaddr, npages, direction,
+ dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction,
mask >> IOMMU_PAGE_SHIFT, align);
if (dma_handle == DMA_ERROR_CODE) {
if (printk_ratelimit()) {
@@ -621,8 +603,9 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (mapping) of the first page.
*/
-void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
- dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node)
+void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
+ size_t size, dma_addr_t *dma_handle,
+ unsigned long mask, gfp_t flag, int node)
{
void *ret = NULL;
dma_addr_t mapping;
@@ -656,7 +639,7 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
/* Set up tces to cover the allocated range */
nio_pages = size >> IOMMU_PAGE_SHIFT;
io_order = get_iommu_order(size);
- mapping = iommu_alloc(tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
+ mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
mask >> IOMMU_PAGE_SHIFT, io_order);
if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order);
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 76b862bd1fe..61dd17449dd 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -36,7 +36,8 @@ static struct legacy_serial_info {
static struct __initdata of_device_id parents[] = {
{.type = "soc",},
{.type = "tsi-bridge",},
- {.type = "opb", .compatible = "ibm,opb",},
+ {.type = "opb", },
+ {.compatible = "ibm,opb",},
{.compatible = "simple-bus",},
{.compatible = "wrs,epld-localbus",},
};
diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c
index ea04e0ab3f2..0516e2d3e02 100644
--- a/arch/powerpc/kernel/pmc.c
+++ b/arch/powerpc/kernel/pmc.c
@@ -26,7 +26,7 @@
static void dummy_perf(struct pt_regs *regs)
{
-#if defined(CONFIG_FSL_BOOKE) && !defined(CONFIG_E200)
+#if defined(CONFIG_FSL_EMB_PERFMON)
mtpmr(PMRN_PMGC0, mfpmr(PMRN_PMGC0) & ~PMGC0_PMIE);
#elif defined(CONFIG_PPC64) || defined(CONFIG_6xx)
if (cur_cpu_spec->pmc_type == PPC_PMC_IBM)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index b9d88374f14..4846bf543a8 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -462,7 +462,7 @@ void show_regs(struct pt_regs * regs)
current, task_pid_nr(current), current->comm, task_thread_info(current));
#ifdef CONFIG_SMP
- printk(" CPU: %d", smp_processor_id());
+ printk(" CPU: %d", raw_smp_processor_id());
#endif /* CONFIG_SMP */
for (i = 0; i < 32; i++) {
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 8b056d2295c..7673e986573 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -21,6 +21,8 @@
#include <linux/smp.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
+#include <linux/regset.h>
+#include <linux/elf.h>
#include <linux/user.h>
#include <linux/security.h>
#include <linux/signal.h>
@@ -58,20 +60,38 @@
#define PT_MAX_PUT_REG PT_CCR
#endif
+static unsigned long get_user_msr(struct task_struct *task)
+{
+ return task->thread.regs->msr | task->thread.fpexc_mode;
+}
+
+static int set_user_msr(struct task_struct *task, unsigned long msr)
+{
+ task->thread.regs->msr &= ~MSR_DEBUGCHANGE;
+ task->thread.regs->msr |= msr & MSR_DEBUGCHANGE;
+ return 0;
+}
+
+/*
+ * We prevent mucking around with the reserved area of trap
+ * which are used internally by the kernel.
+ */
+static int set_user_trap(struct task_struct *task, unsigned long trap)
+{
+ task->thread.regs->trap = trap & 0xfff0;
+ return 0;
+}
+
/*
* Get contents of register REGNO in task TASK.
*/
unsigned long ptrace_get_reg(struct task_struct *task, int regno)
{
- unsigned long tmp = 0;
-
if (task->thread.regs == NULL)
return -EIO;
- if (regno == PT_MSR) {
- tmp = ((unsigned long *)task->thread.regs)[PT_MSR];
- return tmp | task->thread.fpexc_mode;
- }
+ if (regno == PT_MSR)
+ return get_user_msr(task);
if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
return ((unsigned long *)task->thread.regs)[regno];
@@ -87,40 +107,134 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
if (task->thread.regs == NULL)
return -EIO;
- if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) {
- if (regno == PT_MSR)
- data = (data & MSR_DEBUGCHANGE)
- | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
- /* We prevent mucking around with the reserved area of trap
- * which are used internally by the kernel
- */
- if (regno == PT_TRAP)
- data &= 0xfff0;
+ if (regno == PT_MSR)
+ return set_user_msr(task, data);
+ if (regno == PT_TRAP)
+ return set_user_trap(task, data);
+
+ if (regno <= PT_MAX_PUT_REG) {
((unsigned long *)task->thread.regs)[regno] = data;
return 0;
}
return -EIO;
}
+static int gpr_get(struct task_struct *target, const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+
+ if (target->thread.regs == NULL)
+ return -EIO;
+
+ CHECK_FULL_REGS(target->thread.regs);
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ target->thread.regs,
+ 0, offsetof(struct pt_regs, msr));
+ if (!ret) {
+ unsigned long msr = get_user_msr(target);
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &msr,
+ offsetof(struct pt_regs, msr),
+ offsetof(struct pt_regs, msr) +
+ sizeof(msr));
+ }
+
+ BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
+ offsetof(struct pt_regs, msr) + sizeof(long));
+
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.regs->orig_gpr3,
+ offsetof(struct pt_regs, orig_gpr3),
+ sizeof(struct pt_regs));
+ if (!ret)
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ sizeof(struct pt_regs), -1);
+
+ return ret;
+}
+
+static int gpr_set(struct task_struct *target, const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ unsigned long reg;
+ int ret;
+
+ if (target->thread.regs == NULL)
+ return -EIO;
+
+ CHECK_FULL_REGS(target->thread.regs);
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ target->thread.regs,
+ 0, PT_MSR * sizeof(reg));
-static int get_fpregs(void __user *data, struct task_struct *task,
- int has_fpscr)
+ if (!ret && count > 0) {
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
+ PT_MSR * sizeof(reg),
+ (PT_MSR + 1) * sizeof(reg));
+ if (!ret)
+ ret = set_user_msr(target, reg);
+ }
+
+ BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
+ offsetof(struct pt_regs, msr) + sizeof(long));
+
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.regs->orig_gpr3,
+ PT_ORIG_R3 * sizeof(reg),
+ (PT_MAX_PUT_REG + 1) * sizeof(reg));
+
+ if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret)
+ ret = user_regset_copyin_ignore(
+ &pos, &count, &kbuf, &ubuf,
+ (PT_MAX_PUT_REG + 1) * sizeof(reg),
+ PT_TRAP * sizeof(reg));
+
+ if (!ret && count > 0) {
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
+ PT_TRAP * sizeof(reg),
+ (PT_TRAP + 1) * sizeof(reg));
+ if (!ret)
+ ret = set_user_trap(target, reg);
+ }
+
+ if (!ret)
+ ret = user_regset_copyin_ignore(
+ &pos, &count, &kbuf, &ubuf,
+ (PT_TRAP + 1) * sizeof(reg), -1);
+
+ return ret;
+}
+
+static int fpr_get(struct task_struct *target, const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
{
- unsigned int count = has_fpscr ? 33 : 32;
+ flush_fp_to_thread(target);
- if (copy_to_user(data, task->thread.fpr, count * sizeof(double)))
- return -EFAULT;
- return 0;
+ BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) !=
+ offsetof(struct thread_struct, fpr[32]));
+
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.fpr, 0, -1);
}
-static int set_fpregs(void __user *data, struct task_struct *task,
- int has_fpscr)
+static int fpr_set(struct task_struct *target, const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
{
- unsigned int count = has_fpscr ? 33 : 32;
+ flush_fp_to_thread(target);
- if (copy_from_user(task->thread.fpr, data, count * sizeof(double)))
- return -EFAULT;
- return 0;
+ BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) !=
+ offsetof(struct thread_struct, fpr[32]));
+
+ return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.fpr, 0, -1);
}
@@ -138,56 +252,74 @@ static int set_fpregs(void __user *data, struct task_struct *task,
* (combined (32- and 64-bit) gdb.
*/
-/*
- * Get contents of AltiVec register state in task TASK
- */
-static int get_vrregs(unsigned long __user *data, struct task_struct *task)
+static int vr_active(struct task_struct *target,
+ const struct user_regset *regset)
{
- unsigned long regsize;
+ flush_altivec_to_thread(target);
+ return target->thread.used_vr ? regset->n : 0;
+}
- /* copy AltiVec registers VR[0] .. VR[31] */
- regsize = 32 * sizeof(vector128);
- if (copy_to_user(data, task->thread.vr, regsize))
- return -EFAULT;
- data += (regsize / sizeof(unsigned long));
+static int vr_get(struct task_struct *target, const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
- /* copy VSCR */
- regsize = 1 * sizeof(vector128);
- if (copy_to_user(data, &task->thread.vscr, regsize))
- return -EFAULT;
- data += (regsize / sizeof(unsigned long));
+ flush_altivec_to_thread(target);
- /* copy VRSAVE */
- if (put_user(task->thread.vrsave, (u32 __user *)data))
- return -EFAULT;
+ BUILD_BUG_ON(offsetof(struct thread_struct, vscr) !=
+ offsetof(struct thread_struct, vr[32]));
- return 0;
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.vr, 0,
+ 33 * sizeof(vector128));
+ if (!ret) {
+ /*
+ * Copy out only the low-order word of vrsave.
+ */
+ union {
+ elf_vrreg_t reg;
+ u32 word;
+ } vrsave;
+ memset(&vrsave, 0, sizeof(vrsave));
+ vrsave.word = target->thread.vrsave;
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
+ 33 * sizeof(vector128), -1);
+ }
+
+ return ret;
}
-/*
- * Write contents of AltiVec register state into task TASK.
- */
-static int set_vrregs(struct task_struct *task, unsigned long __user *data)
+static int vr_set(struct task_struct *target, const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
{
- unsigned long regsize;
+ int ret;
- /* copy AltiVec registers VR[0] .. VR[31] */
- regsize = 32 * sizeof(vector128);
- if (copy_from_user(task->thread.vr, data, regsize))
- return -EFAULT;
- data += (regsize / sizeof(unsigned long));
+ flush_altivec_to_thread(target);
- /* copy VSCR */
- regsize = 1 * sizeof(vector128);
- if (copy_from_user(&task->thread.vscr, data, regsize))
- return -EFAULT;
- data += (regsize / sizeof(unsigned long));
+ BUILD_BUG_ON(offsetof(struct thread_struct, vscr) !=
+ offsetof(struct thread_struct, vr[32]));
- /* copy VRSAVE */
- if (get_user(task->thread.vrsave, (u32 __user *)data))
- return -EFAULT;
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.vr, 0, 33 * sizeof(vector128));
+ if (!ret && count > 0) {
+ /*
+ * We use only the first word of vrsave.
+ */
+ union {
+ elf_vrreg_t reg;
+ u32 word;
+ } vrsave;
+ memset(&vrsave, 0, sizeof(vrsave));
+ vrsave.word = target->thread.vrsave;
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
+ 33 * sizeof(vector128), -1);
+ if (!ret)
+ target->thread.vrsave = vrsave.word;
+ }
- return 0;
+ return ret;
}
#endif /* CONFIG_ALTIVEC */
@@ -203,57 +335,273 @@ static int set_vrregs(struct task_struct *task, unsigned long __user *data)
* }
*/
-/*
- * Get contents of SPE register state in task TASK.
- */
-static int get_evrregs(unsigned long *data, struct task_struct *task)
+static int evr_active(struct task_struct *target,
+ const struct user_regset *regset)
{
- int i;
+ flush_spe_to_thread(target);
+ return target->thread.used_spe ? regset->n : 0;
+}
- if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(unsigned long)))
- return -EFAULT;
+static int evr_get(struct task_struct *target, const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
- /* copy SPEFSCR */
- if (__put_user(task->thread.spefscr, &data[34]))
- return -EFAULT;
+ flush_spe_to_thread(target);
- /* copy SPE registers EVR[0] .. EVR[31] */
- for (i = 0; i < 32; i++, data++)
- if (__put_user(task->thread.evr[i], data))
- return -EFAULT;
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.evr,
+ 0, sizeof(target->thread.evr));
- /* copy ACC */
- if (__put_user64(task->thread.acc, (unsigned long long *)data))
- return -EFAULT;
+ BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) !=
+ offsetof(struct thread_struct, spefscr));
- return 0;
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.acc,
+ sizeof(target->thread.evr), -1);
+
+ return ret;
+}
+
+static int evr_set(struct task_struct *target, const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+
+ flush_spe_to_thread(target);
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.evr,
+ 0, sizeof(target->thread.evr));
+
+ BUILD_BUG_ON(offsetof(struct thread_struct, acc) + sizeof(u64) !=
+ offsetof(struct thread_struct, spefscr));
+
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.acc,
+ sizeof(target->thread.evr), -1);
+
+ return ret;
}
+#endif /* CONFIG_SPE */
+
/*
- * Write contents of SPE register state into task TASK.
+ * These are our native regset flavors.
*/
-static int set_evrregs(struct task_struct *task, unsigned long *data)
+enum powerpc_regset {
+ REGSET_GPR,
+ REGSET_FPR,
+#ifdef CONFIG_ALTIVEC
+ REGSET_VMX,
+#endif
+#ifdef CONFIG_SPE
+ REGSET_SPE,
+#endif
+};
+
+static const struct user_regset native_regsets[] = {
+ [REGSET_GPR] = {
+ .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
+ .size = sizeof(long), .align = sizeof(long),
+ .get = gpr_get, .set = gpr_set
+ },
+ [REGSET_FPR] = {
+ .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
+ .size = sizeof(double), .align = sizeof(double),
+ .get = fpr_get, .set = fpr_set
+ },
+#ifdef CONFIG_ALTIVEC
+ [REGSET_VMX] = {
+ .core_note_type = NT_PPC_VMX, .n = 34,
+ .size = sizeof(vector128), .align = sizeof(vector128),
+ .active = vr_active, .get = vr_get, .set = vr_set
+ },
+#endif
+#ifdef CONFIG_SPE
+ [REGSET_SPE] = {
+ .n = 35,
+ .size = sizeof(u32), .align = sizeof(u32),
+ .active = evr_active, .get = evr_get, .set = evr_set
+ },
+#endif
+};
+
+static const struct user_regset_view user_ppc_native_view = {
+ .name = UTS_MACHINE, .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI,
+ .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
+};
+
+#ifdef CONFIG_PPC64
+#include <linux/compat.h>
+
+static int gpr32_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
{
- int i;
+ const unsigned long *regs = &target->thread.regs->gpr[0];
+ compat_ulong_t *k = kbuf;
+ compat_ulong_t __user *u = ubuf;
+ compat_ulong_t reg;
+
+ if (target->thread.regs == NULL)
+ return -EIO;
+
+ CHECK_FULL_REGS(target->thread.regs);
- if (!access_ok(VERIFY_READ, data, 35 * sizeof(unsigned long)))
- return -EFAULT;
+ pos /= sizeof(reg);
+ count /= sizeof(reg);
- /* copy SPEFSCR */
- if (__get_user(task->thread.spefscr, &data[34]))
- return -EFAULT;
+ if (kbuf)
+ for (; count > 0 && pos < PT_MSR; --count)
+ *k++ = regs[pos++];
+ else
+ for (; count > 0 && pos < PT_MSR; --count)
+ if (__put_user((compat_ulong_t) regs[pos++], u++))
+ return -EFAULT;
- /* copy SPE registers EVR[0] .. EVR[31] */
- for (i = 0; i < 32; i++, data++)
- if (__get_user(task->thread.evr[i], data))
+ if (count > 0 && pos == PT_MSR) {
+ reg = get_user_msr(target);
+ if (kbuf)
+ *k++ = reg;
+ else if (__put_user(reg, u++))
return -EFAULT;
- /* copy ACC */
- if (__get_user64(task->thread.acc, (unsigned long long*)data))
- return -EFAULT;
+ ++pos;
+ --count;
+ }
- return 0;
+ if (kbuf)
+ for (; count > 0 && pos < PT_REGS_COUNT; --count)
+ *k++ = regs[pos++];
+ else
+ for (; count > 0 && pos < PT_REGS_COUNT; --count)
+ if (__put_user((compat_ulong_t) regs[pos++], u++))
+ return -EFAULT;
+
+ kbuf = k;
+ ubuf = u;
+ pos *= sizeof(reg);
+ count *= sizeof(reg);
+ return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ PT_REGS_COUNT * sizeof(reg), -1);
+}
+
+static int gpr32_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ unsigned long *regs = &target->thread.regs->gpr[0];
+ const compat_ulong_t *k = kbuf;
+ const compat_ulong_t __user *u = ubuf;
+ compat_ulong_t reg;
+
+ if (target->thread.regs == NULL)
+ return -EIO;
+
+ CHECK_FULL_REGS(target->thread.regs);
+
+ pos /= sizeof(reg);
+ count /= sizeof(reg);
+
+ if (kbuf)
+ for (; count > 0 && pos < PT_MSR; --count)
+ regs[pos++] = *k++;
+ else
+ for (; count > 0 && pos < PT_MSR; --count) {
+ if (__get_user(reg, u++))
+ return -EFAULT;
+ regs[pos++] = reg;
+ }
+
+
+ if (count > 0 && pos == PT_MSR) {
+ if (kbuf)
+ reg = *k++;
+ else if (__get_user(reg, u++))
+ return -EFAULT;
+ set_user_msr(target, reg);
+ ++pos;
+ --count;
+ }
+
+ if (kbuf)
+ for (; count > 0 && pos <= PT_MAX_PUT_REG; --count)
+ regs[pos++] = *k++;
+ else
+ for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) {
+ if (__get_user(reg, u++))
+ return -EFAULT;
+ regs[pos++] = reg;
+ }
+
+ if (count > 0 && pos == PT_TRAP) {
+ if (kbuf)
+ reg = *k++;
+ else if (__get_user(reg, u++))
+ return -EFAULT;
+ set_user_trap(target, reg);
+ ++pos;
+ --count;
+ }
+
+ kbuf = k;
+ ubuf = u;
+ pos *= sizeof(reg);
+ count *= sizeof(reg);
+ return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ (PT_TRAP + 1) * sizeof(reg), -1);
+}
+
+/*
+ * These are the regset flavors matching the CONFIG_PPC32 native set.
+ */
+static const struct user_regset compat_regsets[] = {
+ [REGSET_GPR] = {
+ .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
+ .size = sizeof(compat_long_t), .align = sizeof(compat_long_t),
+ .get = gpr32_get, .set = gpr32_set
+ },
+ [REGSET_FPR] = {
+ .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
+ .size = sizeof(double), .align = sizeof(double),
+ .get = fpr_get, .set = fpr_set
+ },
+#ifdef CONFIG_ALTIVEC
+ [REGSET_VMX] = {
+ .core_note_type = NT_PPC_VMX, .n = 34,
+ .size = sizeof(vector128), .align = sizeof(vector128),
+ .active = vr_active, .get = vr_get, .set = vr_set
+ },
+#endif
+#ifdef CONFIG_SPE
+ [REGSET_SPE] = {
+ .core_note_type = NT_PPC_SPE, .n = 35,
+ .size = sizeof(u32), .align = sizeof(u32),
+ .active = evr_active, .get = evr_get, .set = evr_set
+ },
+#endif
+};
+
+static const struct user_regset_view user_ppc_compat_view = {
+ .name = "ppc", .e_machine = EM_PPC, .ei_osabi = ELF_OSABI,
+ .regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets)
+};
+#endif /* CONFIG_PPC64 */
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+#ifdef CONFIG_PPC64
+ if (test_tsk_thread_flag(task, TIF_32BIT))
+ return &user_ppc_compat_view;
+#endif
+ return &user_ppc_native_view;
}
-#endif /* CONFIG_SPE */
void user_enable_single_step(struct task_struct *task)
@@ -323,55 +671,29 @@ void ptrace_disable(struct task_struct *child)
static long arch_ptrace_old(struct task_struct *child, long request, long addr,
long data)
{
- int ret = -EPERM;
-
- switch(request) {
- case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
- unsigned long __user *tmp = (unsigned long __user *)addr;
-
- CHECK_FULL_REGS(child->thread.regs);
- for (i = 0; i < 32; i++) {
- ret = put_user(*reg, tmp);
- if (ret)
- break;
- reg++;
- tmp++;
- }
- break;
- }
-
- case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
- unsigned long __user *tmp = (unsigned long __user *)addr;
-
- CHECK_FULL_REGS(child->thread.regs);
- for (i = 0; i < 32; i++) {
- ret = get_user(*reg, tmp);
- if (ret)
- break;
- reg++;
- tmp++;
- }
- break;
- }
-
- case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
- flush_fp_to_thread(child);
- ret = get_fpregs((void __user *)addr, child, 0);
- break;
- }
-
- case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
- flush_fp_to_thread(child);
- ret = set_fpregs((void __user *)addr, child, 0);
- break;
+ switch (request) {
+ case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+ return copy_regset_to_user(child, &user_ppc_native_view,
+ REGSET_GPR, 0, 32 * sizeof(long),
+ (void __user *) data);
+
+ case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+ return copy_regset_from_user(child, &user_ppc_native_view,
+ REGSET_GPR, 0, 32 * sizeof(long),
+ (const void __user *) data);
+
+ case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
+ return copy_regset_to_user(child, &user_ppc_native_view,
+ REGSET_FPR, 0, 32 * sizeof(double),
+ (void __user *) data);
+
+ case PPC_PTRACE_SETFPREGS: /* Set FPRs 0 - 31. */
+ return copy_regset_from_user(child, &user_ppc_native_view,
+ REGSET_FPR, 0, 32 * sizeof(double),
+ (const void __user *) data);
}
- }
- return ret;
+ return -EPERM;
}
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
@@ -379,12 +701,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
int ret = -EPERM;
switch (request) {
- /* when I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA:
- ret = generic_ptrace_peekdata(child, addr, data);
- break;
-
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long index, tmp;
@@ -412,12 +728,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
- /* If I and D space are separate, this will have to be fixed. */
- case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA:
- ret = generic_ptrace_pokedata(child, addr, data);
- break;
-
/* write the word at location addr in the USER area */
case PTRACE_POKEUSR: {
unsigned long index;
@@ -462,85 +772,60 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef CONFIG_PPC64
case PTRACE_GETREGS64:
#endif
- case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
- int ui;
- if (!access_ok(VERIFY_WRITE, (void __user *)data,
- sizeof(struct pt_regs))) {
- ret = -EIO;
- break;
- }
- CHECK_FULL_REGS(child->thread.regs);
- ret = 0;
- for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
- ret |= __put_user(ptrace_get_reg(child, ui),
- (unsigned long __user *) data);
- data += sizeof(long);
- }
- break;
- }
+ case PTRACE_GETREGS: /* Get all pt_regs from the child. */
+ return copy_regset_to_user(child, &user_ppc_native_view,
+ REGSET_GPR,
+ 0, sizeof(struct pt_regs),
+ (void __user *) data);
#ifdef CONFIG_PPC64
case PTRACE_SETREGS64:
#endif
- case PTRACE_SETREGS: { /* Set all gp regs in the child. */
- unsigned long tmp;
- int ui;
- if (!access_ok(VERIFY_READ, (void __user *)data,
- sizeof(struct pt_regs))) {
- ret = -EIO;
- break;
- }
- CHECK_FULL_REGS(child->thread.regs);
- ret = 0;
- for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
- ret = __get_user(tmp, (unsigned long __user *) data);
- if (ret)
- break;
- ptrace_put_reg(child, ui, tmp);
- data += sizeof(long);
- }
- break;
- }
-
- case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */
- flush_fp_to_thread(child);
- ret = get_fpregs((void __user *)data, child, 1);
- break;
- }
-
- case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */
- flush_fp_to_thread(child);
- ret = set_fpregs((void __user *)data, child, 1);
- break;
- }
+ case PTRACE_SETREGS: /* Set all gp regs in the child. */
+ return copy_regset_from_user(child, &user_ppc_native_view,
+ REGSET_GPR,
+ 0, sizeof(struct pt_regs),
+ (const void __user *) data);
+
+ case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */
+ return copy_regset_to_user(child, &user_ppc_native_view,
+ REGSET_FPR,
+ 0, sizeof(elf_fpregset_t),
+ (void __user *) data);
+
+ case PTRACE_SETFPREGS: /* Set the child FPU state (FPR0...31 + FPSCR) */
+ return copy_regset_from_user(child, &user_ppc_native_view,
+ REGSET_FPR,
+ 0, sizeof(elf_fpregset_t),
+ (const void __user *) data);
#ifdef CONFIG_ALTIVEC
case PTRACE_GETVRREGS:
- /* Get the child altivec register state. */
- flush_altivec_to_thread(child);
- ret = get_vrregs((unsigned long __user *)data, child);
- break;
+ return copy_regset_to_user(child, &user_ppc_native_view,
+ REGSET_VMX,
+ 0, (33 * sizeof(vector128) +
+ sizeof(u32)),
+ (void __user *) data);
case PTRACE_SETVRREGS:
- /* Set the child altivec register state. */
- flush_altivec_to_thread(child);
- ret = set_vrregs(child, (unsigned long __user *)data);
- break;
+ return copy_regset_from_user(child, &user_ppc_native_view,
+ REGSET_VMX,
+ 0, (33 * sizeof(vector128) +
+ sizeof(u32)),
+ (const void __user *) data);
#endif
#ifdef CONFIG_SPE
case PTRACE_GETEVRREGS:
/* Get the child spe register state. */
- flush_spe_to_thread(child);
- ret = get_evrregs((unsigned long __user *)data, child);
- break;
+ return copy_regset_to_user(child, &user_ppc_native_view,
+ REGSET_SPE, 0, 35 * sizeof(u32),
+ (void __user *) data);
case PTRACE_SETEVRREGS:
/* Set the child spe register state. */
- /* this is to clear the MSR_SPE bit to force a reload
- * of register state from memory */
- flush_spe_to_thread(child);
- ret = set_evrregs(child, (unsigned long __user *)data);
- break;
+ return copy_regset_from_user(child, &user_ppc_native_view,
+ REGSET_SPE, 0, 35 * sizeof(u32),
+ (const void __user *) data);
#endif
/* Old reverse args ptrace callss */
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index fea6206ff90..4c1de6af4c0 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -24,9 +24,11 @@
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
+#include <linux/regset.h>
#include <linux/user.h>
#include <linux/security.h>
#include <linux/signal.h>
+#include <linux/compat.h>
#include <asm/uaccess.h>
#include <asm/page.h>
@@ -45,87 +47,31 @@
static long compat_ptrace_old(struct task_struct *child, long request,
long addr, long data)
{
- int ret = -EPERM;
-
- switch(request) {
- case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
- unsigned int __user *tmp = (unsigned int __user *)addr;
-
- CHECK_FULL_REGS(child->thread.regs);
- for (i = 0; i < 32; i++) {
- ret = put_user(*reg, tmp);
- if (ret)
- break;
- reg++;
- tmp++;
- }
- break;
- }
-
- case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
- int i;
- unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
- unsigned int __user *tmp = (unsigned int __user *)addr;
-
- CHECK_FULL_REGS(child->thread.regs);
- for (i = 0; i < 32; i++) {
- ret = get_user(*reg, tmp);
- if (ret)
- break;
- reg++;
- tmp++;
- }
- break;
+ switch (request) {
+ case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
+ return copy_regset_to_user(child,
+ task_user_regset_view(current), 0,
+ 0, 32 * sizeof(compat_long_t),
+ compat_ptr(data));
+
+ case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
+ return copy_regset_from_user(child,
+ task_user_regset_view(current), 0,
+ 0, 32 * sizeof(compat_long_t),
+ compat_ptr(data));
}
- }
- return ret;
+ return -EPERM;
}
-long compat_sys_ptrace(int request, int pid, unsigned long addr,
- unsigned long data)
+long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+ compat_ulong_t caddr, compat_ulong_t cdata)
{
- struct task_struct *child;
+ unsigned long addr = caddr;
+ unsigned long data = cdata;
int ret;
- lock_kernel();
- if (request == PTRACE_TRACEME) {
- ret = ptrace_traceme();
- goto out;
- }
-
- child = ptrace_get_task_struct(pid);
- if (IS_ERR(child)) {
- ret = PTR_ERR(child);
- goto out;
- }
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
- /* when I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned int tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp, (u32 __user *)data);
- break;
- }
-
/*
* Read 4 bytes of the other process' storage
* data is a pointer specifying where the user wants the
@@ -225,19 +171,6 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
break;
}
- /* If I and D space are separate, this will have to be fixed. */
- case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA: {
- unsigned int tmp;
- tmp = data;
- ret = 0;
- if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1)
- == sizeof(tmp))
- break;
- ret = -EIO;
- break;
- }
-
/*
* Write 4 bytes into the other process' storage
* data is the 4 bytes that the user wants written
@@ -337,46 +270,17 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
break;
}
- case PTRACE_GETEVENTMSG:
- ret = put_user(child->ptrace_message, (unsigned int __user *) data);
- break;
+ case PTRACE_GETREGS: /* Get all pt_regs from the child. */
+ return copy_regset_to_user(
+ child, task_user_regset_view(current), 0,
+ 0, PT_REGS_COUNT * sizeof(compat_long_t),
+ compat_ptr(data));
- case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
- int ui;
- if (!access_ok(VERIFY_WRITE, (void __user *)data,
- PT_REGS_COUNT * sizeof(int))) {
- ret = -EIO;
- break;
- }
- CHECK_FULL_REGS(child->thread.regs);
- ret = 0;
- for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
- ret |= __put_user(ptrace_get_reg(child, ui),
- (unsigned int __user *) data);
- data += sizeof(int);
- }
- break;
- }
-
- case PTRACE_SETREGS: { /* Set all gp regs in the child. */
- unsigned long tmp;
- int ui;
- if (!access_ok(VERIFY_READ, (void __user *)data,
- PT_REGS_COUNT * sizeof(int))) {
- ret = -EIO;
- break;
- }
- CHECK_FULL_REGS(child->thread.regs);
- ret = 0;
- for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
- ret = __get_user(tmp, (unsigned int __user *) data);
- if (ret)
- break;
- ptrace_put_reg(child, ui, tmp);
- data += sizeof(int);
- }
- break;
- }
+ case PTRACE_SETREGS: /* Set all gp regs in the child. */
+ return copy_regset_from_user(
+ child, task_user_regset_view(current), 0,
+ 0, PT_REGS_COUNT * sizeof(compat_long_t),
+ compat_ptr(data));
case PTRACE_GETFPREGS:
case PTRACE_SETFPREGS:
@@ -402,12 +306,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
break;
default:
- ret = ptrace_request(child, request, addr, data);
+ ret = compat_ptrace_request(child, request, addr, data);
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
+
return ret;
}
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 5cd3db5cae4..3b26fbd6bec 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -66,6 +66,7 @@
#include <asm/smp.h>
#include <asm/vdso_datapage.h>
#include <asm/firmware.h>
+#include <asm/cputime.h>
#ifdef CONFIG_PPC_ISERIES
#include <asm/iseries/it_lp_queue.h>
#include <asm/iseries/hv_call_xm.h>
@@ -189,6 +190,8 @@ u64 __cputime_sec_factor;
EXPORT_SYMBOL(__cputime_sec_factor);
u64 __cputime_clockt_factor;
EXPORT_SYMBOL(__cputime_clockt_factor);
+DEFINE_PER_CPU(unsigned long, cputime_last_delta);
+DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta);
static void calc_cputime_factors(void)
{
@@ -257,8 +260,8 @@ void account_system_vtime(struct task_struct *tsk)
}
account_system_time(tsk, 0, delta);
account_system_time_scaled(tsk, deltascaled);
- get_paca()->purrdelta = delta;
- get_paca()->spurrdelta = deltascaled;
+ per_cpu(cputime_last_delta, smp_processor_id()) = delta;
+ per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
local_irq_restore(flags);
}
@@ -276,10 +279,7 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
get_paca()->user_time = 0;
account_user_time(tsk, utime);
- /* Estimate the scaled utime by scaling the real utime based
- * on the last spurr to purr ratio */
- utimescaled = utime * get_paca()->spurrdelta / get_paca()->purrdelta;
- get_paca()->spurrdelta = get_paca()->purrdelta = 0;
+ utimescaled = cputime_to_scaled(utime);
account_user_time_scaled(tsk, utimescaled);
}
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 848a20475db..4b5b7ff4f78 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -54,7 +54,7 @@
#endif
#include <asm/kexec.h>
-#ifdef CONFIG_DEBUGGER
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
int (*__debugger)(struct pt_regs *regs);
int (*__debugger_ipi)(struct pt_regs *regs);
int (*__debugger_bpt)(struct pt_regs *regs);
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 3702df7dc56..d3437c4c4a6 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -336,9 +336,9 @@ static unsigned long __init find_function32(struct lib32_elfinfo *lib,
return sym->st_value - VDSO32_LBASE;
}
-static int vdso_do_func_patch32(struct lib32_elfinfo *v32,
- struct lib64_elfinfo *v64,
- const char *orig, const char *fix)
+static int __init vdso_do_func_patch32(struct lib32_elfinfo *v32,
+ struct lib64_elfinfo *v64,
+ const char *orig, const char *fix)
{
Elf32_Sym *sym32_gen, *sym32_fix;
@@ -433,9 +433,9 @@ static unsigned long __init find_function64(struct lib64_elfinfo *lib,
#endif
}
-static int vdso_do_func_patch64(struct lib32_elfinfo *v32,
- struct lib64_elfinfo *v64,
- const char *orig, const char *fix)
+static int __init vdso_do_func_patch64(struct lib32_elfinfo *v32,
+ struct lib64_elfinfo *v64,
+ const char *orig, const char *fix)
{
Elf64_Sym *sym64_gen, *sym64_fix;
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index f0bad7070fb..f98867252ee 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -176,7 +176,7 @@ static void __devinit vio_dev_release(struct device *dev)
* Returns a pointer to the created vio_dev or NULL if node has
* NULL device_type or compatible fields.
*/
-struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
+struct vio_dev *vio_register_device_node(struct device_node *of_node)
{
struct vio_dev *viodev;
const unsigned int *unit_address;
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index e8122447f01..be5c506779a 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -129,6 +129,39 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size)
return __add_pages(zone, start_pfn, nr_pages);
}
+#ifdef CONFIG_MEMORY_HOTREMOVE
+int remove_memory(u64 start, u64 size)
+{
+ unsigned long start_pfn, end_pfn;
+ int ret;
+
+ start_pfn = start >> PAGE_SHIFT;
+ end_pfn = start_pfn + (size >> PAGE_SHIFT);
+ ret = offline_pages(start_pfn, end_pfn, 120 * HZ);
+ if (ret)
+ goto out;
+ /* Arch-specific calls go here - next patch */
+out:
+ return ret;
+}
+#endif /* CONFIG_MEMORY_HOTREMOVE */
+
+/*
+ * walk_memory_resource() needs to make sure there is no holes in a given
+ * memory range. On PPC64, since this range comes from /sysfs, the range
+ * is guaranteed to be valid, non-overlapping and can not contain any
+ * holes. By the time we get here (memory add or remove), /proc/device-tree
+ * is updated and correct. Only reason we need to check against device-tree
+ * would be if we allow user-land to specify a memory range through a
+ * system call/ioctl etc. instead of doing offline/online through /sysfs.
+ */
+int
+walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg,
+ int (*func)(unsigned long, unsigned long, void *))
+{
+ return (*func)(start_pfn, nr_pages, arg);
+}
+
#endif /* CONFIG_MEMORY_HOTPLUG */
void show_mem(void)
@@ -220,12 +253,13 @@ void __init do_init_bootmem(void)
lmb_size_bytes(&lmb.reserved, i) - 1;
if (addr < total_lowmem)
reserve_bootmem(lmb.reserved.region[i].base,
- lmb_size_bytes(&lmb.reserved, i));
+ lmb_size_bytes(&lmb.reserved, i),
+ BOOTMEM_DEFAULT);
else if (lmb.reserved.region[i].base < total_lowmem) {
unsigned long adjusted_size = total_lowmem -
lmb.reserved.region[i].base;
reserve_bootmem(lmb.reserved.region[i].base,
- adjusted_size);
+ adjusted_size, BOOTMEM_DEFAULT);
}
}
#else
@@ -234,7 +268,8 @@ void __init do_init_bootmem(void)
/* reserve the sections we're already using */
for (i = 0; i < lmb.reserved.cnt; i++)
reserve_bootmem(lmb.reserved.region[i].base,
- lmb_size_bytes(&lmb.reserved, i));
+ lmb_size_bytes(&lmb.reserved, i),
+ BOOTMEM_DEFAULT);
#endif
/* XXX need to clip this if using highmem? */
@@ -483,7 +518,12 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
*/
_tlbie(address, 0 /* 8xx doesn't care about PID */);
#endif
- if (!PageReserved(page)
+ /* The _PAGE_USER test should really be _PAGE_EXEC, but
+ * older glibc versions execute some code from no-exec
+ * pages, which for now we are supporting. If exec-only
+ * pages are ever implemented, this will have to change.
+ */
+ if (!PageReserved(page) && (pte_val(pte) & _PAGE_USER)
&& !test_bit(PG_arch_1, &page->flags)) {
if (vma->vm_mm == current->active_mm) {
__flush_dcache_icache((void *) address);
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index c12adc3ddff..a300d254aac 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -24,6 +24,8 @@
static int numa_enabled = 1;
+static char *cmdline __initdata;
+
static int numa_debug;
#define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
@@ -39,6 +41,53 @@ static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
static int min_common_depth;
static int n_mem_addr_cells, n_mem_size_cells;
+static int __cpuinit fake_numa_create_new_node(unsigned long end_pfn,
+ unsigned int *nid)
+{
+ unsigned long long mem;
+ char *p = cmdline;
+ static unsigned int fake_nid;
+ static unsigned long long curr_boundary;
+
+ /*
+ * Modify node id, iff we started creating NUMA nodes
+ * We want to continue from where we left of the last time
+ */
+ if (fake_nid)
+ *nid = fake_nid;
+ /*
+ * In case there are no more arguments to parse, the
+ * node_id should be the same as the last fake node id
+ * (we've handled this above).
+ */
+ if (!p)
+ return 0;
+
+ mem = memparse(p, &p);
+ if (!mem)
+ return 0;
+
+ if (mem < curr_boundary)
+ return 0;
+
+ curr_boundary = mem;
+
+ if ((end_pfn << PAGE_SHIFT) > mem) {
+ /*
+ * Skip commas and spaces
+ */
+ while (*p == ',' || *p == ' ' || *p == '\t')
+ p++;
+
+ cmdline = p;
+ fake_nid++;
+ *nid = fake_nid;
+ dbg("created new fake_node with id %d\n", fake_nid);
+ return 1;
+ }
+ return 0;
+}
+
static void __cpuinit map_cpu_to_node(int cpu, int node)
{
numa_cpu_lookup_table[cpu] = node;
@@ -344,6 +393,9 @@ static void __init parse_drconf_memory(struct device_node *memory)
if (nid == 0xffff || nid >= MAX_NUMNODES)
nid = default_nid;
}
+
+ fake_numa_create_new_node(((start + lmb_size) >> PAGE_SHIFT),
+ &nid);
node_set_online(nid);
size = numa_enforce_memory_limit(start, lmb_size);
@@ -429,6 +481,8 @@ new_range:
nid = of_node_to_nid_single(memory);
if (nid < 0)
nid = default_nid;
+
+ fake_numa_create_new_node(((start + size) >> PAGE_SHIFT), &nid);
node_set_online(nid);
if (!(size = numa_enforce_memory_limit(start, size))) {
@@ -461,7 +515,7 @@ static void __init setup_nonnuma(void)
unsigned long top_of_ram = lmb_end_of_DRAM();
unsigned long total_ram = lmb_phys_mem_size();
unsigned long start_pfn, end_pfn;
- unsigned int i;
+ unsigned int i, nid = 0;
printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
top_of_ram, total_ram);
@@ -471,9 +525,11 @@ static void __init setup_nonnuma(void)
for (i = 0; i < lmb.memory.cnt; ++i) {
start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
- add_active_range(0, start_pfn, end_pfn);
+
+ fake_numa_create_new_node(end_pfn, &nid);
+ add_active_range(nid, start_pfn, end_pfn);
+ node_set_online(nid);
}
- node_set_online(0);
}
void __init dump_numa_cpu_topology(void)
@@ -675,7 +731,7 @@ void __init do_init_bootmem(void)
dbg("reserve_bootmem %lx %lx\n", physbase,
size);
reserve_bootmem_node(NODE_DATA(nid), physbase,
- size);
+ size, BOOTMEM_DEFAULT);
}
}
@@ -702,6 +758,10 @@ static int __init early_numa(char *p)
if (strstr(p, "debug"))
numa_debug = 1;
+ p = strstr(p, "fake=");
+ if (p)
+ cmdline = p + strlen("fake=");
+
return 0;
}
early_param("numa", early_numa);
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 64488723162..ac3390f8190 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -86,7 +86,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return ret;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_pages((unsigned long)pgd, PGDIR_ORDER);
}
@@ -107,23 +107,24 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add
return pte;
}
-struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *ptepage;
#ifdef CONFIG_HIGHPTE
- gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
+ gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT | __GFP_ZERO;
#else
- gfp_t flags = GFP_KERNEL | __GFP_REPEAT;
+ gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
#endif
ptepage = alloc_pages(flags, 0);
- if (ptepage)
- clear_highpage(ptepage);
+ if (!ptepage)
+ return NULL;
+ pgtable_page_ctor(ptepage);
return ptepage;
}
-void pte_free_kernel(pte_t *pte)
+void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
#ifdef CONFIG_SMP
hash_page_sync();
@@ -131,11 +132,12 @@ void pte_free_kernel(pte_t *pte)
free_page((unsigned long)pte);
}
-void pte_free(struct page *ptepage)
+void pte_free(struct mm_struct *mm, pgtable_t ptepage)
{
#ifdef CONFIG_SMP
hash_page_sync();
#endif
+ pgtable_page_dtor(ptepage);
__free_page(ptepage);
}
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index c5f64c3bd66..2ef6b0dddd8 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -15,5 +15,5 @@ oprofile-$(CONFIG_OPROFILE_CELL) += op_model_cell.o \
cell/spu_profiler.o cell/vma_map.o \
cell/spu_task_sync.o
oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o
-oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
+oprofile-$(CONFIG_FSL_EMB_PERFMON) += op_model_fsl_emb.o
oprofile-$(CONFIG_6xx) += op_model_7450.o
diff --git a/arch/powerpc/oprofile/cell/spu_task_sync.c b/arch/powerpc/oprofile/cell/spu_task_sync.c
index 4a890cb42b9..257b13cb18a 100644
--- a/arch/powerpc/oprofile/cell/spu_task_sync.c
+++ b/arch/powerpc/oprofile/cell/spu_task_sync.c
@@ -198,14 +198,13 @@ out:
* dcookie user still being registered (namely, the reader
* of the event buffer).
*/
-static inline unsigned long fast_get_dcookie(struct dentry *dentry,
- struct vfsmount *vfsmnt)
+static inline unsigned long fast_get_dcookie(struct path *path)
{
unsigned long cookie;
- if (dentry->d_cookie)
- return (unsigned long)dentry;
- get_dcookie(dentry, vfsmnt, &cookie);
+ if (path->dentry->d_cookie)
+ return (unsigned long)path->dentry;
+ get_dcookie(path, &cookie);
return cookie;
}
@@ -240,8 +239,7 @@ get_exec_dcookie_and_offset(struct spu *spu, unsigned int *offsetp,
continue;
if (!(vma->vm_flags & VM_EXECUTABLE))
continue;
- app_cookie = fast_get_dcookie(vma->vm_file->f_dentry,
- vma->vm_file->f_vfsmnt);
+ app_cookie = fast_get_dcookie(&vma->vm_file->f_path);
pr_debug("got dcookie for %s\n",
vma->vm_file->f_dentry->d_name.name);
app = vma->vm_file;
@@ -262,8 +260,7 @@ get_exec_dcookie_and_offset(struct spu *spu, unsigned int *offsetp,
break;
}
- *spu_bin_dcookie = fast_get_dcookie(vma->vm_file->f_dentry,
- vma->vm_file->f_vfsmnt);
+ *spu_bin_dcookie = fast_get_dcookie(&vma->vm_file->f_path);
pr_debug("got dcookie for %s\n", vma->vm_file->f_dentry->d_name.name);
up_read(&mm->mmap_sem);
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index a28cce1d6c2..4908dc98f9c 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -202,9 +202,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
model = &op_model_7450;
break;
#endif
-#ifdef CONFIG_FSL_BOOKE
- case PPC_OPROFILE_BOOKE:
- model = &op_model_fsl_booke;
+#if defined(CONFIG_FSL_EMB_PERFMON)
+ case PPC_OPROFILE_FSL_EMB:
+ model = &op_model_fsl_emb;
break;
#endif
default:
diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_emb.c
index 183a28bb181..91596f6ba1f 100644
--- a/arch/powerpc/oprofile/op_model_fsl_booke.c
+++ b/arch/powerpc/oprofile/op_model_fsl_emb.c
@@ -1,7 +1,5 @@
/*
- * arch/powerpc/oprofile/op_model_fsl_booke.c
- *
- * Freescale Book-E oprofile support, based on ppc64 oprofile support
+ * Freescale Embedded oprofile support, based on ppc64 oprofile support
* Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
*
* Copyright (c) 2004 Freescale Semiconductor, Inc
@@ -22,7 +20,7 @@
#include <asm/system.h>
#include <asm/processor.h>
#include <asm/cputable.h>
-#include <asm/reg_booke.h>
+#include <asm/reg_fsl_emb.h>
#include <asm/page.h>
#include <asm/pmc.h>
#include <asm/oprofile_impl.h>
@@ -244,7 +242,7 @@ static void dump_pmcs(void)
mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3));
}
-static int fsl_booke_cpu_setup(struct op_counter_config *ctr)
+static int fsl_emb_cpu_setup(struct op_counter_config *ctr)
{
int i;
@@ -262,7 +260,7 @@ static int fsl_booke_cpu_setup(struct op_counter_config *ctr)
return 0;
}
-static int fsl_booke_reg_setup(struct op_counter_config *ctr,
+static int fsl_emb_reg_setup(struct op_counter_config *ctr,
struct op_system_config *sys,
int num_ctrs)
{
@@ -281,7 +279,7 @@ static int fsl_booke_reg_setup(struct op_counter_config *ctr,
return 0;
}
-static int fsl_booke_start(struct op_counter_config *ctr)
+static int fsl_emb_start(struct op_counter_config *ctr)
{
int i;
@@ -315,7 +313,7 @@ static int fsl_booke_start(struct op_counter_config *ctr)
return 0;
}
-static void fsl_booke_stop(void)
+static void fsl_emb_stop(void)
{
/* freeze counters */
pmc_stop_ctrs();
@@ -329,7 +327,7 @@ static void fsl_booke_stop(void)
}
-static void fsl_booke_handle_interrupt(struct pt_regs *regs,
+static void fsl_emb_handle_interrupt(struct pt_regs *regs,
struct op_counter_config *ctr)
{
unsigned long pc;
@@ -362,10 +360,10 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs,
pmc_start_ctrs(1);
}
-struct op_powerpc_model op_model_fsl_booke = {
- .reg_setup = fsl_booke_reg_setup,
- .cpu_setup = fsl_booke_cpu_setup,
- .start = fsl_booke_start,
- .stop = fsl_booke_stop,
- .handle_interrupt = fsl_booke_handle_interrupt,
+struct op_powerpc_model op_model_fsl_emb = {
+ .reg_setup = fsl_emb_reg_setup,
+ .cpu_setup = fsl_emb_cpu_setup,
+ .start = fsl_emb_start,
+ .stop = fsl_emb_stop,
+ .handle_interrupt = fsl_emb_handle_interrupt,
};
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
index 74f31177e47..a9260e21451 100644
--- a/arch/powerpc/platforms/40x/Kconfig
+++ b/arch/powerpc/platforms/40x/Kconfig
@@ -72,6 +72,7 @@ config WALNUT
default y
select 405GP
select PCI
+ select OF_RTC
help
This option enables support for the IBM PPC405GP evaluation board.
diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c
index 88b66444dfb..0422590040d 100644
--- a/arch/powerpc/platforms/40x/virtex.c
+++ b/arch/powerpc/platforms/40x/virtex.c
@@ -37,7 +37,7 @@ static int __init virtex_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (!of_flat_dt_is_compatible(root, "xilinx,virtex"))
+ if (!of_flat_dt_is_compatible(root, "xlnx,virtex"))
return 0;
return 1;
diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c
index 5d9edd917f9..b8b257efeb7 100644
--- a/arch/powerpc/platforms/40x/walnut.c
+++ b/arch/powerpc/platforms/40x/walnut.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/of_platform.h>
+#include <linux/rtc.h>
#include <asm/machdep.h>
#include <asm/prom.h>
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
index 8f01563dbd2..da5b7b7599d 100644
--- a/arch/powerpc/platforms/44x/warp.c
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -137,7 +137,7 @@ static int __init pika_dtm_start(void)
}
of_node_put(np);
- fpga = ioremap(res.start + 0x20, 4);
+ fpga = ioremap(res.start, 0x24);
if (fpga == NULL)
return -ENOENT;
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
new file mode 100644
index 00000000000..4c0da0c079e
--- /dev/null
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -0,0 +1,19 @@
+config PPC_MPC512x
+ bool
+ select FSL_SOC
+ select IPIC
+ default n
+
+config PPC_MPC5121
+ bool
+ select PPC_MPC512x
+ default n
+
+config MPC5121_ADS
+ bool "Freescale MPC5121E ADS"
+ depends on PPC_MULTIPLATFORM && PPC32
+ select DEFAULT_UIMAGE
+ select PPC_MPC5121
+ help
+ This option enables support for the MPC5121E ADS board.
+ default n
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
new file mode 100644
index 00000000000..232c89f2039
--- /dev/null
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for the Freescale PowerPC 512x linux kernel.
+#
+obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c
new file mode 100644
index 00000000000..50bd3a31902
--- /dev/null
+++ b/arch/powerpc/platforms/512x/mpc5121_ads.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: John Rigby, <jrigby@freescale.com>, Thur Mar 29 2007
+ *
+ * Description:
+ * MPC5121 ADS board setup
+ *
+ * This 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/kernel.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+
+/**
+ * mpc512x_find_ips_freq - Find the IPS bus frequency for a device
+ * @node: device node
+ *
+ * Returns IPS bus frequency, or 0 if the bus frequency cannot be found.
+ */
+unsigned long
+mpc512x_find_ips_freq(struct device_node *node)
+{
+ struct device_node *np;
+ const unsigned int *p_ips_freq = NULL;
+
+ of_node_get(node);
+ while (node) {
+ p_ips_freq = of_get_property(node, "bus-frequency", NULL);
+ if (p_ips_freq)
+ break;
+
+ np = of_get_parent(node);
+ of_node_put(node);
+ node = np;
+ }
+ if (node)
+ of_node_put(node);
+
+ return p_ips_freq ? *p_ips_freq : 0;
+}
+EXPORT_SYMBOL(mpc512x_find_ips_freq);
+
+static struct of_device_id __initdata of_bus_ids[] = {
+ { .name = "soc", },
+ { .name = "localbus", },
+ {},
+};
+
+static void __init mpc5121_ads_declare_of_platform_devices(void)
+{
+ /* Find every child of the SOC node and add it to of_platform */
+ if (of_platform_bus_probe(NULL, of_bus_ids, NULL))
+ printk(KERN_ERR __FILE__ ": "
+ "Error while probing of_platform bus\n");
+}
+
+static void __init mpc5121_ads_init_IRQ(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,ipic");
+ if (!np)
+ return;
+
+ ipic_init(np, 0);
+ of_node_put(np);
+
+ /*
+ * Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ ipic_set_default_priority();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc5121_ads_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "fsl,mpc5121ads");
+}
+
+define_machine(mpc5121_ads) {
+ .name = "MPC5121 ADS",
+ .probe = mpc5121_ads_probe,
+ .init = mpc5121_ads_declare_of_platform_devices,
+ .init_IRQ = mpc5121_ads_init_IRQ,
+ .get_irq = ipic_get_irq,
+ .calibrate_decr = generic_calibrate_decr,
+};
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
index 515f244c90b..cf945d55c27 100644
--- a/arch/powerpc/platforms/52xx/Kconfig
+++ b/arch/powerpc/platforms/52xx/Kconfig
@@ -8,7 +8,6 @@ config PPC_MPC5200_SIMPLE
bool "Generic support for simple MPC5200 based boards"
depends on PPC_MPC52xx
select DEFAULT_UIMAGE
- select WANT_DEVICE_TREE
help
This option enables support for a simple MPC52xx based boards which
do not need a custom platform specific setup. Such boards are
@@ -35,7 +34,6 @@ config PPC_LITE5200
bool "Freescale Lite5200 Eval Board"
depends on PPC_MPC52xx
select DEFAULT_UIMAGE
- select WANT_DEVICE_TREE
config PPC_MPC5200_BUGFIX
bool "MPC5200 (L25R) bugfix support"
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c
index 3fce6b375db..7d301875198 100644
--- a/arch/powerpc/platforms/82xx/mpc8272_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c
@@ -134,13 +134,12 @@ static void __init mpc8272_ads_setup_arch(void)
}
bcsr = of_iomap(np, 0);
+ of_node_put(np);
if (!bcsr) {
printk(KERN_ERR "Cannot map BCSR registers\n");
return;
}
- of_node_put(np);
-
clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN);
setbits32(&bcsr[1], BCSR1_FETH_RST);
diff --git a/arch/powerpc/platforms/82xx/pq2fads.c b/arch/powerpc/platforms/82xx/pq2fads.c
index 68196e34999..e1dceeec499 100644
--- a/arch/powerpc/platforms/82xx/pq2fads.c
+++ b/arch/powerpc/platforms/82xx/pq2fads.c
@@ -130,13 +130,12 @@ static void __init pq2fads_setup_arch(void)
}
bcsr = of_iomap(np, 0);
+ of_node_put(np);
if (!bcsr) {
printk(KERN_ERR "Cannot map BCSR registers\n");
return;
}
- of_node_put(np);
-
/* Enable the serial and ethernet ports */
clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN);
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index 9f0fd88b2b1..e7f706b624f 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -101,7 +101,7 @@ static void __init mpc832x_rdb_setup_arch(void)
#ifdef CONFIG_QUICC_ENGINE
qe_reset();
- if ((np = of_find_node_by_name(np, "par_io")) != NULL) {
+ if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
par_io_init(np);
of_node_put(np);
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 88bb748aff0..68065e62fc3 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -14,6 +14,8 @@
#define MPC83XX_SCCR_USB_DRCM_11 0x00300000
#define MPC83XX_SCCR_USB_DRCM_01 0x00100000
#define MPC83XX_SCCR_USB_DRCM_10 0x00200000
+#define MPC8315_SCCR_USB_MASK 0x00c00000
+#define MPC8315_SCCR_USB_DRCM_11 0x00c00000
#define MPC837X_SCCR_USB_DRCM_11 0x00c00000
/* system i/o configuration register low */
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
index 681230a30ac..471fdd8f410 100644
--- a/arch/powerpc/platforms/83xx/usb.c
+++ b/arch/powerpc/platforms/83xx/usb.c
@@ -104,6 +104,7 @@ int mpc831x_usb_cfg(void)
u32 temp;
void __iomem *immap, *usb_regs;
struct device_node *np = NULL;
+ struct device_node *immr_node = NULL;
const void *prop;
struct resource res;
int ret = 0;
@@ -124,10 +125,15 @@ int mpc831x_usb_cfg(void)
}
/* Configure clock */
- temp = in_be32(immap + MPC83XX_SCCR_OFFS);
- temp &= ~MPC83XX_SCCR_USB_MASK;
- temp |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */
- out_be32(immap + MPC83XX_SCCR_OFFS, temp);
+ immr_node = of_get_parent(np);
+ if (immr_node && of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
+ clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
+ MPC8315_SCCR_USB_MASK,
+ MPC8315_SCCR_USB_DRCM_11);
+ else
+ clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
+ MPC83XX_SCCR_USB_MASK,
+ MPC83XX_SCCR_USB_DRCM_11);
/* Configure pin mux for ULPI. There is no pin mux for UTMI */
if (prop && !strcmp(prop, "ulpi")) {
@@ -144,6 +150,9 @@ int mpc831x_usb_cfg(void)
iounmap(immap);
+ if (immr_node)
+ of_node_put(immr_node);
+
/* Map USB SOC space */
ret = of_address_to_resource(np, 0, &res);
if (ret) {
diff --git a/arch/powerpc/platforms/8xx/adder875.c b/arch/powerpc/platforms/8xx/adder875.c
index c6bc0783c3b..82363e98f50 100644
--- a/arch/powerpc/platforms/8xx/adder875.c
+++ b/arch/powerpc/platforms/8xx/adder875.c
@@ -15,12 +15,12 @@
#include <asm/time.h>
#include <asm/machdep.h>
-#include <asm/commproc.h>
+#include <asm/cpm1.h>
#include <asm/fs_pd.h>
#include <asm/udbg.h>
#include <asm/prom.h>
-#include <sysdev/commproc.h>
+#include "mpc8xx.h"
struct cpm_pin {
int port, pin, flags;
@@ -108,7 +108,7 @@ define_machine(adder875) {
.name = "Adder MPC875",
.probe = adder875_probe,
.setup_arch = adder875_setup,
- .init_IRQ = m8xx_pic_init,
+ .init_IRQ = mpc8xx_pics_init,
.get_irq = mpc8xx_get_irq,
.restart = mpc8xx_restart,
.calibrate_decr = generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/8xx/ep88xc.c b/arch/powerpc/platforms/8xx/ep88xc.c
index a8dffa00577..7d9ac6040d6 100644
--- a/arch/powerpc/platforms/8xx/ep88xc.c
+++ b/arch/powerpc/platforms/8xx/ep88xc.c
@@ -15,7 +15,6 @@
#include <asm/machdep.h>
#include <asm/io.h>
#include <asm/udbg.h>
-#include <asm/commproc.h>
#include <asm/cpm1.h>
#include "mpc8xx.h"
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index fdce10c4f07..0afd2259554 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -15,7 +15,6 @@ config PPC_MULTIPLATFORM
config PPC_82xx
bool "Freescale 82xx"
depends on 6xx
- select WANT_DEVICE_TREE
config PPC_83xx
bool "Freescale 83xx"
@@ -23,7 +22,7 @@ config PPC_83xx
select FSL_SOC
select MPC83xx
select IPIC
- select WANT_DEVICE_TREE
+ select FSL_EMB_PERFMON
config PPC_86xx
bool "Freescale 86xx"
@@ -41,6 +40,7 @@ config CLASSIC32
source "arch/powerpc/platforms/pseries/Kconfig"
source "arch/powerpc/platforms/iseries/Kconfig"
source "arch/powerpc/platforms/chrp/Kconfig"
+source "arch/powerpc/platforms/512x/Kconfig"
source "arch/powerpc/platforms/52xx/Kconfig"
source "arch/powerpc/platforms/powermac/Kconfig"
source "arch/powerpc/platforms/prep/Kconfig"
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 7fc41104d53..73d81ce14b6 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -14,7 +14,7 @@ choice
There are five families of 32 bit PowerPC chips supported.
The most common ones are the desktop and server CPUs (601, 603,
604, 740, 750, 74xx) CPUs from Freescale and IBM, with their
- embedded 52xx/82xx/83xx/86xx counterparts.
+ embedded 512x/52xx/82xx/83xx/86xx counterparts.
The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500
(85xx) each form a family of their own that is not compatible
with the others.
@@ -22,33 +22,29 @@ choice
If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx.
config 6xx
- bool "52xx/6xx/7xx/74xx/82xx/83xx/86xx"
+ bool "512x/52xx/6xx/7xx/74xx/82xx/83xx/86xx"
select PPC_FPU
config PPC_85xx
bool "Freescale 85xx"
select E500
select FSL_SOC
- select WANT_DEVICE_TREE
select MPC85xx
config PPC_8xx
bool "Freescale 8xx"
select FSL_SOC
select 8xx
- select WANT_DEVICE_TREE
select PPC_LIB_RHEAP
config 40x
bool "AMCC 40x"
select PPC_DCR_NATIVE
- select WANT_DEVICE_TREE
select PPC_UDBG_16550
config 44x
bool "AMCC 44x"
select PPC_DCR_NATIVE
- select WANT_DEVICE_TREE
select PPC_UDBG_16550
config E200
@@ -94,6 +90,7 @@ config 8xx
bool
config E500
+ select FSL_EMB_PERFMON
bool
config PPC_FPU
@@ -115,6 +112,9 @@ config FSL_BOOKE
depends on E200 || E500
default y
+config FSL_EMB_PERFMON
+ bool
+
config PTE_64BIT
bool
depends on 44x || E500
@@ -221,7 +221,7 @@ config NR_CPUS
config NOT_COHERENT_CACHE
bool
- depends on 4xx || 8xx || E200
+ depends on 4xx || 8xx || E200 || PPC_MPC512x
default y
config CHECK_CACHE_COHERENCY
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 6d9079da5f5..a984894466d 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -11,6 +11,7 @@ endif
obj-$(CONFIG_PPC_CHRP) += chrp/
obj-$(CONFIG_40x) += 40x/
obj-$(CONFIG_44x) += 44x/
+obj-$(CONFIG_PPC_MPC512x) += 512x/
obj-$(CONFIG_PPC_MPC52xx) += 52xx/
obj-$(CONFIG_PPC_8xx) += 8xx/
obj-$(CONFIG_PPC_82xx) += 82xx/
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 3a963b4a9be..2f169991896 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -54,6 +54,13 @@ config SPU_FS_64K_LS
uses 4K pages. This can improve performances of applications
using multiple SPEs by lowering the TLB pressure on them.
+config SPU_TRACE
+ tristate "SPU event tracing support"
+ depends on SPU_FS && MARKERS
+ help
+ This option allows reading a trace of spu-related events through
+ the sputrace file in procfs.
+
config SPU_BASE
bool
default n
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 095988f13bf..d95e71dee91 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -13,7 +13,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/msi.h>
-#include <linux/reboot.h>
+#include <linux/of_platform.h>
#include <asm/dcr.h>
#include <asm/machdep.h>
@@ -65,14 +65,12 @@
struct axon_msic {
struct irq_host *irq_host;
- __le32 *fifo;
+ __le32 *fifo_virt;
+ dma_addr_t fifo_phys;
dcr_host_t dcr_host;
- struct list_head list;
u32 read_offset;
};
-static LIST_HEAD(axon_msic_list);
-
static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
{
pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
@@ -94,7 +92,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
while (msic->read_offset != write_offset) {
idx = msic->read_offset / sizeof(__le32);
- msi = le32_to_cpu(msic->fifo[idx]);
+ msi = le32_to_cpu(msic->fifo_virt[idx]);
msi &= 0xFFFF;
pr_debug("axon_msi: woff %x roff %x msi %x\n",
@@ -139,6 +137,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
tmp = dn;
dn = of_find_node_by_phandle(*ph);
+ of_node_put(tmp);
if (!dn) {
dev_dbg(&dev->dev,
"axon_msi: msi-translator doesn't point to a node\n");
@@ -156,7 +155,6 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
out_error:
of_node_put(dn);
- of_node_put(tmp);
return msic;
}
@@ -292,30 +290,24 @@ static struct irq_host_ops msic_host_ops = {
.map = msic_host_map,
};
-static int axon_msi_notify_reboot(struct notifier_block *nb,
- unsigned long code, void *data)
+static int axon_msi_shutdown(struct of_device *device)
{
- struct axon_msic *msic;
+ struct axon_msic *msic = device->dev.platform_data;
u32 tmp;
- list_for_each_entry(msic, &axon_msic_list, list) {
- pr_debug("axon_msi: disabling %s\n",
- msic->irq_host->of_node->full_name);
- tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
- tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
- msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
- }
+ pr_debug("axon_msi: disabling %s\n",
+ msic->irq_host->of_node->full_name);
+ tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
+ tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
+ msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
return 0;
}
-static struct notifier_block axon_msi_reboot_notifier = {
- .notifier_call = axon_msi_notify_reboot
-};
-
-static int axon_msi_setup_one(struct device_node *dn)
+static int axon_msi_probe(struct of_device *device,
+ const struct of_device_id *device_id)
{
- struct page *page;
+ struct device_node *dn = device->node;
struct axon_msic *msic;
unsigned int virq;
int dcr_base, dcr_len;
@@ -346,16 +338,14 @@ static int axon_msi_setup_one(struct device_node *dn)
goto out_free_msic;
}
- page = alloc_pages_node(of_node_to_nid(dn), GFP_KERNEL,
- get_order(MSIC_FIFO_SIZE_BYTES));
- if (!page) {
+ msic->fifo_virt = dma_alloc_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES,
+ &msic->fifo_phys, GFP_KERNEL);
+ if (!msic->fifo_virt) {
printk(KERN_ERR "axon_msi: couldn't allocate fifo for %s\n",
dn->full_name);
goto out_free_msic;
}
- msic->fifo = page_address(page);
-
msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP,
NR_IRQS, &msic_host_ops, 0);
if (!msic->irq_host) {
@@ -378,14 +368,18 @@ static int axon_msi_setup_one(struct device_node *dn)
pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq);
/* Enable the MSIC hardware */
- msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, (u64)msic->fifo >> 32);
+ msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32);
msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG,
- (u64)msic->fifo & 0xFFFFFFFF);
+ msic->fifo_phys & 0xFFFFFFFF);
msic_dcr_write(msic, MSIC_CTRL_REG,
MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
MSIC_CTRL_FIFO_SIZE);
- list_add(&msic->list, &axon_msic_list);
+ device->dev.platform_data = msic;
+
+ ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
+ ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
+ ppc_md.msi_check_device = axon_msi_check_device;
printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name);
@@ -394,7 +388,8 @@ static int axon_msi_setup_one(struct device_node *dn)
out_free_host:
kfree(msic->irq_host);
out_free_fifo:
- __free_pages(virt_to_page(msic->fifo), get_order(MSIC_FIFO_SIZE_BYTES));
+ dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt,
+ msic->fifo_phys);
out_free_msic:
kfree(msic);
out:
@@ -402,28 +397,24 @@ out:
return -1;
}
-static int axon_msi_init(void)
-{
- struct device_node *dn;
- int found = 0;
-
- pr_debug("axon_msi: initialising ...\n");
-
- for_each_compatible_node(dn, NULL, "ibm,axon-msic") {
- if (axon_msi_setup_one(dn) == 0)
- found++;
- }
-
- if (found) {
- ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;
- ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs;
- ppc_md.msi_check_device = axon_msi_check_device;
-
- register_reboot_notifier(&axon_msi_reboot_notifier);
+static const struct of_device_id axon_msi_device_id[] = {
+ {
+ .compatible = "ibm,axon-msic"
+ },
+ {}
+};
- pr_debug("axon_msi: registered callbacks!\n");
- }
+static struct of_platform_driver axon_msi_driver = {
+ .match_table = axon_msi_device_id,
+ .probe = axon_msi_probe,
+ .shutdown = axon_msi_shutdown,
+ .driver = {
+ .name = "axon-msi"
+ },
+};
- return 0;
+static int __init axon_msi_init(void)
+{
+ return of_register_platform_driver(&axon_msi_driver);
}
-arch_initcall(axon_msi_init);
+subsys_initcall(axon_msi_init);
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index df330666ccc..edab631a8dc 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -26,6 +26,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/notifier.h>
+#include <linux/of.h>
#include <linux/of_platform.h>
#include <asm/prom.h>
@@ -789,18 +790,16 @@ static int __init cell_iommu_init_disabled(void)
static u64 cell_iommu_get_fixed_address(struct device *dev)
{
u64 cpu_addr, size, best_size, pci_addr = OF_BAD_ADDR;
- struct device_node *tmp, *np;
+ struct device_node *np;
const u32 *ranges = NULL;
int i, len, best;
- np = dev->archdata.of_node;
- of_node_get(np);
- ranges = of_get_property(np, "dma-ranges", &len);
- while (!ranges && np) {
- tmp = of_get_parent(np);
- of_node_put(np);
- np = tmp;
+ np = of_node_get(dev->archdata.of_node);
+ while (np) {
ranges = of_get_property(np, "dma-ranges", &len);
+ if (ranges)
+ break;
+ np = of_get_next_parent(np);
}
if (!ranges) {
@@ -842,19 +841,18 @@ static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask)
if (!dev->dma_mask || !dma_supported(dev, dma_mask))
return -EIO;
- if (dma_mask == DMA_BIT_MASK(64)) {
- if (cell_iommu_get_fixed_address(dev) == OF_BAD_ADDR)
- dev_dbg(dev, "iommu: 64-bit OK, but bad addr\n");
- else {
- dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n");
- set_dma_ops(dev, &dma_iommu_fixed_ops);
- cell_dma_dev_setup(dev);
- }
+ if (dma_mask == DMA_BIT_MASK(64) &&
+ cell_iommu_get_fixed_address(dev) != OF_BAD_ADDR)
+ {
+ dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n");
+ set_dma_ops(dev, &dma_iommu_fixed_ops);
} else {
dev_dbg(dev, "iommu: not 64-bit, using default ops\n");
set_dma_ops(dev, get_pci_dma_ops());
}
+ cell_dma_dev_setup(dev);
+
*dev->dma_mask = dma_mask;
return 0;
@@ -918,6 +916,18 @@ static int __init cell_iommu_fixed_mapping_init(void)
return -1;
}
+ /* We must have dma-ranges properties for fixed mapping to work */
+ for (np = NULL; (np = of_find_all_nodes(np));) {
+ if (of_find_property(np, "dma-ranges", NULL))
+ break;
+ }
+ of_node_put(np);
+
+ if (!np) {
+ pr_debug("iommu: no dma-ranges found, no fixed mapping\n");
+ return -1;
+ }
+
/* The default setup is to have the fixed mapping sit after the
* dynamic region, so find the top of the largest IOMMU window
* on any axon, then add the size of RAM and that's our max value.
@@ -981,8 +991,8 @@ static int __init cell_iommu_fixed_mapping_init(void)
dsize = htab_size_bytes;
}
- pr_debug("iommu: setting up %d, dynamic window %lx-%lx " \
- "fixed window %lx-%lx\n", iommu->nid, dbase,
+ printk(KERN_DEBUG "iommu: node %d, dynamic window 0x%lx-0x%lx "
+ "fixed window 0x%lx-0x%lx\n", iommu->nid, dbase,
dbase + dsize, fbase, fbase + fsize);
cell_iommu_setup_page_tables(iommu, dbase, dsize, fbase, fsize);
@@ -998,8 +1008,6 @@ static int __init cell_iommu_fixed_mapping_init(void)
dma_iommu_ops.set_dma_mask = dma_set_mask_and_switch;
set_pci_dma_ops(&dma_iommu_ops);
- printk(KERN_DEBUG "IOMMU fixed mapping established.\n");
-
return 0;
}
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index b2494ebcdbe..e43024c0392 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -1,4 +1,13 @@
-#define DEBUG
+/*
+ * Copyright 2006-2008, IBM Corporation.
+ *
+ * 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.
+ */
+
+#undef DEBUG
#include <linux/types.h>
#include <linux/kernel.h>
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index e6534b519c9..a7f609b3b87 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -98,7 +98,7 @@ static int __init cell_publish_devices(void)
}
return 0;
}
-machine_device_initcall(cell, cell_publish_devices);
+machine_subsys_initcall(cell, cell_publish_devices);
static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
{
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index d3a349fb42e..99610a6361f 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -4,6 +4,8 @@ spufs-y += inode.o file.o context.o syscalls.o coredump.o
spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o
spufs-y += switch.o fault.o lscsa_alloc.o
+obj-$(CONFIG_SPU_TRACE) += sputrace.o
+
# Rules to build switch.o with the help of SPU tool chain
SPU_CROSS := spu-
SPU_CC := $(SPU_CROSS)gcc
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index 50d98a154aa..64eb15b2204 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -288,6 +288,12 @@ static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val)
spin_lock(&ctx->csa.register_lock);
ctx->csa.prob.spu_runcntl_RW = val;
if (val & SPU_RUNCNTL_RUNNABLE) {
+ ctx->csa.prob.spu_status_R &=
+ ~SPU_STATUS_STOPPED_BY_STOP &
+ ~SPU_STATUS_STOPPED_BY_HALT &
+ ~SPU_STATUS_SINGLE_STEP &
+ ~SPU_STATUS_INVALID_INSTR &
+ ~SPU_STATUS_INVALID_CH;
ctx->csa.prob.spu_status_R |= SPU_STATUS_RUNNING;
} else {
ctx->csa.prob.spu_status_R &= ~SPU_STATUS_RUNNING;
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
index eff4d291ba8..e46d300e21a 100644
--- a/arch/powerpc/platforms/cell/spufs/fault.c
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -108,7 +108,7 @@ int spufs_handle_class1(struct spu_context *ctx)
u64 ea, dsisr, access;
unsigned long flags;
unsigned flt = 0;
- int ret, ret2;
+ int ret;
/*
* dar and dsisr get passed from the registers
@@ -148,13 +148,10 @@ int spufs_handle_class1(struct spu_context *ctx)
ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt);
/*
- * If spu_acquire fails due to a pending signal we just want to return
- * EINTR to userspace even if that means missing the dma restart or
- * updating the page fault statistics.
+ * This is nasty: we need the state_mutex for all the bookkeeping even
+ * if the syscall was interrupted by a signal. ewww.
*/
- ret2 = spu_acquire(ctx);
- if (ret2)
- goto out;
+ mutex_lock(&ctx->state_mutex);
/*
* Clear dsisr under ctxt lock after handling the fault, so that
@@ -185,7 +182,6 @@ int spufs_handle_class1(struct spu_context *ctx)
} else
spufs_handle_event(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
- out:
spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
return ret;
}
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 3fcd06418b0..c66c3756970 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -29,6 +29,7 @@
#include <linux/poll.h>
#include <linux/ptrace.h>
#include <linux/seq_file.h>
+#include <linux/marker.h>
#include <asm/io.h>
#include <asm/semaphore.h>
@@ -357,6 +358,9 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
{
struct spu_context *ctx = vma->vm_file->private_data;
unsigned long area, offset = address - vma->vm_start;
+ int ret = 0;
+
+ spu_context_nospu_trace(spufs_ps_nopfn__enter, ctx);
offset += vma->vm_pgoff << PAGE_SHIFT;
if (offset >= ps_size)
@@ -375,14 +379,18 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
if (ctx->state == SPU_STATE_SAVED) {
up_read(&current->mm->mmap_sem);
- spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
+ spu_context_nospu_trace(spufs_ps_nopfn__sleep, ctx);
+ ret = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
+ spu_context_trace(spufs_ps_nopfn__wake, ctx, ctx->spu);
down_read(&current->mm->mmap_sem);
} else {
area = ctx->spu->problem_phys + ps_offs;
vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
+ spu_context_trace(spufs_ps_nopfn__insert, ctx, ctx->spu);
}
- spu_release(ctx);
+ if (!ret)
+ spu_release(ctx);
return NOPFN_REFAULT;
}
@@ -454,7 +462,7 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
if (!i->i_openers++)
ctx->cntl = inode->i_mapping;
mutex_unlock(&ctx->mapping_lock);
- return spufs_attr_open(inode, file, spufs_cntl_get,
+ return simple_attr_open(inode, file, spufs_cntl_get,
spufs_cntl_set, "0x%08lx");
}
@@ -464,7 +472,7 @@ spufs_cntl_release(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spufs_attr_release(inode, file);
+ simple_attr_release(inode, file);
mutex_lock(&ctx->mapping_lock);
if (!--i->i_openers)
@@ -476,8 +484,8 @@ spufs_cntl_release(struct inode *inode, struct file *file)
static const struct file_operations spufs_cntl_fops = {
.open = spufs_cntl_open,
.release = spufs_cntl_release,
- .read = spufs_attr_read,
- .write = spufs_attr_write,
+ .read = simple_attr_read,
+ .write = simple_attr_write,
.mmap = spufs_cntl_mmap,
};
@@ -749,23 +757,25 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
count = spu_acquire(ctx);
if (count)
- return count;
+ goto out;
/* wait only for the first element */
count = 0;
if (file->f_flags & O_NONBLOCK) {
- if (!spu_ibox_read(ctx, &ibox_data))
+ if (!spu_ibox_read(ctx, &ibox_data)) {
count = -EAGAIN;
+ goto out_unlock;
+ }
} else {
count = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
+ if (count)
+ goto out;
}
- if (count)
- goto out;
/* if we can't write at all, return -EFAULT */
count = __put_user(ibox_data, udata);
if (count)
- goto out;
+ goto out_unlock;
for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
int ret;
@@ -782,9 +792,9 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
break;
}
-out:
+out_unlock:
spu_release(ctx);
-
+out:
return count;
}
@@ -899,7 +909,7 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
count = spu_acquire(ctx);
if (count)
- return count;
+ goto out;
/*
* make sure we can at least write one element, by waiting
@@ -907,14 +917,16 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
*/
count = 0;
if (file->f_flags & O_NONBLOCK) {
- if (!spu_wbox_write(ctx, wbox_data))
+ if (!spu_wbox_write(ctx, wbox_data)) {
count = -EAGAIN;
+ goto out_unlock;
+ }
} else {
count = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
+ if (count)
+ goto out;
}
- if (count)
- goto out;
/* write as much as possible */
for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
@@ -928,8 +940,9 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
break;
}
-out:
+out_unlock:
spu_release(ctx);
+out:
return count;
}
@@ -1592,12 +1605,11 @@ static ssize_t spufs_mfc_read(struct file *file, char __user *buffer,
} else {
ret = spufs_wait(ctx->mfc_wq,
spufs_read_mfc_tagstatus(ctx, &status));
+ if (ret)
+ goto out;
}
spu_release(ctx);
- if (ret)
- goto out;
-
ret = 4;
if (copy_to_user(buffer, &status, 4))
ret = -EFAULT;
@@ -1726,6 +1738,8 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
int status;
ret = spufs_wait(ctx->mfc_wq,
spu_send_mfc_command(ctx, cmd, &status));
+ if (ret)
+ goto out;
if (status)
ret = status;
}
@@ -1779,7 +1793,7 @@ static int spufs_mfc_flush(struct file *file, fl_owner_t id)
ret = spu_acquire(ctx);
if (ret)
- return ret;
+ goto out;
#if 0
/* this currently hangs */
ret = spufs_wait(ctx->mfc_wq,
@@ -1788,12 +1802,13 @@ static int spufs_mfc_flush(struct file *file, fl_owner_t id)
goto out;
ret = spufs_wait(ctx->mfc_wq,
ctx->ops->read_mfc_tagstatus(ctx) == ctx->tagwait);
-out:
+ if (ret)
+ goto out;
#else
ret = 0;
#endif
spu_release(ctx);
-
+out:
return ret;
}
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index c0e968a4c21..6d1228c66c5 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -1,3 +1,4 @@
+
/*
* SPU file system
*
@@ -322,7 +323,7 @@ static struct spu_context *
spufs_assert_affinity(unsigned int flags, struct spu_gang *gang,
struct file *filp)
{
- struct spu_context *tmp, *neighbor;
+ struct spu_context *tmp, *neighbor, *err;
int count, node;
int aff_supp;
@@ -354,11 +355,15 @@ spufs_assert_affinity(unsigned int flags, struct spu_gang *gang,
if (!list_empty(&neighbor->aff_list) && !(neighbor->aff_head) &&
!list_is_last(&neighbor->aff_list, &gang->aff_list_head) &&
!list_entry(neighbor->aff_list.next, struct spu_context,
- aff_list)->aff_head)
- return ERR_PTR(-EEXIST);
+ aff_list)->aff_head) {
+ err = ERR_PTR(-EEXIST);
+ goto out_put_neighbor;
+ }
- if (gang != neighbor->gang)
- return ERR_PTR(-EINVAL);
+ if (gang != neighbor->gang) {
+ err = ERR_PTR(-EINVAL);
+ goto out_put_neighbor;
+ }
count = 1;
list_for_each_entry(tmp, &gang->aff_list_head, aff_list)
@@ -372,11 +377,17 @@ spufs_assert_affinity(unsigned int flags, struct spu_gang *gang,
break;
}
- if (node == MAX_NUMNODES)
- return ERR_PTR(-EEXIST);
+ if (node == MAX_NUMNODES) {
+ err = ERR_PTR(-EEXIST);
+ goto out_put_neighbor;
+ }
}
return neighbor;
+
+out_put_neighbor:
+ put_spu_context(neighbor);
+ return err;
}
static void
@@ -454,9 +465,12 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
if (ret)
goto out_aff_unlock;
- if (affinity)
+ if (affinity) {
spufs_set_affinity(flags, SPUFS_I(dentry->d_inode)->i_ctx,
neighbor);
+ if (neighbor)
+ put_spu_context(neighbor);
+ }
/*
* get references for dget and mntget, will be released
@@ -579,7 +593,7 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
ret = -EINVAL;
/* check if we are on spufs */
- if (nd->dentry->d_sb->s_type != &spufs_type)
+ if (nd->path.dentry->d_sb->s_type != &spufs_type)
goto out;
/* don't accept undefined flags */
@@ -587,9 +601,9 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
goto out;
/* only threads can be underneath a gang */
- if (nd->dentry != nd->dentry->d_sb->s_root) {
+ if (nd->path.dentry != nd->path.dentry->d_sb->s_root) {
if ((flags & SPU_CREATE_GANG) ||
- !SPUFS_I(nd->dentry->d_inode)->i_gang)
+ !SPUFS_I(nd->path.dentry->d_inode)->i_gang)
goto out;
}
@@ -605,16 +619,17 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
mode &= ~current->fs->umask;
if (flags & SPU_CREATE_GANG)
- return spufs_create_gang(nd->dentry->d_inode,
- dentry, nd->mnt, mode);
+ return spufs_create_gang(nd->path.dentry->d_inode,
+ dentry, nd->path.mnt, mode);
else
- return spufs_create_context(nd->dentry->d_inode,
- dentry, nd->mnt, flags, mode, filp);
+ return spufs_create_context(nd->path.dentry->d_inode,
+ dentry, nd->path.mnt, flags, mode,
+ filp);
out_dput:
dput(dentry);
out_dir:
- mutex_unlock(&nd->dentry->d_inode->i_mutex);
+ mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
out:
return ret;
}
@@ -742,8 +757,11 @@ spufs_fill_super(struct super_block *sb, void *data, int silent)
.statfs = simple_statfs,
.delete_inode = spufs_delete_inode,
.drop_inode = generic_delete_inode,
+ .show_options = generic_show_options,
};
+ save_mount_options(sb, data);
+
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index c01a09da1e5..fca22e18069 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -53,7 +53,7 @@ int spu_stopped(struct spu_context *ctx, u32 *stat)
stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP |
SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP;
- if (*stat & stopped)
+ if (!(*stat & SPU_STATUS_RUNNING) && (*stat & stopped))
return 1;
dsisr = ctx->csa.dsisr;
@@ -354,8 +354,15 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
do {
ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status));
- if (unlikely(ret))
+ if (unlikely(ret)) {
+ /*
+ * This is nasty: we need the state_mutex for all the
+ * bookkeeping even if the syscall was interrupted by
+ * a signal. ewww.
+ */
+ mutex_lock(&ctx->state_mutex);
break;
+ }
spu = ctx->spu;
if (unlikely(test_and_clear_bit(SPU_SCHED_NOTIFY_ACTIVE,
&ctx->sched_flags))) {
@@ -388,16 +395,14 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
SPU_STATUS_STOPPED_BY_HALT |
SPU_STATUS_SINGLE_STEP)));
- if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
- (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100) &&
- (ctx->state == SPU_STATE_RUNNABLE))
- ctx->stats.libassist++;
-
-
spu_disable_spu(ctx);
ret = spu_run_fini(ctx, npc, &status);
spu_yield(ctx);
+ if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
+ (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100))
+ ctx->stats.libassist++;
+
if ((ret == 0) ||
((ret == -ERESTARTSYS) &&
((status & SPU_STATUS_STOPPED_BY_HALT) ||
@@ -410,8 +415,11 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
* since we have TIF_SINGLESTEP set, thus the kernel will do
* it upon return from the syscall anyawy
*/
- if ((status & SPU_STATUS_STOPPED_BY_STOP)
- && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
+ if (unlikely(status & SPU_STATUS_SINGLE_STEP))
+ ret = -ERESTARTSYS;
+
+ else if (unlikely((status & SPU_STATUS_STOPPED_BY_STOP)
+ && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff)) {
force_sig(SIGTRAP, current);
ret = -ERESTARTSYS;
}
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 00d914232af..5915343e259 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -39,6 +39,7 @@
#include <linux/pid_namespace.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/marker.h>
#include <asm/io.h>
#include <asm/mmu_context.h>
@@ -216,8 +217,8 @@ void do_notify_spus_active(void)
*/
static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
{
- pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
- spu->number, spu->node);
+ spu_context_trace(spu_bind_context__enter, ctx, spu);
+
spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
if (ctx->flags & SPU_CREATE_NOSCHED)
@@ -399,8 +400,8 @@ static int has_affinity(struct spu_context *ctx)
*/
static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
{
- pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
- spu->pid, spu->number, spu->node);
+ spu_context_trace(spu_unbind_context__enter, ctx, spu);
+
spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
if (spu->ctx->flags & SPU_CREATE_NOSCHED)
@@ -528,6 +529,8 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
struct spu *spu, *aff_ref_spu;
int node, n;
+ spu_context_nospu_trace(spu_get_idle__enter, ctx);
+
if (ctx->gang) {
mutex_lock(&ctx->gang->aff_mutex);
if (has_affinity(ctx)) {
@@ -546,8 +549,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
if (atomic_dec_and_test(&ctx->gang->aff_sched_count))
ctx->gang->aff_ref_spu = NULL;
mutex_unlock(&ctx->gang->aff_mutex);
-
- return NULL;
+ goto not_found;
}
mutex_unlock(&ctx->gang->aff_mutex);
}
@@ -565,12 +567,14 @@ static struct spu *spu_get_idle(struct spu_context *ctx)
mutex_unlock(&cbe_spu_info[node].list_mutex);
}
+ not_found:
+ spu_context_nospu_trace(spu_get_idle__not_found, ctx);
return NULL;
found:
spu->alloc_state = SPU_USED;
mutex_unlock(&cbe_spu_info[node].list_mutex);
- pr_debug("Got SPU %d %d\n", spu->number, spu->node);
+ spu_context_trace(spu_get_idle__found, ctx, spu);
spu_init_channels(spu);
return spu;
}
@@ -587,6 +591,8 @@ static struct spu *find_victim(struct spu_context *ctx)
struct spu *spu;
int node, n;
+ spu_context_nospu_trace(spu_find_vitim__enter, ctx);
+
/*
* Look for a possible preemption candidate on the local node first.
* If there is no candidate look at the other nodes. This isn't
@@ -640,6 +646,8 @@ static struct spu *find_victim(struct spu_context *ctx)
goto restart;
}
+ spu_context_trace(__spu_deactivate__unload, ctx, spu);
+
mutex_lock(&cbe_spu_info[node].list_mutex);
cbe_spu_info[node].nr_active--;
spu_unbind_context(spu, victim);
@@ -822,6 +830,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
*/
void spu_deactivate(struct spu_context *ctx)
{
+ spu_context_nospu_trace(spu_deactivate__enter, ctx);
__spu_deactivate(ctx, 1, MAX_PRIO);
}
@@ -835,6 +844,7 @@ void spu_deactivate(struct spu_context *ctx)
*/
void spu_yield(struct spu_context *ctx)
{
+ spu_context_nospu_trace(spu_yield__enter, ctx);
if (!(ctx->flags & SPU_CREATE_NOSCHED)) {
mutex_lock(&ctx->state_mutex);
__spu_deactivate(ctx, 0, MAX_PRIO);
@@ -864,11 +874,15 @@ static noinline void spusched_tick(struct spu_context *ctx)
goto out;
spu = ctx->spu;
+
+ spu_context_trace(spusched_tick__preempt, ctx, spu);
+
new = grab_runnable_context(ctx->prio + 1, spu->node);
if (new) {
spu_unschedule(spu, ctx);
spu_add_to_rq(ctx);
} else {
+ spu_context_nospu_trace(spusched_tick__newslice, ctx);
ctx->time_slice++;
}
out:
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 0e114038ea6..2c2fe3c07d7 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -268,6 +268,9 @@ extern char *isolated_loader;
* Same as wait_event_interruptible(), except that here
* we need to call spu_release(ctx) before sleeping, and
* then spu_acquire(ctx) when awoken.
+ *
+ * Returns with state_mutex re-acquired when successfull or
+ * with -ERESTARTSYS and the state_mutex dropped when interrupted.
*/
#define spufs_wait(wq, condition) \
@@ -278,11 +281,11 @@ extern char *isolated_loader;
prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \
if (condition) \
break; \
+ spu_release(ctx); \
if (signal_pending(current)) { \
__ret = -ERESTARTSYS; \
break; \
} \
- spu_release(ctx); \
schedule(); \
__ret = spu_acquire(ctx); \
if (__ret) \
@@ -325,4 +328,9 @@ extern void spu_free_lscsa(struct spu_state *csa);
extern void spuctx_switch_state(struct spu_context *ctx,
enum spu_utilization_state new_state);
+#define spu_context_trace(name, ctx, spu) \
+ trace_mark(name, "%p %p", ctx, spu);
+#define spu_context_nospu_trace(name, ctx) \
+ trace_mark(name, "%p", ctx);
+
#endif
diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c
new file mode 100644
index 00000000000..01974f7776e
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/sputrace.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2007 IBM Deutschland Entwicklung GmbH
+ * Released under GPL v2.
+ *
+ * Partially based on net/ipv4/tcp_probe.c.
+ *
+ * Simple tracing facility for spu contexts.
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/marker.h>
+#include <linux/proc_fs.h>
+#include <linux/wait.h>
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+#include "spufs.h"
+
+struct spu_probe {
+ const char *name;
+ const char *format;
+ marker_probe_func *probe_func;
+};
+
+struct sputrace {
+ ktime_t tstamp;
+ int owner_tid; /* owner */
+ int curr_tid;
+ const char *name;
+ int number;
+};
+
+static int bufsize __read_mostly = 16384;
+MODULE_PARM_DESC(bufsize, "Log buffer size (number of records)");
+module_param(bufsize, int, 0);
+
+
+static DEFINE_SPINLOCK(sputrace_lock);
+static DECLARE_WAIT_QUEUE_HEAD(sputrace_wait);
+static ktime_t sputrace_start;
+static unsigned long sputrace_head, sputrace_tail;
+static struct sputrace *sputrace_log;
+
+static int sputrace_used(void)
+{
+ return (sputrace_head - sputrace_tail) % bufsize;
+}
+
+static inline int sputrace_avail(void)
+{
+ return bufsize - sputrace_used();
+}
+
+static int sputrace_sprint(char *tbuf, int n)
+{
+ const struct sputrace *t = sputrace_log + sputrace_tail % bufsize;
+ struct timespec tv =
+ ktime_to_timespec(ktime_sub(t->tstamp, sputrace_start));
+
+ return snprintf(tbuf, n,
+ "[%lu.%09lu] %d: %s (thread = %d, spu = %d)\n",
+ (unsigned long) tv.tv_sec,
+ (unsigned long) tv.tv_nsec,
+ t->owner_tid,
+ t->name,
+ t->curr_tid,
+ t->number);
+}
+
+static ssize_t sputrace_read(struct file *file, char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ int error = 0, cnt = 0;
+
+ if (!buf || len < 0)
+ return -EINVAL;
+
+ while (cnt < len) {
+ char tbuf[128];
+ int width;
+
+ error = wait_event_interruptible(sputrace_wait,
+ sputrace_used() > 0);
+ if (error)
+ break;
+
+ spin_lock(&sputrace_lock);
+ if (sputrace_head == sputrace_tail) {
+ spin_unlock(&sputrace_lock);
+ continue;
+ }
+
+ width = sputrace_sprint(tbuf, sizeof(tbuf));
+ if (width < len)
+ sputrace_tail = (sputrace_tail + 1) % bufsize;
+ spin_unlock(&sputrace_lock);
+
+ if (width >= len)
+ break;
+
+ error = copy_to_user(buf + cnt, tbuf, width);
+ if (error)
+ break;
+ cnt += width;
+ }
+
+ return cnt == 0 ? error : cnt;
+}
+
+static int sputrace_open(struct inode *inode, struct file *file)
+{
+ spin_lock(&sputrace_lock);
+ sputrace_head = sputrace_tail = 0;
+ sputrace_start = ktime_get();
+ spin_unlock(&sputrace_lock);
+
+ return 0;
+}
+
+static const struct file_operations sputrace_fops = {
+ .owner = THIS_MODULE,
+ .open = sputrace_open,
+ .read = sputrace_read,
+};
+
+static void sputrace_log_item(const char *name, struct spu_context *ctx,
+ struct spu *spu)
+{
+ spin_lock(&sputrace_lock);
+ if (sputrace_avail() > 1) {
+ struct sputrace *t = sputrace_log + sputrace_head;
+
+ t->tstamp = ktime_get();
+ t->owner_tid = ctx->tid;
+ t->name = name;
+ t->curr_tid = current->pid;
+ t->number = spu ? spu->number : -1;
+
+ sputrace_head = (sputrace_head + 1) % bufsize;
+ } else {
+ printk(KERN_WARNING
+ "sputrace: lost samples due to full buffer.\n");
+ }
+ spin_unlock(&sputrace_lock);
+
+ wake_up(&sputrace_wait);
+}
+
+static void spu_context_event(void *probe_private, void *call_data,
+ const char *format, va_list *args)
+{
+ struct spu_probe *p = probe_private;
+ struct spu_context *ctx;
+ struct spu *spu;
+
+ ctx = va_arg(*args, struct spu_context *);
+ spu = va_arg(*args, struct spu *);
+
+ sputrace_log_item(p->name, ctx, spu);
+}
+
+static void spu_context_nospu_event(void *probe_private, void *call_data,
+ const char *format, va_list *args)
+{
+ struct spu_probe *p = probe_private;
+ struct spu_context *ctx;
+
+ ctx = va_arg(*args, struct spu_context *);
+
+ sputrace_log_item(p->name, ctx, NULL);
+}
+
+struct spu_probe spu_probes[] = {
+ { "spu_bind_context__enter", "%p %p", spu_context_event },
+ { "spu_unbind_context__enter", "%p %p", spu_context_event },
+ { "spu_get_idle__enter", "%p", spu_context_nospu_event },
+ { "spu_get_idle__found", "%p %p", spu_context_event },
+ { "spu_get_idle__not_found", "%p", spu_context_nospu_event },
+ { "spu_find_victim__enter", "%p", spu_context_nospu_event },
+ { "spusched_tick__preempt", "%p %p", spu_context_event },
+ { "spusched_tick__newslice", "%p", spu_context_nospu_event },
+ { "spu_yield__enter", "%p", spu_context_nospu_event },
+ { "spu_deactivate__enter", "%p", spu_context_nospu_event },
+ { "__spu_deactivate__unload", "%p %p", spu_context_event },
+ { "spufs_ps_nopfn__enter", "%p", spu_context_nospu_event },
+ { "spufs_ps_nopfn__sleep", "%p", spu_context_nospu_event },
+ { "spufs_ps_nopfn__wake", "%p %p", spu_context_event },
+ { "spufs_ps_nopfn__insert", "%p %p", spu_context_event },
+ { "spu_acquire_saved__enter", "%p", spu_context_nospu_event },
+ { "destroy_spu_context__enter", "%p", spu_context_nospu_event },
+};
+
+static int __init sputrace_init(void)
+{
+ struct proc_dir_entry *entry;
+ int i, error = -ENOMEM;
+
+ sputrace_log = kcalloc(sizeof(struct sputrace),
+ bufsize, GFP_KERNEL);
+ if (!sputrace_log)
+ goto out;
+
+ entry = create_proc_entry("sputrace", S_IRUSR, NULL);
+ if (!entry)
+ goto out_free_log;
+ entry->proc_fops = &sputrace_fops;
+
+ for (i = 0; i < ARRAY_SIZE(spu_probes); i++) {
+ struct spu_probe *p = &spu_probes[i];
+
+ error = marker_probe_register(p->name, p->format,
+ p->probe_func, p);
+ if (error)
+ printk(KERN_INFO "Unable to register probe %s\n",
+ p->name);
+ }
+
+ return 0;
+
+out_free_log:
+ kfree(sputrace_log);
+out:
+ return -ENOMEM;
+}
+
+static void __exit sputrace_exit(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(spu_probes); i++)
+ marker_probe_unregister(spu_probes[i].name,
+ spu_probes[i].probe_func, &spu_probes[i]);
+
+ remove_proc_entry("sputrace", NULL);
+ kfree(sputrace_log);
+}
+
+module_init(sputrace_init);
+module_exit(sputrace_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index 43040441317..49c87769b1f 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -73,7 +73,7 @@ static long do_spu_create(const char __user *pathname, unsigned int flags,
LOOKUP_OPEN|LOOKUP_CREATE, &nd);
if (!ret) {
ret = spufs_create(&nd, flags, mode, neighbor);
- path_release(&nd);
+ path_put(&nd.path);
}
putname(tmp);
}
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 6c808375793..42908896781 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -24,7 +24,6 @@ config STORCENTER
select MPIC
select FSL_SOC
select PPC_UDBG_16550 if SERIAL_8250
- select WANT_DEVICE_TREE
select MPC10X_OPENPIC
select MPC10X_BRIDGE
help
@@ -37,7 +36,6 @@ config MPC7448HPC2
select TSI108_BRIDGE
select DEFAULT_UIMAGE
select PPC_UDBG_16550
- select WANT_DEVICE_TREE
select TSI108_BRIDGE
help
Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
@@ -48,7 +46,6 @@ config PPC_HOLLY
depends on EMBEDDED6xx
select TSI108_BRIDGE
select PPC_UDBG_16550
- select WANT_DEVICE_TREE
select TSI108_BRIDGE
help
Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval
@@ -59,7 +56,6 @@ config PPC_PRPMC2800
depends on EMBEDDED6xx
select MV64X60
select NOT_COHERENT_CACHE
- select WANT_DEVICE_TREE
help
This option enables support for the Motorola PrPMC2800 board
diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c
index e12e9d29871..8864e488498 100644
--- a/arch/powerpc/platforms/embedded6xx/storcenter.c
+++ b/arch/powerpc/platforms/embedded6xx/storcenter.c
@@ -132,33 +132,18 @@ static void __init storcenter_init_IRQ(void)
paddr = (phys_addr_t)of_translate_address(dnp, prop);
mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET,
- 4, 32, " EPIC ");
+ 16, 32, " OpenPIC ");
of_node_put(dnp);
BUG_ON(mpic == NULL);
- /* PCI IRQs */
/*
- * 2.6.12 patch:
- * openpic_set_sources(0, 5, OpenPIC_Addr + 0x10200);
- * openpic_set_sources(5, 2, OpenPIC_Addr + 0x11120);
- * first_irq, num_irqs, __iomem first_ISR
- * o_ss: i, src: 0, fdf50200
- * o_ss: i, src: 1, fdf50220
- * o_ss: i, src: 2, fdf50240
- * o_ss: i, src: 3, fdf50260
- * o_ss: i, src: 4, fdf50280
- * o_ss: i, src: 5, fdf51120
- * o_ss: i, src: 6, fdf51140
+ * 16 Serial Interrupts followed by 16 Internal Interrupts.
+ * I2C is the second internal, so it is at 17, 0x11020.
*/
mpic_assign_isu(mpic, 0, paddr + 0x10200);
- mpic_assign_isu(mpic, 1, paddr + 0x10220);
- mpic_assign_isu(mpic, 2, paddr + 0x10240);
- mpic_assign_isu(mpic, 3, paddr + 0x10260);
- mpic_assign_isu(mpic, 4, paddr + 0x10280);
- mpic_assign_isu(mpic, 5, paddr + 0x11120);
- mpic_assign_isu(mpic, 6, paddr + 0x11140);
+ mpic_assign_isu(mpic, 1, paddr + 0x11000);
mpic_init(mpic);
}
@@ -178,7 +163,7 @@ static int __init storcenter_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- return of_flat_dt_is_compatible(root, "storcenter");
+ return of_flat_dt_is_compatible(root, "iomega,storcenter");
}
define_machine(storcenter){
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 6a0c6f6675c..11fa3c772ed 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -199,7 +199,7 @@ static struct iommu_table vio_iommu_table;
void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
{
- return iommu_alloc_coherent(&vio_iommu_table, size, dma_handle,
+ return iommu_alloc_coherent(NULL, &vio_iommu_table, size, dma_handle,
DMA_32BIT_MASK, flag, -1);
}
EXPORT_SYMBOL_GPL(iseries_hv_alloc);
@@ -213,7 +213,7 @@ EXPORT_SYMBOL_GPL(iseries_hv_free);
dma_addr_t iseries_hv_map(void *vaddr, size_t size,
enum dma_data_direction direction)
{
- return iommu_map_single(&vio_iommu_table, vaddr, size,
+ return iommu_map_single(NULL, &vio_iommu_table, vaddr, size,
DMA_32BIT_MASK, direction);
}
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index be06cfd9fa3..657b72f6849 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -75,7 +75,7 @@ static struct property *new_property(const char *name, int length,
return np;
}
-static void __init free_property(struct property *np)
+static void free_property(struct property *np)
{
kfree(np);
}
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index c04abcc28a7..792d3ce8112 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -113,8 +113,6 @@ static inline void debug_calc_bogomips(void)
* result. We backup/restore the value to avoid affecting the
* core cpufreq framework's own calculation.
*/
- extern void calibrate_delay(void);
-
unsigned long save_lpj = loops_per_jiffy;
calibrate_delay();
loops_per_jiffy = save_lpj;
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index ba931be2175..5169ecc3712 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2565,6 +2565,8 @@ static void __init probe_uninorth(void)
/* Locate core99 Uni-N */
uninorth_node = of_find_node_by_name(NULL, "uni-n");
+ uninorth_maj = 1;
+
/* Locate G5 u3 */
if (uninorth_node == NULL) {
uninorth_node = of_find_node_by_name(NULL, "u3");
@@ -2575,8 +2577,10 @@ static void __init probe_uninorth(void)
uninorth_node = of_find_node_by_name(NULL, "u4");
uninorth_maj = 4;
}
- if (uninorth_node == NULL)
+ if (uninorth_node == NULL) {
+ uninorth_maj = 0;
return;
+ }
addrp = of_get_property(uninorth_node, "reg", NULL);
if (addrp == NULL)
@@ -3029,3 +3033,8 @@ void pmac_resume_agp_for_card(struct pci_dev *dev)
pmac_agp_resume(pmac_agp_bridge);
}
EXPORT_SYMBOL(pmac_resume_agp_for_card);
+
+int pmac_get_uninorth_variant(void)
+{
+ return uninorth_maj;
+}
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index c4ad54e0f28..1f032483c02 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -58,7 +58,7 @@ static void pseries_mach_cpu_die(void)
{
local_irq_disable();
idle_task_exit();
- xics_teardown_cpu(0);
+ xics_teardown_cpu();
unregister_slb_shadow(hard_smp_processor_id(), __pa(get_slb_shadow()));
rtas_stop_self();
/* Should never get here... */
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c
index 412a5e7aff2..e9dd5fe081c 100644
--- a/arch/powerpc/platforms/pseries/kexec.c
+++ b/arch/powerpc/platforms/pseries/kexec.c
@@ -54,7 +54,7 @@ void __init setup_kexec_cpu_down_mpic(void)
static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary)
{
pseries_kexec_cpu_down(crash_shutdown, secondary);
- xics_teardown_cpu(secondary);
+ xics_kexec_teardown_cpu(secondary);
}
void __init setup_kexec_cpu_down_xics(void)
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index c02f8742c54..2800fced8c7 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -167,6 +167,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
if ((child = of_get_next_child(np, NULL))) {
of_node_put(child);
+ of_node_put(parent);
return -EBUSY;
}
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 8f8dd9c3ca6..ca52b587166 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -160,6 +160,46 @@ static inline void lpar_qirr_info(int n_cpu , u8 value)
/* High level handlers and init code */
+static void xics_update_irq_servers(void)
+{
+ int i, j;
+ struct device_node *np;
+ u32 ilen;
+ const u32 *ireg, *isize;
+ u32 hcpuid;
+
+ /* Find the server numbers for the boot cpu. */
+ np = of_get_cpu_node(boot_cpuid, NULL);
+ BUG_ON(!np);
+
+ ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
+ if (!ireg) {
+ of_node_put(np);
+ return;
+ }
+
+ i = ilen / sizeof(int);
+ hcpuid = get_hard_smp_processor_id(boot_cpuid);
+
+ /* Global interrupt distribution server is specified in the last
+ * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
+ * entry fom this property for current boot cpu id and use it as
+ * default distribution server
+ */
+ for (j = 0; j < i; j += 2) {
+ if (ireg[j] == hcpuid) {
+ default_server = hcpuid;
+ default_distrib_server = ireg[j+1];
+
+ isize = of_get_property(np,
+ "ibm,interrupt-server#-size", NULL);
+ if (isize)
+ interrupt_server_size = *isize;
+ }
+ }
+
+ of_node_put(np);
+}
#ifdef CONFIG_SMP
static int get_irq_server(unsigned int virq, unsigned int strict_check)
@@ -169,6 +209,9 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check)
cpumask_t cpumask = irq_desc[virq].affinity;
cpumask_t tmp = CPU_MASK_NONE;
+ if (! cpu_isset(default_server, cpu_online_map))
+ xics_update_irq_servers();
+
if (!distribute_irqs)
return default_server;
@@ -658,39 +701,11 @@ static void __init xics_setup_8259_cascade(void)
set_irq_chained_handler(cascade, pseries_8259_cascade);
}
-static struct device_node *cpuid_to_of_node(int cpu)
-{
- struct device_node *np;
- u32 hcpuid = get_hard_smp_processor_id(cpu);
-
- for_each_node_by_type(np, "cpu") {
- int i, len;
- const u32 *intserv;
-
- intserv = of_get_property(np, "ibm,ppc-interrupt-server#s",
- &len);
-
- if (!intserv)
- intserv = of_get_property(np, "reg", &len);
-
- i = len / sizeof(u32);
-
- while (i--)
- if (intserv[i] == hcpuid)
- return np;
- }
-
- return NULL;
-}
-
void __init xics_init_IRQ(void)
{
- int i, j;
struct device_node *np;
- u32 ilen, indx = 0;
- const u32 *ireg, *isize;
+ u32 indx = 0;
int found = 0;
- u32 hcpuid;
ppc64_boot_msg(0x20, "XICS Init");
@@ -709,34 +724,7 @@ void __init xics_init_IRQ(void)
return;
xics_init_host();
-
- /* Find the server numbers for the boot cpu. */
- np = cpuid_to_of_node(boot_cpuid);
- BUG_ON(!np);
- ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
- if (!ireg)
- goto skip_gserver_check;
- i = ilen / sizeof(int);
- hcpuid = get_hard_smp_processor_id(boot_cpuid);
-
- /* Global interrupt distribution server is specified in the last
- * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
- * entry fom this property for current boot cpu id and use it as
- * default distribution server
- */
- for (j = 0; j < i; j += 2) {
- if (ireg[j] == hcpuid) {
- default_server = hcpuid;
- default_distrib_server = ireg[j+1];
-
- isize = of_get_property(np,
- "ibm,interrupt-server#-size", NULL);
- if (isize)
- interrupt_server_size = *isize;
- }
- }
-skip_gserver_check:
- of_node_put(np);
+ xics_update_irq_servers();
if (firmware_has_feature(FW_FEATURE_LPAR))
ppc_md.get_irq = xics_get_irq_lpar;
@@ -775,11 +763,9 @@ void xics_request_IPIs(void)
}
#endif /* CONFIG_SMP */
-void xics_teardown_cpu(int secondary)
+void xics_teardown_cpu()
{
int cpu = smp_processor_id();
- unsigned int ipi;
- struct irq_desc *desc;
xics_set_cpu_priority(0);
@@ -790,9 +776,17 @@ void xics_teardown_cpu(int secondary)
lpar_qirr_info(cpu, 0xff);
else
direct_qirr_info(cpu, 0xff);
+}
+
+void xics_kexec_teardown_cpu(int secondary)
+{
+ unsigned int ipi;
+ struct irq_desc *desc;
+
+ xics_teardown_cpu();
/*
- * we need to EOI the IPI if we got here from kexec down IPI
+ * we need to EOI the IPI
*
* probably need to check all the other interrupts too
* should we be flagging idle loop instead?
@@ -880,8 +874,8 @@ void xics_migrate_irqs_away(void)
virq, cpu);
/* Reset affinity to all cpus */
+ irq_desc[virq].affinity = CPU_MASK_ALL;
desc->chip->set_affinity(virq, CPU_MASK_ALL);
- irq_desc[irq].affinity = CPU_MASK_ALL;
unlock:
spin_unlock_irqrestore(&desc->lock, flags);
}
diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h
index 9ffd809d29e..c26bcff47b6 100644
--- a/arch/powerpc/platforms/pseries/xics.h
+++ b/arch/powerpc/platforms/pseries/xics.h
@@ -16,7 +16,8 @@
extern void xics_init_IRQ(void);
extern void xics_setup_cpu(void);
-extern void xics_teardown_cpu(int secondary);
+extern void xics_teardown_cpu(void);
+extern void xics_kexec_teardown_cpu(int secondary);
extern void xics_cause_IPI(int cpu);
extern void xics_request_IPIs(void);
extern void xics_migrate_irqs_away(void);
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
index 427027c7ea0..437e48d3ae3 100644
--- a/arch/powerpc/sysdev/dcr.c
+++ b/arch/powerpc/sysdev/dcr.c
@@ -137,5 +137,6 @@ void dcr_unmap(dcr_host_t host, unsigned int dcr_c)
h.token = NULL;
}
EXPORT_SYMBOL_GPL(dcr_unmap);
-
-#endif /* !defined(CONFIG_PPC_DCR_NATIVE) */
+#else /* defined(CONFIG_PPC_DCR_NATIVE) */
+DEFINE_SPINLOCK(dcr_ind_lock);
+#endif /* !defined(CONFIG_PPC_DCR_NATIVE) */
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index e48b20e934c..2c5388ce902 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -1342,7 +1342,7 @@ static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk,
if (ret)
goto unreg;
- ret = platform_device_register(pdev);
+ ret = platform_device_add(pdev);
if (ret)
goto unreg;
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index 0e74a4bd982..5d2d5522ef4 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -174,15 +174,19 @@ int mpc8xx_pic_init(void)
goto out;
siu_reg = ioremap(res.start, res.end - res.start + 1);
- if (siu_reg == NULL)
- return -EINVAL;
+ if (siu_reg == NULL) {
+ ret = -EINVAL;
+ goto out;
+ }
- mpc8xx_pic_host = irq_alloc_host(of_node_get(np), IRQ_HOST_MAP_LINEAR,
+ mpc8xx_pic_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
64, &mpc8xx_pic_host_ops, 64);
if (mpc8xx_pic_host == NULL) {
printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");
ret = -ENOMEM;
+ goto out;
}
+ return 0;
out:
of_node_put(np);
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 5ef844da935..6efbd5e5bb1 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -66,7 +66,7 @@ phys_addr_t get_qe_base(void)
{
struct device_node *qe;
unsigned int size;
- const void *prop;
+ const u32 *prop;
if (qebase != -1)
return qebase;
@@ -79,7 +79,8 @@ phys_addr_t get_qe_base(void)
}
prop = of_get_property(qe, "reg", &size);
- qebase = of_translate_address(qe, prop);
+ if (prop && size >= sizeof(*prop))
+ qebase = of_translate_address(qe, prop);
of_node_put(qe);
return qebase;
@@ -172,10 +173,9 @@ unsigned int get_brg_clk(void)
}
prop = of_get_property(qe, "brg-frequency", &size);
- if (!prop || size != sizeof(*prop))
- return brg_clk;
+ if (prop && size == sizeof(*prop))
+ brg_clk = *prop;
- brg_clk = *prop;
of_node_put(qe);
return brg_clk;
diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
index 25ef55bacd9..ec1defea9c1 100644
--- a/arch/ppc/8260_io/enet.c
+++ b/arch/ppc/8260_io/enet.c
@@ -418,7 +418,7 @@ scc_enet_rx(struct net_device *dev)
struct sk_buff *skb;
ushort pkt_len;
- cep = (struct scc_enet_private *)dev->priv;
+ cep = dev->priv;
/* First, grab all of the stats for the incoming packet.
* These get messed up if we get called due to a busy condition.
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index a3a27dafff1..bcc3aa9d04f 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -682,7 +682,7 @@ fcc_enet_rx(struct net_device *dev)
struct sk_buff *skb;
ushort pkt_len;
- cep = (struct fcc_enet_private *)dev->priv;
+ cep = dev->priv;
/* First, grab all of the stats for the incoming packet.
* These get messed up if we get called due to a busy condition.
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 531156f8919..abc877faf12 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -42,6 +42,7 @@ config GENERIC_CALIBRATE_DELAY
config PPC
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
select HAVE_KPROBES
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index d51368d72e3..294055902f0 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -275,7 +275,7 @@ static void c_stop(struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start =c_start,
.next = c_next,
.stop = c_stop,
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 52b64fcbdfc..8a24bc47eb6 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -143,11 +143,6 @@ SECTIONS
. = ALIGN(4096);
__init_end = .;
-
- . = ALIGN(4096);
- _sextratext = .;
- _eextratext = .;
-
__bss_start = .;
.bss :
{
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index fadacfd1880..03a79bff127 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -74,7 +74,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return ret;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_pages((unsigned long)pgd, PGDIR_ORDER);
}
@@ -95,7 +95,7 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add
return pte;
}
-struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *ptepage;
@@ -106,12 +106,14 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
#endif
ptepage = alloc_pages(flags, 0);
- if (ptepage)
+ if (ptepage) {
clear_highpage(ptepage);
+ pgtable_page_ctor(ptepage);
+ }
return ptepage;
}
-void pte_free_kernel(pte_t *pte)
+void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
#ifdef CONFIG_SMP
hash_page_sync();
@@ -119,11 +121,12 @@ void pte_free_kernel(pte_t *pte)
free_page((unsigned long)pte);
}
-void pte_free(struct page *ptepage)
+void pte_free(struct mm_struct *mm, pgtable_t ptepage)
{
#ifdef CONFIG_SMP
hash_page_sync();
#endif
+ pgtable_page_dtor(ptepage);
__free_page(ptepage);
}
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index 3c56654bfc6..38449855d5f 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -91,20 +91,11 @@ extern void prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi
#define cached_21 (((char *)(ppc_cached_irq_mask))[3])
#define cached_A1 (((char *)(ppc_cached_irq_mask))[2])
-#ifdef CONFIG_SOUND_CS4232
-long ppc_cs4232_dma, ppc_cs4232_dma2;
-#endif
-
extern PTE *Hash, *Hash_end;
extern unsigned long Hash_size, Hash_mask;
extern int probingmem;
extern unsigned long loops_per_jiffy;
-#ifdef CONFIG_SOUND_CS4232
-EXPORT_SYMBOL(ppc_cs4232_dma);
-EXPORT_SYMBOL(ppc_cs4232_dma2);
-#endif
-
/* useful ISA ports */
#define PREP_SYSCTL 0x81c
/* present in the IBM reference design; possibly identical in Mot boxes: */
@@ -569,74 +560,6 @@ prep_show_percpuinfo(struct seq_file *m, int i)
return 0;
}
-#ifdef CONFIG_SOUND_CS4232
-static long __init masktoint(unsigned int i)
-{
- int t = -1;
- while (i >> ++t)
- ;
- return (t-1);
-}
-
-/*
- * ppc_cs4232_dma and ppc_cs4232_dma2 are used in include/asm/dma.h
- * to distinguish sound dma-channels from others. This is because
- * blocksize on 16 bit dma-channels 5,6,7 is 128k, but
- * the cs4232.c uses 64k like on 8 bit dma-channels 0,1,2,3
- */
-
-static void __init prep_init_sound(void)
-{
- PPC_DEVICE *audiodevice = NULL;
-
- /*
- * Get the needed resource information from residual data.
- *
- */
- if (have_residual_data)
- audiodevice = residual_find_device(~0, NULL,
- MultimediaController, AudioController, -1, 0);
-
- if (audiodevice != NULL) {
- PnP_TAG_PACKET *pkt;
-
- pkt = PnP_find_packet((unsigned char *)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
- S5_Packet, 0);
- if (pkt != NULL)
- ppc_cs4232_dma = masktoint(pkt->S5_Pack.DMAMask);
- pkt = PnP_find_packet((unsigned char*)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
- S5_Packet, 1);
- if (pkt != NULL)
- ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask);
- }
-
- /*
- * These are the PReP specs' defaults for the cs4231. We use these
- * as fallback incase we don't have residual data.
- * At least the IBM Thinkpad 850 with IDE DMA Channels at 6 and 7
- * will use the other values.
- */
- if (audiodevice == NULL) {
- switch (_prep_type) {
- case _PREP_IBM:
- ppc_cs4232_dma = 1;
- ppc_cs4232_dma2 = -1;
- break;
- default:
- ppc_cs4232_dma = 6;
- ppc_cs4232_dma2 = 7;
- }
- }
-
- /*
- * Find a way to push this information to the cs4232 driver
- * Give it out with printk, when not in cmd_line?
- * Append it to cmd_line and boot_command_line?
- * Format is cs4232=io,irq,dma,dma2
- */
-}
-#endif /* CONFIG_SOUND_CS4232 */
-
/*
* Fill out screen_info according to the residual data. This allows us to use
* at least vesafb.
@@ -898,10 +821,6 @@ prep_setup_arch(void)
}
}
-#ifdef CONFIG_SOUND_CS4232
- prep_init_sound();
-#endif /* CONFIG_SOUND_CS4232 */
-
prep_init_vesa();
switch (_prep_type) {
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 82cbffd0365..92a4f7b4323 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -16,6 +16,9 @@ config LOCKDEP_SUPPORT
config STACKTRACE_SUPPORT
def_bool y
+config HAVE_LATENCYTOP_SUPPORT
+ def_bool y
+
config RWSEM_GENERIC_SPINLOCK
bool
@@ -47,6 +50,11 @@ config NO_IOMEM
config NO_DMA
def_bool y
+config GENERIC_LOCKBREAK
+ bool
+ default y
+ depends on SMP && PREEMPT
+
mainmenu "Linux Kernel Configuration"
config S390
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
index 2283933a9a9..4599fa06bd8 100644
--- a/arch/s390/Kconfig.debug
+++ b/arch/s390/Kconfig.debug
@@ -6,4 +6,12 @@ config TRACE_IRQFLAGS_SUPPORT
source "lib/Kconfig.debug"
+config DEBUG_PAGEALLOC
+ bool "Debug page memory allocations"
+ depends on DEBUG_KERNEL
+ help
+ Unmap pages from the kernel linear mapping after free_pages().
+ This results in a slowdown, but helps to find certain types of
+ memory corruptions.
+
endmenu
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index ece7b99da89..39921f3a968 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23
-# Mon Oct 22 12:10:44 2007
+# Linux kernel version: 2.6.24
+# Sat Feb 9 12:13:01 2008
#
CONFIG_MMU=y
CONFIG_ZONE_DMA=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
@@ -15,6 +16,7 @@ CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_BUG=y
CONFIG_NO_IOMEM=y
CONFIG_NO_DMA=y
+CONFIG_GENERIC_LOCKBREAK=y
CONFIG_S390=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -32,7 +34,6 @@ CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
CONFIG_AUDIT=y
# CONFIG_AUDITSYSCALL is not set
CONFIG_IKCONFIG=y
@@ -41,13 +42,19 @@ CONFIG_LOG_BUF_SHIFT=17
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_NS=y
-CONFIG_CGROUP_CPUACCT=y
# CONFIG_CPUSETS is not set
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_FAIR_USER_SCHED=y
# CONFIG_FAIR_CGROUP_SCHED is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -61,17 +68,26 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -99,6 +115,8 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_RCU is not set
#
# Base setup
@@ -137,7 +155,7 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-CONFIG_PREEMPT_BKL=y
+# CONFIG_RCU_TRACE is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -151,7 +169,6 @@ CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
-CONFIG_HOLES_IN_ZONE=y
#
# I/O subsystem configuration
@@ -180,6 +197,7 @@ CONFIG_HZ_100=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
CONFIG_NO_IDLE_HZ=y
CONFIG_NO_IDLE_HZ_INIT=y
CONFIG_S390_HYPFS_FS=y
@@ -201,6 +219,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
CONFIG_NET_KEY=y
# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_IUCV=m
@@ -251,6 +270,7 @@ CONFIG_IPV6_SIT=y
# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
#
# Core Netfilter Configuration
@@ -258,7 +278,6 @@ CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
CONFIG_NF_CONNTRACK=m
# CONFIG_NF_CT_ACCT is not set
# CONFIG_NF_CONNTRACK_MARK is not set
@@ -286,7 +305,7 @@ CONFIG_NF_CONNTRACK=m
# CONFIG_IP_NF_ARPTABLES is not set
#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
+# IPv6: Netfilter Configuration
#
# CONFIG_NF_CONNTRACK_IPV6 is not set
# CONFIG_IP6_NF_QUEUE is not set
@@ -343,6 +362,7 @@ CONFIG_NET_CLS_U32=m
CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
# CONFIG_NET_EMATCH is not set
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
@@ -351,7 +371,6 @@ CONFIG_NET_ACT_POLICE=y
CONFIG_NET_ACT_NAT=m
# CONFIG_NET_ACT_PEDIT is not set
# CONFIG_NET_ACT_SIMP is not set
-CONFIG_NET_CLS_POLICE=y
# CONFIG_NET_CLS_IND is not set
CONFIG_NET_SCH_FIFO=y
@@ -360,6 +379,15 @@ CONFIG_NET_SCH_FIFO=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
# CONFIG_AF_RXRPC is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -389,7 +417,7 @@ CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_XIP=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -406,6 +434,7 @@ CONFIG_DASD_DIAG=y
CONFIG_DASD_EER=y
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
#
# SCSI device support
@@ -487,6 +516,7 @@ CONFIG_NET_ETHERNET=y
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
CONFIG_NETDEV_1000=y
+# CONFIG_E1000E_ENABLED is not set
CONFIG_NETDEV_10000=y
# CONFIG_TR is not set
# CONFIG_WAN is not set
@@ -508,7 +538,6 @@ CONFIG_QETH=y
CONFIG_CCWGROUP=y
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -558,6 +587,7 @@ CONFIG_S390_TAPE_34XX=m
CONFIG_MONWRITER=m
CONFIG_S390_VMUR=m
# CONFIG_POWER_SUPPLY is not set
+# CONFIG_THERMAL is not set
# CONFIG_WATCHDOG is not set
#
@@ -584,12 +614,10 @@ CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -632,8 +660,10 @@ CONFIG_CONFIGFS_FS=m
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
@@ -686,16 +716,13 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
CONFIG_DLM=m
# CONFIG_DLM_DEBUG is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-CONFIG_KPROBES=y
-# CONFIG_MARKERS is not set
#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
@@ -721,12 +748,18 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
# CONFIG_FRAME_POINTER is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
CONFIG_SAMPLES=y
+# CONFIG_SAMPLE_KOBJECT is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
#
# Security options
@@ -738,6 +771,7 @@ CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_AEAD=m
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_SEQIV=m
CONFIG_CRYPTO_HASH=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=m
@@ -745,17 +779,20 @@ CONFIG_CRYPTO_HMAC=m
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=m
-# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA1=m
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
# CONFIG_CRYPTO_XTS is not set
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CCM=m
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_DES is not set
CONFIG_CRYPTO_FCRYPT=m
@@ -770,20 +807,22 @@ CONFIG_CRYPTO_FCRYPT=m
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_ANUBIS is not set
CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SALSA20=m
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
CONFIG_CRYPTO_CAMELLIA=m
# CONFIG_CRYPTO_TEST is not set
CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_HW=y
+CONFIG_ZCRYPT=m
+# CONFIG_ZCRYPT_MONOLITHIC is not set
# CONFIG_CRYPTO_SHA1_S390 is not set
# CONFIG_CRYPTO_SHA256_S390 is not set
# CONFIG_CRYPTO_DES_S390 is not set
# CONFIG_CRYPTO_AES_S390 is not set
CONFIG_S390_PRNG=m
-CONFIG_ZCRYPT=m
-# CONFIG_ZCRYPT_MONOLITHIC is not set
#
# Library routines
@@ -794,5 +833,7 @@ CONFIG_BITREVERSE=m
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=m
CONFIG_CRC7=m
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
CONFIG_PLIST=y
diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c
index f1e40ca00d8..3e1c315b736 100644
--- a/arch/s390/kernel/binfmt_elf32.c
+++ b/arch/s390/kernel/binfmt_elf32.c
@@ -134,6 +134,7 @@ static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
}
#include <asm/processor.h>
+#include <asm/pgalloc.h>
#include <linux/module.h>
#include <linux/elfcore.h>
#include <linux/binfmts.h>
@@ -183,6 +184,16 @@ struct elf_prpsinfo32
#undef start_thread
#define start_thread start_thread31
+static inline void start_thread31(struct pt_regs *regs, unsigned long new_psw,
+ unsigned long new_stackp)
+{
+ set_fs(USER_DS);
+ regs->psw.mask = psw_user32_bits;
+ regs->psw.addr = new_psw;
+ regs->gprs[15] = new_stackp;
+ crst_table_downgrade(current->mm, 1UL << 31);
+}
+
MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit Linux for S390 binaries,"
" Copyright 2000 IBM Corporation");
MODULE_AUTHOR("Gerhard Tonn <ton@de.ibm.com>");
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 6ee1bedbd1b..743d54f0b8d 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1698,14 +1698,6 @@ compat_sys_signalfd_wrapper:
llgfr %r4,%r4 # compat_size_t
jg compat_sys_signalfd
- .globl compat_sys_timerfd_wrapper
-compat_sys_timerfd_wrapper:
- lgfr %r2,%r2 # int
- lgfr %r3,%r3 # int
- lgfr %r4,%r4 # int
- llgtr %r5,%r5 # struct compat_itimerspec *
- jg compat_sys_timerfd
-
.globl sys_eventfd_wrapper
sys_eventfd_wrapper:
llgfr %r2,%r2 # unsigned int
@@ -1720,3 +1712,23 @@ sys_fallocate_wrapper:
sllg %r5,%r6,32 # get high word of 64bit loff_t
l %r5,164(%r15) # get low word of 64bit loff_t
jg sys_fallocate
+
+ .globl sys_timerfd_create_wrapper
+sys_timerfd_create_wrapper:
+ lgfr %r2,%r2 # int
+ lgfr %r3,%r3 # int
+ jg sys_timerfd_create
+
+ .globl compat_sys_timerfd_settime_wrapper
+compat_sys_timerfd_settime_wrapper:
+ lgfr %r2,%r2 # int
+ lgfr %r3,%r3 # int
+ llgtr %r4,%r4 # struct compat_itimerspec *
+ llgtr %r5,%r5 # struct compat_itimerspec *
+ jg compat_sys_timerfd_settime
+
+ .globl compat_sys_timerfd_gettime_wrapper
+compat_sys_timerfd_gettime_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # struct compat_itimerspec *
+ jg compat_sys_timerfd_gettime
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 1a6dac8df6f..6766e37fe8e 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -11,6 +11,7 @@
#include <linux/sys.h>
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/cache.h>
#include <asm/lowcore.h>
#include <asm/errno.h>
@@ -830,9 +831,7 @@ mcck_return:
* Restart interruption handler, kick starter for additional CPUs
*/
#ifdef CONFIG_SMP
-#ifndef CONFIG_HOTPLUG_CPU
- .section .init.text,"ax"
-#endif
+ __CPUINIT
.globl restart_int_handler
restart_int_handler:
l %r15,__LC_SAVE_AREA+60 # load ksp
@@ -845,9 +844,7 @@ restart_int_handler:
br %r14 # branch to start_secondary
restart_addr:
.long start_secondary
-#ifndef CONFIG_HOTPLUG_CPU
.previous
-#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index a3e47b893f0..efde6e178f6 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -11,6 +11,7 @@
#include <linux/sys.h>
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/cache.h>
#include <asm/lowcore.h>
#include <asm/errno.h>
@@ -801,9 +802,7 @@ mcck_return:
* Restart interruption handler, kick starter for additional CPUs
*/
#ifdef CONFIG_SMP
-#ifndef CONFIG_HOTPLUG_CPU
- .section .init.text,"ax"
-#endif
+ __CPUINIT
.globl restart_int_handler
restart_int_handler:
lg %r15,__LC_SAVE_AREA+120 # load ksp
@@ -814,9 +813,7 @@ restart_int_handler:
lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone
stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
jg start_secondary
-#ifndef CONFIG_HOTPLUG_CPU
.previous
-#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index db28cca81fe..60acdc266db 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -439,7 +439,7 @@ static void ipl_run(struct shutdown_trigger *trigger)
reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
}
-static int ipl_init(void)
+static int __init ipl_init(void)
{
int rc;
@@ -471,8 +471,11 @@ out:
return 0;
}
-static struct shutdown_action ipl_action = {SHUTDOWN_ACTION_IPL_STR, ipl_run,
- ipl_init};
+static struct shutdown_action __refdata ipl_action = {
+ .name = SHUTDOWN_ACTION_IPL_STR,
+ .fn = ipl_run,
+ .init = ipl_init,
+};
/*
* reipl shutdown action: Reboot Linux on shutdown.
@@ -792,7 +795,7 @@ static int __init reipl_fcp_init(void)
return 0;
}
-static int reipl_init(void)
+static int __init reipl_init(void)
{
int rc;
@@ -819,8 +822,11 @@ static int reipl_init(void)
return 0;
}
-static struct shutdown_action reipl_action = {SHUTDOWN_ACTION_REIPL_STR,
- reipl_run, reipl_init};
+static struct shutdown_action __refdata reipl_action = {
+ .name = SHUTDOWN_ACTION_REIPL_STR,
+ .fn = reipl_run,
+ .init = reipl_init,
+};
/*
* dump shutdown action: Dump Linux on shutdown.
@@ -998,7 +1004,7 @@ static int __init dump_fcp_init(void)
return 0;
}
-static int dump_init(void)
+static int __init dump_init(void)
{
int rc;
@@ -1020,8 +1026,11 @@ static int dump_init(void)
return 0;
}
-static struct shutdown_action dump_action = {SHUTDOWN_ACTION_DUMP_STR,
- dump_run, dump_init};
+static struct shutdown_action __refdata dump_action = {
+ .name = SHUTDOWN_ACTION_DUMP_STR,
+ .fn = dump_run,
+ .init = dump_init,
+};
/*
* vmcmd shutdown action: Trigger vm command on shutdown.
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 0e7aca03930..a6a4729e0e9 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -29,7 +29,6 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/reboot.h>
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 766c783bd7a..290e504061a 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -24,7 +24,6 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/delay.h>
@@ -77,7 +76,7 @@ unsigned long machine_flags = 0;
unsigned long elf_hwcap = 0;
char elf_platform[ELF_PLATFORM_SIZE];
-struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
+struct mem_chunk __meminitdata memory_chunk[MEMORY_CHUNKS];
volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
static unsigned long __initdata memory_end;
@@ -145,7 +144,7 @@ __setup("condev=", condev_setup);
static int __init conmode_setup(char *str)
{
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
if (strncmp(str, "hwc", 4) == 0 || strncmp(str, "sclp", 5) == 0)
SET_CONSOLE_SCLP;
#endif
@@ -183,7 +182,7 @@ static void __init conmode_default(void)
*/
cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
if (ptr == NULL) {
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
return;
@@ -193,7 +192,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3270;
#elif defined(CONFIG_TN3215_CONSOLE)
SET_CONSOLE_3215;
-#elif defined(CONFIG_SCLP_CONSOLE)
+#elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
} else if (strncmp(ptr + 8, "3215", 4) == 0) {
@@ -201,7 +200,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3215;
#elif defined(CONFIG_TN3270_CONSOLE)
SET_CONSOLE_3270;
-#elif defined(CONFIG_SCLP_CONSOLE)
+#elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
}
@@ -212,7 +211,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3270;
#endif
} else {
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
}
@@ -528,7 +527,7 @@ static void __init setup_memory_end(void)
memory_size = 0;
memory_end &= PAGE_MASK;
- max_mem = memory_end ? min(VMALLOC_START, memory_end) : VMALLOC_START;
+ max_mem = memory_end ? min(VMEM_MAX_PHYS, memory_end) : VMEM_MAX_PHYS;
memory_end = min(max_mem, memory_end);
/*
@@ -649,21 +648,24 @@ setup_memory(void)
/*
* Reserve memory used for lowcore/command line/kernel image.
*/
- reserve_bootmem(0, (unsigned long)_ehead);
+ reserve_bootmem(0, (unsigned long)_ehead, BOOTMEM_DEFAULT);
reserve_bootmem((unsigned long)_stext,
- PFN_PHYS(start_pfn) - (unsigned long)_stext);
+ PFN_PHYS(start_pfn) - (unsigned long)_stext,
+ BOOTMEM_DEFAULT);
/*
* Reserve the bootmem bitmap itself as well. We do this in two
* steps (first step was init_bootmem()) because this catches
* the (very unlikely) case of us accidentally initializing the
* bootmem allocator with an invalid RAM area.
*/
- reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size);
+ reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size,
+ BOOTMEM_DEFAULT);
#ifdef CONFIG_BLK_DEV_INITRD
if (INITRD_START && INITRD_SIZE) {
if (INITRD_START + INITRD_SIZE <= memory_end) {
- reserve_bootmem(INITRD_START, INITRD_SIZE);
+ reserve_bootmem(INITRD_START, INITRD_SIZE,
+ BOOTMEM_DEFAULT);
initrd_start = INITRD_START;
initrd_end = initrd_start + INITRD_SIZE;
} else {
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index aa37fa15451..85060659fb1 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -225,12 +225,11 @@ EXPORT_SYMBOL(smp_call_function_single);
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler.
*/
-int
-smp_call_function_mask(cpumask_t mask,
- void (*func)(void *), void *info,
- int wait)
+int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
+ int wait)
{
preempt_disable();
+ cpu_clear(smp_processor_id(), mask);
__smp_call_function_map(func, info, 0, wait, mask);
preempt_enable();
return 0;
@@ -1008,7 +1007,7 @@ static struct notifier_block __cpuinitdata smp_cpu_nb = {
.notifier_call = smp_cpu_notify,
};
-static int smp_add_present_cpu(int cpu)
+static int __devinit smp_add_present_cpu(int cpu)
{
struct cpu *c = &per_cpu(cpu_devices, cpu);
struct sys_device *s = &c->sysdev;
@@ -1036,8 +1035,8 @@ out:
}
#ifdef CONFIG_HOTPLUG_CPU
-static ssize_t rescan_store(struct sys_device *dev, const char *buf,
- size_t count)
+static ssize_t __ref rescan_store(struct sys_device *dev,
+ const char *buf, size_t count)
{
cpumask_t newcpus;
int cpu;
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index da692472996..85e46a5d0e0 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -14,7 +14,8 @@
static unsigned long save_context_stack(struct stack_trace *trace,
unsigned long sp,
unsigned long low,
- unsigned long high)
+ unsigned long high,
+ int savesched)
{
struct stack_frame *sf;
struct pt_regs *regs;
@@ -47,10 +48,12 @@ static unsigned long save_context_stack(struct stack_trace *trace,
return sp;
regs = (struct pt_regs *)sp;
addr = regs->psw.addr & PSW_ADDR_INSN;
- if (!trace->skip)
- trace->entries[trace->nr_entries++] = addr;
- else
- trace->skip--;
+ if (savesched || !in_sched_functions(addr)) {
+ if (!trace->skip)
+ trace->entries[trace->nr_entries++] = addr;
+ else
+ trace->skip--;
+ }
if (trace->nr_entries >= trace->max_entries)
return sp;
low = sp;
@@ -66,15 +69,27 @@ void save_stack_trace(struct stack_trace *trace)
orig_sp = sp & PSW_ADDR_INSN;
new_sp = save_context_stack(trace, orig_sp,
S390_lowcore.panic_stack - PAGE_SIZE,
- S390_lowcore.panic_stack);
+ S390_lowcore.panic_stack, 1);
if (new_sp != orig_sp)
return;
new_sp = save_context_stack(trace, new_sp,
S390_lowcore.async_stack - ASYNC_SIZE,
- S390_lowcore.async_stack);
+ S390_lowcore.async_stack, 1);
if (new_sp != orig_sp)
return;
save_context_stack(trace, new_sp,
S390_lowcore.thread_info,
- S390_lowcore.thread_info + THREAD_SIZE);
+ S390_lowcore.thread_info + THREAD_SIZE, 1);
+}
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+ unsigned long sp, low, high;
+
+ sp = tsk->thread.ksp & PSW_ADDR_INSN;
+ low = (unsigned long) task_stack_page(tsk);
+ high = (unsigned long) task_pt_regs(tsk);
+ save_context_stack(trace, sp, low, high, 0);
+ if (trace->nr_entries < trace->max_entries)
+ trace->entries[trace->nr_entries++] = ULONG_MAX;
}
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 9e26ed9fe4e..c87ec687d4c 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -325,5 +325,8 @@ SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper)
SYSCALL(s390_fallocate,sys_fallocate,sys_fallocate_wrapper)
SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper) /* 315 */
SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
-SYSCALL(sys_timerfd,sys_timerfd,compat_sys_timerfd_wrapper)
+NI_SYSCALL /* 317 old sys_timer_fd */
SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper)
+SYSCALL(sys_timerfd_create,sys_timerfd_create,sys_timerfd_create_wrapper)
+SYSCALL(sys_timerfd_settime,sys_timerfd_settime,compat_sys_timerfd_settime_wrapper) /* 320 */
+SYSCALL(sys_timerfd_gettime,sys_timerfd_gettime,compat_sys_timerfd_gettime_wrapper)
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 52b8342c6bf..60f728aeaf1 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -24,6 +24,7 @@
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/seq_file.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/kdebug.h>
@@ -59,6 +60,7 @@ int sysctl_userprocess_debug = 0;
extern pgm_check_handler_t do_protection_exception;
extern pgm_check_handler_t do_dat_exception;
extern pgm_check_handler_t do_monitor_call;
+extern pgm_check_handler_t do_asce_exception;
#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
@@ -218,41 +220,40 @@ void show_registers(struct pt_regs *regs)
}
/* This is called from fs/proc/array.c */
-char *task_show_regs(struct task_struct *task, char *buffer)
+void task_show_regs(struct seq_file *m, struct task_struct *task)
{
struct pt_regs *regs;
regs = task_pt_regs(task);
- buffer += sprintf(buffer, "task: %p, ksp: %p\n",
+ seq_printf(m, "task: %p, ksp: %p\n",
task, (void *)task->thread.ksp);
- buffer += sprintf(buffer, "User PSW : %p %p\n",
+ seq_printf(m, "User PSW : %p %p\n",
(void *) regs->psw.mask, (void *)regs->psw.addr);
- buffer += sprintf(buffer, "User GPRS: " FOURLONG,
+ seq_printf(m, "User GPRS: " FOURLONG,
regs->gprs[0], regs->gprs[1],
regs->gprs[2], regs->gprs[3]);
- buffer += sprintf(buffer, " " FOURLONG,
+ seq_printf(m, " " FOURLONG,
regs->gprs[4], regs->gprs[5],
regs->gprs[6], regs->gprs[7]);
- buffer += sprintf(buffer, " " FOURLONG,
+ seq_printf(m, " " FOURLONG,
regs->gprs[8], regs->gprs[9],
regs->gprs[10], regs->gprs[11]);
- buffer += sprintf(buffer, " " FOURLONG,
+ seq_printf(m, " " FOURLONG,
regs->gprs[12], regs->gprs[13],
regs->gprs[14], regs->gprs[15]);
- buffer += sprintf(buffer, "User ACRS: %08x %08x %08x %08x\n",
+ seq_printf(m, "User ACRS: %08x %08x %08x %08x\n",
task->thread.acrs[0], task->thread.acrs[1],
task->thread.acrs[2], task->thread.acrs[3]);
- buffer += sprintf(buffer, " %08x %08x %08x %08x\n",
+ seq_printf(m, " %08x %08x %08x %08x\n",
task->thread.acrs[4], task->thread.acrs[5],
task->thread.acrs[6], task->thread.acrs[7]);
- buffer += sprintf(buffer, " %08x %08x %08x %08x\n",
+ seq_printf(m, " %08x %08x %08x %08x\n",
task->thread.acrs[8], task->thread.acrs[9],
task->thread.acrs[10], task->thread.acrs[11]);
- buffer += sprintf(buffer, " %08x %08x %08x %08x\n",
+ seq_printf(m, " %08x %08x %08x %08x\n",
task->thread.acrs[12], task->thread.acrs[13],
task->thread.acrs[14], task->thread.acrs[15]);
- return buffer;
}
static DEFINE_SPINLOCK(die_lock);
@@ -271,7 +272,10 @@ void die(const char * str, struct pt_regs * regs, long err)
printk("PREEMPT ");
#endif
#ifdef CONFIG_SMP
- printk("SMP");
+ printk("SMP ");
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ printk("DEBUG_PAGEALLOC");
#endif
printk("\n");
notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
@@ -727,7 +731,7 @@ void __init trap_init(void)
pgm_check_table[0x12] = &translation_exception;
pgm_check_table[0x13] = &special_op_exception;
#ifdef CONFIG_64BIT
- pgm_check_table[0x38] = &do_dat_exception;
+ pgm_check_table[0x38] = &do_asce_exception;
pgm_check_table[0x39] = &do_dat_exception;
pgm_check_table[0x3A] = &do_dat_exception;
pgm_check_table[0x3B] = &do_dat_exception;
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 7d43c3cd3ef..b4607155e8d 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -35,7 +35,7 @@ SECTIONS
KPROBES_TEXT
*(.fixup)
*(.gnu.warning)
- } = 0x0700
+ } :text = 0x0700
_etext = .; /* End of text section */
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 2456b52ed06..ed13d429a48 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -32,6 +32,7 @@
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/s390_ext.h>
+#include <asm/mmu_context.h>
#ifndef CONFIG_64BIT
#define __FAIL_ADDR_MASK 0x7ffff000
@@ -444,6 +445,45 @@ void __kprobes do_dat_exception(struct pt_regs *regs, unsigned long error_code)
do_exception(regs, error_code & 0xff, 0);
}
+#ifdef CONFIG_64BIT
+void __kprobes do_asce_exception(struct pt_regs *regs, unsigned long error_code)
+{
+ struct mm_struct *mm;
+ struct vm_area_struct *vma;
+ unsigned long address;
+ int space;
+
+ mm = current->mm;
+ address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK;
+ space = check_space(current);
+
+ if (unlikely(space == 0 || in_atomic() || !mm))
+ goto no_context;
+
+ local_irq_enable();
+
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, address);
+ up_read(&mm->mmap_sem);
+
+ if (vma) {
+ update_mm(mm, current);
+ return;
+ }
+
+ /* User mode accesses just cause a SIGSEGV */
+ if (regs->psw.mask & PSW_MASK_PSTATE) {
+ current->thread.prot_addr = address;
+ current->thread.trap_no = error_code;
+ do_sigsegv(regs, error_code, SEGV_MAPERR, address);
+ return;
+ }
+
+no_context:
+ do_no_context(regs, error_code, address);
+}
+#endif
+
#ifdef CONFIG_PFAULT
/*
* 'pfault' pseudo page faults routines.
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index b234bb4a6da..8053245fe25 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -112,6 +112,7 @@ void __init paging_init(void)
init_mm.pgd = swapper_pg_dir;
S390_lowcore.kernel_asce = __pa(init_mm.pgd) & PAGE_MASK;
#ifdef CONFIG_64BIT
+ /* A three level page table (4TB) is enough for the kernel space. */
S390_lowcore.kernel_asce |= _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
pgd_type = _REGION3_ENTRY_EMPTY;
#else
@@ -167,6 +168,33 @@ void __init mem_init(void)
PFN_ALIGN((unsigned long)&_eshared) - 1);
}
+#ifdef CONFIG_DEBUG_PAGEALLOC
+void kernel_map_pages(struct page *page, int numpages, int enable)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long address;
+ int i;
+
+ for (i = 0; i < numpages; i++) {
+ address = page_to_phys(page + i);
+ pgd = pgd_offset_k(address);
+ pud = pud_offset(pgd, address);
+ pmd = pmd_offset(pud, address);
+ pte = pte_offset_kernel(pmd, address);
+ if (!enable) {
+ ptep_invalidate(&init_mm, address, pte);
+ continue;
+ }
+ *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW));
+ /* Flush cpu write queue. */
+ mb();
+ }
+}
+#endif
+
void free_initmem(void)
{
unsigned long addr;
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index 356257c171d..5932a824547 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -27,6 +27,7 @@
#include <linux/personality.h>
#include <linux/mm.h>
#include <linux/module.h>
+#include <asm/pgalloc.h>
/*
* Top of mmap area (just below the process stack).
@@ -62,6 +63,8 @@ static inline int mmap_is_legacy(void)
current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY;
}
+#ifndef CONFIG_64BIT
+
/*
* This function, called very early during the creation of a new
* process VM image, sets up which VM layout function to use:
@@ -84,3 +87,65 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
}
EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
+#else
+
+static unsigned long
+s390_get_unmapped_area(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+ struct mm_struct *mm = current->mm;
+ int rc;
+
+ addr = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
+ if (addr & ~PAGE_MASK)
+ return addr;
+ if (unlikely(mm->context.asce_limit < addr + len)) {
+ rc = crst_table_upgrade(mm, addr + len);
+ if (rc)
+ return (unsigned long) rc;
+ }
+ return addr;
+}
+
+static unsigned long
+s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+ const unsigned long len, const unsigned long pgoff,
+ const unsigned long flags)
+{
+ struct mm_struct *mm = current->mm;
+ unsigned long addr = addr0;
+ int rc;
+
+ addr = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
+ if (addr & ~PAGE_MASK)
+ return addr;
+ if (unlikely(mm->context.asce_limit < addr + len)) {
+ rc = crst_table_upgrade(mm, addr + len);
+ if (rc)
+ return (unsigned long) rc;
+ }
+ return addr;
+}
+/*
+ * This function, called very early during the creation of a new
+ * process VM image, sets up which VM layout function to use:
+ */
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+ /*
+ * Fall back to the standard layout if the personality
+ * bit is set, or if the expected stack growth is unlimited:
+ */
+ if (mmap_is_legacy()) {
+ mm->mmap_base = TASK_UNMAPPED_BASE;
+ mm->get_unmapped_area = s390_get_unmapped_area;
+ mm->unmap_area = arch_unmap_area;
+ } else {
+ mm->mmap_base = mmap_base();
+ mm->get_unmapped_area = s390_get_unmapped_area_topdown;
+ mm->unmap_area = arch_unmap_area_topdown;
+ }
+}
+EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
+
+#endif
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index e60e0ae1340..fd072013f88 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -23,11 +23,18 @@
#include <asm/pgalloc.h>
#include <asm/tlb.h>
#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
#ifndef CONFIG_64BIT
#define ALLOC_ORDER 1
+#define TABLES_PER_PAGE 4
+#define FRAG_MASK 15UL
+#define SECOND_HALVES 10UL
#else
#define ALLOC_ORDER 2
+#define TABLES_PER_PAGE 2
+#define FRAG_MASK 3UL
+#define SECOND_HALVES 2UL
#endif
unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
@@ -45,50 +52,179 @@ unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
}
page->index = page_to_phys(shadow);
}
+ spin_lock(&mm->page_table_lock);
+ list_add(&page->lru, &mm->context.crst_list);
+ spin_unlock(&mm->page_table_lock);
return (unsigned long *) page_to_phys(page);
}
-void crst_table_free(unsigned long *table)
+void crst_table_free(struct mm_struct *mm, unsigned long *table)
{
unsigned long *shadow = get_shadow_table(table);
+ struct page *page = virt_to_page(table);
+ spin_lock(&mm->page_table_lock);
+ list_del(&page->lru);
+ spin_unlock(&mm->page_table_lock);
if (shadow)
free_pages((unsigned long) shadow, ALLOC_ORDER);
free_pages((unsigned long) table, ALLOC_ORDER);
}
+#ifdef CONFIG_64BIT
+int crst_table_upgrade(struct mm_struct *mm, unsigned long limit)
+{
+ unsigned long *table, *pgd;
+ unsigned long entry;
+
+ BUG_ON(limit > (1UL << 53));
+repeat:
+ table = crst_table_alloc(mm, mm->context.noexec);
+ if (!table)
+ return -ENOMEM;
+ spin_lock(&mm->page_table_lock);
+ if (mm->context.asce_limit < limit) {
+ pgd = (unsigned long *) mm->pgd;
+ if (mm->context.asce_limit <= (1UL << 31)) {
+ entry = _REGION3_ENTRY_EMPTY;
+ mm->context.asce_limit = 1UL << 42;
+ mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+ _ASCE_USER_BITS |
+ _ASCE_TYPE_REGION3;
+ } else {
+ entry = _REGION2_ENTRY_EMPTY;
+ mm->context.asce_limit = 1UL << 53;
+ mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+ _ASCE_USER_BITS |
+ _ASCE_TYPE_REGION2;
+ }
+ crst_table_init(table, entry);
+ pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd);
+ mm->pgd = (pgd_t *) table;
+ table = NULL;
+ }
+ spin_unlock(&mm->page_table_lock);
+ if (table)
+ crst_table_free(mm, table);
+ if (mm->context.asce_limit < limit)
+ goto repeat;
+ update_mm(mm, current);
+ return 0;
+}
+
+void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
+{
+ pgd_t *pgd;
+
+ if (mm->context.asce_limit <= limit)
+ return;
+ __tlb_flush_mm(mm);
+ while (mm->context.asce_limit > limit) {
+ pgd = mm->pgd;
+ switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) {
+ case _REGION_ENTRY_TYPE_R2:
+ mm->context.asce_limit = 1UL << 42;
+ mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+ _ASCE_USER_BITS |
+ _ASCE_TYPE_REGION3;
+ break;
+ case _REGION_ENTRY_TYPE_R3:
+ mm->context.asce_limit = 1UL << 31;
+ mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+ _ASCE_USER_BITS |
+ _ASCE_TYPE_SEGMENT;
+ break;
+ default:
+ BUG();
+ }
+ mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
+ crst_table_free(mm, (unsigned long *) pgd);
+ }
+ update_mm(mm, current);
+}
+#endif
+
/*
* page table entry allocation/free routines.
*/
-unsigned long *page_table_alloc(int noexec)
+unsigned long *page_table_alloc(struct mm_struct *mm)
{
- struct page *page = alloc_page(GFP_KERNEL);
+ struct page *page;
unsigned long *table;
+ unsigned long bits;
- if (!page)
- return NULL;
- page->index = 0;
- if (noexec) {
- struct page *shadow = alloc_page(GFP_KERNEL);
- if (!shadow) {
- __free_page(page);
+ bits = mm->context.noexec ? 3UL : 1UL;
+ spin_lock(&mm->page_table_lock);
+ page = NULL;
+ if (!list_empty(&mm->context.pgtable_list)) {
+ page = list_first_entry(&mm->context.pgtable_list,
+ struct page, lru);
+ if ((page->flags & FRAG_MASK) == ((1UL << TABLES_PER_PAGE) - 1))
+ page = NULL;
+ }
+ if (!page) {
+ spin_unlock(&mm->page_table_lock);
+ page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
+ if (!page)
return NULL;
- }
- table = (unsigned long *) page_to_phys(shadow);
+ pgtable_page_ctor(page);
+ page->flags &= ~FRAG_MASK;
+ table = (unsigned long *) page_to_phys(page);
clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
- page->index = (addr_t) table;
+ spin_lock(&mm->page_table_lock);
+ list_add(&page->lru, &mm->context.pgtable_list);
}
table = (unsigned long *) page_to_phys(page);
- clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
+ while (page->flags & bits) {
+ table += 256;
+ bits <<= 1;
+ }
+ page->flags |= bits;
+ if ((page->flags & FRAG_MASK) == ((1UL << TABLES_PER_PAGE) - 1))
+ list_move_tail(&page->lru, &mm->context.pgtable_list);
+ spin_unlock(&mm->page_table_lock);
return table;
}
-void page_table_free(unsigned long *table)
+void page_table_free(struct mm_struct *mm, unsigned long *table)
{
- unsigned long *shadow = get_shadow_pte(table);
+ struct page *page;
+ unsigned long bits;
- if (shadow)
- free_page((unsigned long) shadow);
- free_page((unsigned long) table);
+ bits = mm->context.noexec ? 3UL : 1UL;
+ bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
+ page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+ spin_lock(&mm->page_table_lock);
+ page->flags ^= bits;
+ if (page->flags & FRAG_MASK) {
+ /* Page now has some free pgtable fragments. */
+ list_move(&page->lru, &mm->context.pgtable_list);
+ page = NULL;
+ } else
+ /* All fragments of the 4K page have been freed. */
+ list_del(&page->lru);
+ spin_unlock(&mm->page_table_lock);
+ if (page) {
+ pgtable_page_dtor(page);
+ __free_page(page);
+ }
+}
+void disable_noexec(struct mm_struct *mm, struct task_struct *tsk)
+{
+ struct page *page;
+
+ spin_lock(&mm->page_table_lock);
+ /* Free shadow region and segment tables. */
+ list_for_each_entry(page, &mm->context.crst_list, lru)
+ if (page->index) {
+ free_pages((unsigned long) page->index, ALLOC_ORDER);
+ page->index = 0;
+ }
+ /* "Free" second halves of page tables. */
+ list_for_each_entry(page, &mm->context.pgtable_list, lru)
+ page->flags &= ~SECOND_HALVES;
+ spin_unlock(&mm->page_table_lock);
+ mm->context.noexec = 0;
+ update_mm(mm, tsk);
}
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 79d13a166a3..35d90a4720f 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -62,14 +62,26 @@ void __meminit memmap_init(unsigned long size, int nid, unsigned long zone,
}
}
-static void __init_refok *vmem_alloc_pages(unsigned int order)
+static void __ref *vmem_alloc_pages(unsigned int order)
{
if (slab_is_available())
return (void *)__get_free_pages(GFP_KERNEL, order);
return alloc_bootmem_pages((1 << order) * PAGE_SIZE);
}
-#define vmem_pud_alloc() ({ BUG(); ((pud_t *) NULL); })
+static inline pud_t *vmem_pud_alloc(void)
+{
+ pud_t *pud = NULL;
+
+#ifdef CONFIG_64BIT
+ pud = vmem_alloc_pages(2);
+ if (!pud)
+ return NULL;
+ pud_val(*pud) = _REGION3_ENTRY_EMPTY;
+ memcpy(pud + 1, pud, (PTRS_PER_PUD - 1)*sizeof(pud_t));
+#endif
+ return pud;
+}
static inline pmd_t *vmem_pmd_alloc(void)
{
@@ -84,13 +96,18 @@ static inline pmd_t *vmem_pmd_alloc(void)
return pmd;
}
-static inline pte_t *vmem_pte_alloc(void)
+static pte_t __init_refok *vmem_pte_alloc(void)
{
- pte_t *pte = vmem_alloc_pages(0);
+ pte_t *pte;
+ if (slab_is_available())
+ pte = (pte_t *) page_table_alloc(&init_mm);
+ else
+ pte = alloc_bootmem(PTRS_PER_PTE * sizeof(pte_t));
if (!pte)
return NULL;
- clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY, PAGE_SIZE);
+ clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY,
+ PTRS_PER_PTE * sizeof(pte_t));
return pte;
}
@@ -250,7 +267,7 @@ static int insert_memory_segment(struct memory_segment *seg)
{
struct memory_segment *tmp;
- if (seg->start + seg->size >= VMALLOC_START ||
+ if (seg->start + seg->size >= VMEM_MAX_PHYS ||
seg->start + seg->size < seg->start)
return -ERANGE;
@@ -360,7 +377,9 @@ void __init vmem_map_init(void)
{
int i;
- BUILD_BUG_ON((unsigned long)VMEM_MAP + VMEM_MAP_SIZE > VMEM_MAP_MAX);
+ INIT_LIST_HEAD(&init_mm.context.crst_list);
+ INIT_LIST_HEAD(&init_mm.context.pgtable_list);
+ init_mm.context.noexec = 0;
NODE_DATA(0)->node_mem_map = VMEM_MAP;
for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++)
vmem_add_mem(memory_chunk[i].addr, memory_chunk[i].size);
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 1c3a90835c7..b3400b5ad5c 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -8,6 +8,7 @@ mainmenu "Linux/SuperH Kernel Configuration"
config SUPERH
def_bool y
select EMBEDDED
+ select HAVE_IDE
select HAVE_OPROFILE
help
The SuperH is a RISC processor targeted for use in embedded systems
@@ -89,6 +90,12 @@ config ARCH_HAS_ILOG2_U64
config ARCH_NO_VIRT_TO_BUS
def_bool y
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
+config IO_TRAPPED
+ bool
+
source "init/Kconfig"
menu "System type"
@@ -308,6 +315,13 @@ config CPU_SUBTYPE_SH7722
select ARCH_SPARSEMEM_ENABLE
select SYS_SUPPORTS_NUMA
+config CPU_SUBTYPE_SH7366
+ bool "Support SH7366 processor"
+ select CPU_SH4AL_DSP
+ select CPU_SHX2
+ select ARCH_SPARSEMEM_ENABLE
+ select SYS_SUPPORTS_NUMA
+
# SH-5 Processor Support
config CPU_SUBTYPE_SH5_101
@@ -452,6 +466,7 @@ config SH_RTS7751R2D
bool "RTS7751R2D"
depends on CPU_SUBTYPE_SH7751R
select SYS_SUPPORTS_PCI
+ select IO_TRAPPED
help
Select RTS7751R2D if configuring for a Renesas Technology
Sales SH-Graphics board.
@@ -468,6 +483,14 @@ config SH_HIGHLANDER
bool "Highlander"
depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
select SYS_SUPPORTS_PCI
+ select IO_TRAPPED
+
+config SH_MIGOR
+ bool "Migo-R"
+ depends on CPU_SUBTYPE_SH7722
+ help
+ Select Migo-R if configuring for the SH7722 Migo-R platform
+ by Renesas System Solutions Asia Pte. Ltd.
config SH_EDOSK7705
bool "EDOSK7705"
diff --git a/arch/sh/Kconfig.cpu b/arch/sh/Kconfig.cpu
index d850184d069..0e27fe3b182 100644
--- a/arch/sh/Kconfig.cpu
+++ b/arch/sh/Kconfig.cpu
@@ -12,6 +12,7 @@ config CPU_LITTLE_ENDIAN
config CPU_BIG_ENDIAN
bool "Big Endian"
+ depends on !CPU_SH5
endchoice
@@ -87,9 +88,6 @@ config SH64_ID2815_WORKAROUND
config CPU_HAS_INTEVT
bool
-config CPU_HAS_MASKREG_IRQ
- bool
-
config CPU_HAS_IPR_IRQ
bool
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index f7c716166ce..5dcb74b947a 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -29,7 +29,8 @@ config EARLY_SCIF_CONSOLE
config EARLY_SCIF_CONSOLE_PORT
hex
depends on EARLY_SCIF_CONSOLE
- default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763
+ default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763
+ default "0xffe00000" if CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366
default "0xffea0000" if CPU_SUBTYPE_SH7785
default "0xfffe8000" if CPU_SUBTYPE_SH7203
default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 17fc36186bf..81381e5773c 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -116,6 +116,7 @@ machdir-$(CONFIG_SH_RTS7751R2D) += renesas/rts7751r2d
machdir-$(CONFIG_SH_7751_SYSTEMH) += renesas/systemh
machdir-$(CONFIG_SH_EDOSK7705) += renesas/edosk7705
machdir-$(CONFIG_SH_HIGHLANDER) += renesas/r7780rp
+machdir-$(CONFIG_SH_MIGOR) += renesas/migor
machdir-$(CONFIG_SH_SDK7780) += renesas/sdk7780
machdir-$(CONFIG_SH_7710VOIPGW) += renesas/sh7710voipgw
machdir-$(CONFIG_SH_X3PROTO) += renesas/x3proto
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
index eda71763ecc..2b708ec7255 100644
--- a/arch/sh/boards/landisk/setup.c
+++ b/arch/sh/boards/landisk/setup.c
@@ -14,7 +14,7 @@
*/
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/pm.h>
#include <linux/mm.h>
#include <asm/machvec.h>
diff --git a/arch/sh/boards/lboxre2/setup.c b/arch/sh/boards/lboxre2/setup.c
index 9c830fdc411..c74440d38ee 100644
--- a/arch/sh/boards/lboxre2/setup.c
+++ b/arch/sh/boards/lboxre2/setup.c
@@ -13,7 +13,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <asm/machvec.h>
#include <asm/addrspace.h>
#include <asm/lboxre2.h>
diff --git a/arch/sh/boards/renesas/migor/Makefile b/arch/sh/boards/renesas/migor/Makefile
new file mode 100644
index 00000000000..77037567633
--- /dev/null
+++ b/arch/sh/boards/renesas/migor/Makefile
@@ -0,0 +1 @@
+obj-y := setup.o
diff --git a/arch/sh/boards/renesas/migor/setup.c b/arch/sh/boards/renesas/migor/setup.c
new file mode 100644
index 00000000000..21ab8c8fb59
--- /dev/null
+++ b/arch/sh/boards/renesas/migor/setup.c
@@ -0,0 +1,61 @@
+/*
+ * Renesas System Solutions Asia Pte. Ltd - Migo-R
+ *
+ * Copyright (C) 2008 Magnus Damm
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+
+/* Address IRQ Size Bus Description
+ * 0x00000000 64MB 16 NOR Flash (SP29PL256N)
+ * 0x0c000000 64MB 64 SDRAM (2xK4M563233G)
+ * 0x10000000 IRQ0 16 Ethernet (SMC91C111)
+ * 0x14000000 IRQ4 16 USB 2.0 Host Controller (M66596)
+ * 0x18000000 8GB 8 NAND Flash (K9K8G08U0A)
+ */
+
+static struct resource smc91x_eth_resources[] = {
+ [0] = {
+ .name = "smc91x-regs" ,
+ .start = P2SEGADDR(0x10000300),
+ .end = P2SEGADDR(0x1000030f),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 32, /* IRQ0 */
+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
+ },
+};
+
+static struct platform_device smc91x_eth_device = {
+ .name = "smc91x",
+ .num_resources = ARRAY_SIZE(smc91x_eth_resources),
+ .resource = smc91x_eth_resources,
+};
+
+static struct platform_device *migor_devices[] __initdata = {
+ &smc91x_eth_device,
+};
+
+static int __init migor_devices_setup(void)
+{
+ return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
+}
+__initcall(migor_devices_setup);
+
+static void __init migor_setup(char **cmdline_p)
+{
+ ctrl_outw(0x1000, 0xa4050110); /* Enable IRQ0 in PJCR */
+}
+
+static struct sh_machine_vector mv_migor __initmv = {
+ .mv_name = "Migo-R",
+ .mv_setup = migor_setup,
+};
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
index a43b47726f5..2f68bea7890 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -15,7 +15,7 @@
*/
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/types.h>
#include <net/ax88796.h>
#include <asm/machvec.h>
@@ -23,6 +23,7 @@
#include <asm/clock.h>
#include <asm/heartbeat.h>
#include <asm/io.h>
+#include <asm/io_trapped.h>
static struct resource r8a66597_usb_host_resources[] = {
[0] = {
@@ -181,13 +182,27 @@ static struct platform_device *r7780rp_devices[] __initdata = {
&m66592_usb_peripheral_device,
&heartbeat_device,
#ifndef CONFIG_SH_R7780RP
- &cf_ide_device,
&ax88796_device,
#endif
};
+/*
+ * The CF is connected using a 16-bit bus where 8-bit operations are
+ * unsupported. The linux ata driver is however using 8-bit operations, so
+ * insert a trapped io filter to convert 8-bit operations into 16-bit.
+ */
+static struct trapped_io cf_trapped_io = {
+ .resource = cf_ide_resources,
+ .num_resources = 2,
+ .minimum_bus_width = 16,
+};
+
static int __init r7780rp_devices_setup(void)
{
+#ifndef CONFIG_SH_R7780RP
+ if (register_trapped_io(&cf_trapped_io) == 0)
+ platform_device_register(&cf_ide_device);
+#endif
return platform_add_devices(r7780rp_devices,
ARRAY_SIZE(r7780rp_devices));
}
@@ -226,34 +241,6 @@ static void r7780rp_power_off(void)
ctrl_outw(0x0001, PA_POFF);
}
-static inline unsigned char is_ide_ioaddr(unsigned long addr)
-{
- return ((cf_ide_resources[0].start <= addr &&
- addr <= cf_ide_resources[0].end) ||
- (cf_ide_resources[1].start <= addr &&
- addr <= cf_ide_resources[1].end));
-}
-
-void highlander_writeb(u8 b, void __iomem *addr)
-{
- unsigned long tmp = (unsigned long __force)addr;
-
- if (is_ide_ioaddr(tmp))
- ctrl_outw((u16)b, tmp);
- else
- ctrl_outb(b, tmp);
-}
-
-u8 highlander_readb(void __iomem *addr)
-{
- unsigned long tmp = (unsigned long __force)addr;
-
- if (is_ide_ioaddr(tmp))
- return ctrl_inw(tmp) & 0xff;
- else
- return ctrl_inb(tmp);
-}
-
/*
* Initialize the board
*/
@@ -338,6 +325,4 @@ static struct sh_machine_vector mv_highlander __initmv = {
.mv_setup = highlander_setup,
.mv_init_irq = highlander_init_irq,
.mv_irq_demux = highlander_irq_demux,
- .mv_readb = highlander_readb,
- .mv_writeb = highlander_writeb,
};
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
index 3452b072add..f21ee49ef3a 100644
--- a/arch/sh/boards/renesas/rts7751r2d/setup.c
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -10,7 +10,7 @@
*/
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <linux/serial_8250.h>
#include <linux/sm501.h>
#include <linux/sm501-regs.h>
@@ -21,6 +21,7 @@
#include <asm/machvec.h>
#include <asm/rts7751r2d.h>
#include <asm/io.h>
+#include <asm/io_trapped.h>
#include <asm/spi.h>
static struct resource cf_ide_resources[] = {
@@ -214,13 +215,25 @@ static struct platform_device *rts7751r2d_devices[] __initdata = {
&uart_device,
&sm501_device,
#endif
- &cf_ide_device,
&heartbeat_device,
&spi_sh_sci_device,
};
+/*
+ * The CF is connected with a 16-bit bus where 8-bit operations are
+ * unsupported. The linux ata driver is however using 8-bit operations, so
+ * insert a trapped io filter to convert 8-bit operations into 16-bit.
+ */
+static struct trapped_io cf_trapped_io = {
+ .resource = cf_ide_resources,
+ .num_resources = 2,
+ .minimum_bus_width = 16,
+};
+
static int __init rts7751r2d_devices_setup(void)
{
+ if (register_trapped_io(&cf_trapped_io) == 0)
+ platform_device_register(&cf_ide_device);
spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus));
return platform_add_devices(rts7751r2d_devices,
ARRAY_SIZE(rts7751r2d_devices));
@@ -232,34 +245,6 @@ static void rts7751r2d_power_off(void)
ctrl_outw(0x0001, PA_POWOFF);
}
-static inline unsigned char is_ide_ioaddr(unsigned long addr)
-{
- return ((cf_ide_resources[0].start <= addr &&
- addr <= cf_ide_resources[0].end) ||
- (cf_ide_resources[1].start <= addr &&
- addr <= cf_ide_resources[1].end));
-}
-
-void rts7751r2d_writeb(u8 b, void __iomem *addr)
-{
- unsigned long tmp = (unsigned long __force)addr;
-
- if (is_ide_ioaddr(tmp))
- ctrl_outw((u16)b, tmp);
- else
- ctrl_outb(b, tmp);
-}
-
-u8 rts7751r2d_readb(void __iomem *addr)
-{
- unsigned long tmp = (unsigned long __force)addr;
-
- if (is_ide_ioaddr(tmp))
- return ctrl_inw(tmp) & 0xff;
- else
- return ctrl_inb(tmp);
-}
-
/*
* Initialize the board
*/
@@ -310,6 +295,4 @@ static struct sh_machine_vector mv_rts7751r2d __initmv = {
.mv_setup = rts7751r2d_setup,
.mv_init_irq = init_rts7751r2d_IRQ,
.mv_irq_demux = rts7751r2d_irq_demux,
- .mv_writeb = rts7751r2d_writeb,
- .mv_readb = rts7751r2d_readb,
};
diff --git a/arch/sh/boards/renesas/sdk7780/Kconfig b/arch/sh/boards/renesas/sdk7780/Kconfig
index e4f5b6985be..065f1df09bf 100644
--- a/arch/sh/boards/renesas/sdk7780/Kconfig
+++ b/arch/sh/boards/renesas/sdk7780/Kconfig
@@ -4,13 +4,6 @@ choice
prompt "SDK7780 options"
default SH_SDK7780_BASE
-config SH_SDK7780_STANDALONE
- bool "SDK7780 board support"
- depends on CPU_SUBTYPE_SH7780
- help
- Selecting this option will enable support for the
- standalone version of the SDK7780. If in doubt, say Y.
-
config SH_SDK7780_BASE
bool "SDK7780 with base-board support"
depends on CPU_SUBTYPE_SH7780
diff --git a/arch/sh/boards/renesas/sdk7780/setup.c b/arch/sh/boards/renesas/sdk7780/setup.c
index 5df32f20187..acc5932587f 100644
--- a/arch/sh/boards/renesas/sdk7780/setup.c
+++ b/arch/sh/boards/renesas/sdk7780/setup.c
@@ -11,7 +11,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <asm/machvec.h>
#include <asm/sdk7780.h>
#include <asm/heartbeat.h>
diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c
index eb97dca5b73..b1a3d9d0172 100644
--- a/arch/sh/boards/se/7722/setup.c
+++ b/arch/sh/boards/se/7722/setup.c
@@ -12,7 +12,7 @@
*/
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
#include <asm/machvec.h>
#include <asm/se7722.h>
#include <asm/io.h>
diff --git a/arch/sh/cchips/hd6446x/hd64465/setup.c b/arch/sh/cchips/hd6446x/hd64465/setup.c
index 5cef0db4018..9b8820c3670 100644
--- a/arch/sh/cchips/hd6446x/hd64465/setup.c
+++ b/arch/sh/cchips/hd6446x/hd64465/setup.c
@@ -17,10 +17,8 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
-
#include <asm/io.h>
#include <asm/irq.h>
-
#include <asm/hd64465/hd64465.h>
static void disable_hd64465_irq(unsigned int irq)
@@ -28,51 +26,45 @@ static void disable_hd64465_irq(unsigned int irq)
unsigned short nimr;
unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
- pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask);
+ pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask);
nimr = inw(HD64465_REG_NIMR);
nimr |= mask;
outw(nimr, HD64465_REG_NIMR);
}
-
static void enable_hd64465_irq(unsigned int irq)
{
unsigned short nimr;
unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
- pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask);
+ pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask);
nimr = inw(HD64465_REG_NIMR);
nimr &= ~mask;
outw(nimr, HD64465_REG_NIMR);
}
-
static void mask_and_ack_hd64465(unsigned int irq)
{
disable_hd64465_irq(irq);
}
-
static void end_hd64465_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
enable_hd64465_irq(irq);
}
-
static unsigned int startup_hd64465_irq(unsigned int irq)
-{
+{
enable_hd64465_irq(irq);
return 0;
}
-
static void shutdown_hd64465_irq(unsigned int irq)
{
disable_hd64465_irq(irq);
}
-
static struct hw_interrupt_type hd64465_irq_type = {
.typename = "HD64465-IRQ",
.startup = startup_hd64465_irq,
@@ -83,7 +75,6 @@ static struct hw_interrupt_type hd64465_irq_type = {
.end = end_hd64465_irq,
};
-
static irqreturn_t hd64465_interrupt(int irq, void *dev_id)
{
printk(KERN_INFO
@@ -93,9 +84,6 @@ static irqreturn_t hd64465_interrupt(int irq, void *dev_id)
return IRQ_NONE;
}
-
-/*====================================================*/
-
/*
* Support for a secondary IRQ demux step. This is necessary
* because the HD64465 presents a very thin interface to the
@@ -103,8 +91,7 @@ static irqreturn_t hd64465_interrupt(int irq, void *dev_id)
* normally done in hardware by other PCMCIA host bridges is
* instead done in software.
*/
-static struct
-{
+static struct {
int (*func)(int, void *);
void *dev;
} hd64465_demux[HD64465_IRQ_NUM];
@@ -112,19 +99,17 @@ static struct
void hd64465_register_irq_demux(int irq,
int (*demux)(int irq, void *dev), void *dev)
{
- hd64465_demux[irq - HD64465_IRQ_BASE].func = demux;
- hd64465_demux[irq - HD64465_IRQ_BASE].dev = dev;
+ hd64465_demux[irq - HD64465_IRQ_BASE].func = demux;
+ hd64465_demux[irq - HD64465_IRQ_BASE].dev = dev;
}
EXPORT_SYMBOL(hd64465_register_irq_demux);
void hd64465_unregister_irq_demux(int irq)
{
- hd64465_demux[irq - HD64465_IRQ_BASE].func = 0;
+ hd64465_demux[irq - HD64465_IRQ_BASE].func = 0;
}
EXPORT_SYMBOL(hd64465_unregister_irq_demux);
-
-
int hd64465_irq_demux(int irq)
{
if (irq == CONFIG_HD64465_IRQ) {
@@ -132,16 +117,16 @@ int hd64465_irq_demux(int irq)
unsigned short nirr = inw(HD64465_REG_NIRR);
unsigned short nimr = inw(HD64465_REG_NIMR);
- pr_debug("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr);
+ pr_debug("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr);
nirr &= ~nimr;
for (bit = 1, i = 0 ; i < HD64465_IRQ_NUM ; bit <<= 1, i++)
if (nirr & bit)
- break;
+ break;
- if (i < HD64465_IRQ_NUM) {
+ if (i < HD64465_IRQ_NUM) {
irq = HD64465_IRQ_BASE + i;
- if (hd64465_demux[i].func != 0)
- irq = hd64465_demux[i].func(irq, hd64465_demux[i].dev);
+ if (hd64465_demux[i].func != 0)
+ irq = hd64465_demux[i].func(irq, hd64465_demux[i].dev);
}
}
return irq;
@@ -154,7 +139,6 @@ static struct irqaction irq0 = {
.name = "HD64465",
};
-
static int __init setup_hd64465(void)
{
int i;
@@ -176,8 +160,8 @@ static int __init setup_hd64465(void)
rev = inw(HD64465_REG_SRR);
printk(KERN_INFO "HD64465 hardware revision %d.%d\n", (rev >> 8) & 0xff, rev & 0xff);
-
- outw(0xffff, HD64465_REG_NIMR); /* mask all interrupts */
+
+ outw(0xffff, HD64465_REG_NIMR); /* mask all interrupts */
for (i = 0; i < HD64465_IRQ_NUM ; i++) {
irq_desc[HD64465_IRQ_BASE + i].chip = &hd64465_irq_type;
@@ -185,16 +169,13 @@ static int __init setup_hd64465(void)
setup_irq(CONFIG_HD64465_IRQ, &irq0);
-#ifdef CONFIG_SERIAL
/* wake up the UART from STANDBY at this point */
smscr = inw(HD64465_REG_SMSCR);
outw(smscr & (~HD64465_SMSCR_UARTST), HD64465_REG_SMSCR);
/* remap IO ports for first ISA serial port to HD64465 UART */
hd64465_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1);
-#endif
return 0;
}
-
module_init(setup_hd64465);
diff --git a/arch/sh/configs/migor_defconfig b/arch/sh/configs/migor_defconfig
new file mode 100644
index 00000000000..ee5900817f8
--- /dev/null
+++ b/arch/sh/configs/migor_defconfig
@@ -0,0 +1,824 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.24
+# Wed Feb 6 21:52:20 2008
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_NUMA=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_KPROBES is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+CONFIG_CPU_SH4AL_DSP=y
+CONFIG_CPU_SHX2=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+CONFIG_CPU_SUBTYPE_SH7722=y
+# CONFIG_CPU_SUBTYPE_SH5_101 is not set
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_29BIT=y
+# CONFIG_X2TLB is not set
+CONFIG_VSYSCALL=y
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=1
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=2
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_MIGRATION is not set
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_SH_FPU_EMU is not set
+CONFIG_SH_DSP=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
+CONFIG_CPU_HAS_DSP=y
+
+#
+# Board support
+#
+# CONFIG_SH_7722_SOLUTION_ENGINE is not set
+CONFIG_SH_MIGOR=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_PCLK_FREQ=33333333
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_RCU_TRACE=y
+CONFIG_GUSA=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC0,115200 earlyprintk=serial ip=on"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_STNIC is not set
+CONFIG_SMC91X=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=3
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+CONFIG_USB_GADGET_M66592=y
+CONFIG_USB_M66592=y
+CONFIG_SUPERH_BUILT_IN_M66592=y
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+CONFIG_USB_G_SERIAL=y
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SH=y
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe00000
+CONFIG_EARLY_PRINTK=y
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_SEQIV is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/rts7751r2d1_defconfig b/arch/sh/configs/rts7751r2d1_defconfig
index 2dc754e5b73..3a915fd436d 100644
--- a/arch/sh/configs/rts7751r2d1_defconfig
+++ b/arch/sh/configs/rts7751r2d1_defconfig
@@ -1,9 +1,10 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc2
-# Tue Aug 14 18:04:44 2007
+# Linux kernel version: 2.6.24
+# Thu Feb 7 16:25:55 2008
#
CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -36,9 +37,14 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -53,6 +59,7 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -65,6 +72,13 @@ CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_KPROBES is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -91,13 +105,17 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_RCU is not set
#
# System type
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
# CONFIG_CPU_SUBTYPE_SH7705 is not set
# CONFIG_CPU_SUBTYPE_SH7706 is not set
# CONFIG_CPU_SUBTYPE_SH7707 is not set
@@ -105,6 +123,8 @@ CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7709 is not set
# CONFIG_CPU_SUBTYPE_SH7710 is not set
# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
# CONFIG_CPU_SUBTYPE_SH7091 is not set
# CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -113,14 +133,15 @@ CONFIG_CPU_SH4=y
CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
-# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
-# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
# CONFIG_CPU_SUBTYPE_SH7785 is not set
# CONFIG_CPU_SUBTYPE_SHX3 is not set
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH5_101 is not set
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -130,6 +151,7 @@ CONFIG_MMU=y
CONFIG_PAGE_OFFSET=0x80000000
CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_29BIT=y
CONFIG_VSYSCALL=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
@@ -147,6 +169,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
@@ -168,23 +191,22 @@ CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SH_FPU=y
# CONFIG_SH_STORE_QUEUES is not set
CONFIG_CPU_HAS_INTEVT=y
-CONFIG_CPU_HAS_INTC_IRQ=y
CONFIG_CPU_HAS_SR_RB=y
CONFIG_CPU_HAS_PTEA=y
+CONFIG_CPU_HAS_FPU=y
#
# Board support
#
# CONFIG_SH_7751_SYSTEMH is not set
# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
CONFIG_SH_RTS7751R2D=y
# CONFIG_SH_LANDISK is not set
# CONFIG_SH_TITAN is not set
# CONFIG_SH_LBOX_RE2 is not set
#
-# RTS7751R2D options
+# RTS7751R2D Board Revision
#
# CONFIG_RTS7751R2D_PLUS is not set
CONFIG_RTS7751R2D_1=y
@@ -198,6 +220,7 @@ CONFIG_SH_PCLK_FREQ=60000000
# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
#
# CPU Frequency scaling
@@ -227,11 +250,15 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
# CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
+CONFIG_RCU_TRACE=y
+CONFIG_GUSA=y
+# CONFIG_GUSA_RB is not set
#
# Boot options
@@ -250,10 +277,7 @@ CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+CONFIG_PCI_LEGACY=y
# CONFIG_PCCARD is not set
CONFIG_HOTPLUG_PCI=y
# CONFIG_HOTPLUG_PCI_FAKE is not set
@@ -281,6 +305,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -299,6 +324,7 @@ CONFIG_IP_FIB_HASH=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -324,10 +350,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
#
@@ -335,6 +357,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
@@ -356,6 +379,7 @@ CONFIG_WIRELESS_EXT=y
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=m
@@ -371,6 +395,7 @@ CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
@@ -420,6 +445,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
@@ -493,7 +519,9 @@ CONFIG_ATA=y
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OPTI is not set
# CONFIG_PATA_OPTIDMA is not set
# CONFIG_PATA_PDC_OLD is not set
@@ -508,14 +536,7 @@ CONFIG_ATA=y
# CONFIG_PATA_WINBOND is not set
CONFIG_PATA_PLATFORM=y
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
@@ -530,25 +551,31 @@ CONFIG_NETDEVICES=y
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
+# CONFIG_VETH is not set
# CONFIG_ARCNET is not set
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
+# CONFIG_AX88796 is not set
# CONFIG_STNIC is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
+# CONFIG_ENC28J60 is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
@@ -560,6 +587,7 @@ CONFIG_8139TOO=y
# CONFIG_8139TOO_TUNE_TWISTER is not set
# CONFIG_8139TOO_8129 is not set
# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
@@ -570,6 +598,10 @@ CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_E1000E_ENABLED is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -577,6 +609,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
@@ -585,11 +618,15 @@ CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
# CONFIG_TR is not set
#
@@ -597,13 +634,21 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -622,7 +667,6 @@ CONFIG_INPUT=y
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -650,6 +694,7 @@ CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
#
# Serial drivers
@@ -674,11 +719,9 @@ CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
@@ -687,16 +730,30 @@ CONFIG_DEVPORT=y
#
# SPI support
#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_SH_SCI=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM70 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
@@ -708,6 +765,13 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
# Multifunction device drivers
@@ -720,16 +784,12 @@ CONFIG_MFD_SM501=y
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
@@ -738,6 +798,7 @@ CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -777,6 +838,12 @@ CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_PM3 is not set
CONFIG_FB_SM501=y
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
#
# Console display driver support
@@ -844,6 +911,7 @@ CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_BT87X is not set
# CONFIG_SND_CA0106 is not set
# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
# CONFIG_SND_DARLA20 is not set
@@ -868,6 +936,7 @@ CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_HDA_INTEL is not set
# CONFIG_SND_HDSP is not set
# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
# CONFIG_SND_ICE1712 is not set
# CONFIG_SND_ICE1724 is not set
# CONFIG_SND_INTEL8X0 is not set
@@ -885,16 +954,27 @@ CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_TRIDENT is not set
# CONFIG_SND_VIA82XX is not set
# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
# CONFIG_SND_VX222 is not set
CONFIG_SND_YMFPCI=m
CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL=y
# CONFIG_SND_AC97_POWER_SAVE is not set
#
+# SPI devices
+#
+
+#
# SUPERH devices
#
#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
# System on Chip audio support
#
# CONFIG_SND_SOC is not set
@@ -904,6 +984,10 @@ CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL=y
#
#
+# ALSA SoC audio for Freescale SOCs
+#
+
+#
# Open Sound System
#
CONFIG_SOUND_PRIME=m
@@ -914,19 +998,104 @@ CONFIG_AC97_BUS=m
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
-# USB Gadget Support
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
# CONFIG_NEW_LEDS is not set
@@ -949,13 +1118,17 @@ CONFIG_RTC_INTF_DEV=y
#
# SPI RTC drivers
#
+# CONFIG_RTC_DRV_MAX6902 is not set
+CONFIG_RTC_DRV_R9701=y
+# CONFIG_RTC_DRV_RS5C348 is not set
#
# Platform RTC drivers
#
+# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_M48T59 is not set
# CONFIG_RTC_DRV_V3020 is not set
@@ -963,20 +1136,7 @@ CONFIG_RTC_INTF_DEV=y
#
# on-CPU RTC drivers
#
-CONFIG_RTC_DRV_SH=y
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
+# CONFIG_RTC_DRV_SH is not set
#
# Userspace I/O
@@ -1034,7 +1194,6 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -1053,10 +1212,7 @@ CONFIG_RAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
# CONFIG_SMB_FS is not set
@@ -1070,10 +1226,6 @@ CONFIG_RAMFS=y
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
@@ -1114,30 +1266,22 @@ CONFIG_NLS_CODEPAGE_932=y
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
#
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-
-#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
# CONFIG_SH_STANDARD_BIOS is not set
CONFIG_EARLY_SCIF_CONSOLE=y
CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
@@ -1149,7 +1293,53 @@ CONFIG_EARLY_PRINTK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
-# CONFIG_CRYPTO is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_SEQIV is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
#
# Library routines
diff --git a/arch/sh/configs/rts7751r2dplus_defconfig b/arch/sh/configs/rts7751r2dplus_defconfig
index 4ff5a752dcd..0a6d3b9e648 100644
--- a/arch/sh/configs/rts7751r2dplus_defconfig
+++ b/arch/sh/configs/rts7751r2dplus_defconfig
@@ -1,9 +1,10 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23-rc2
-# Tue Aug 14 16:33:08 2007
+# Linux kernel version: 2.6.24
+# Thu Feb 7 16:17:47 2008
#
CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -36,9 +37,14 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FAIR_USER_SCHED=y
+# CONFIG_FAIR_CGROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
@@ -53,6 +59,7 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -65,6 +72,13 @@ CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_KPROBES is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -91,13 +105,17 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_RCU is not set
#
# System type
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
# CONFIG_CPU_SUBTYPE_SH7705 is not set
# CONFIG_CPU_SUBTYPE_SH7706 is not set
# CONFIG_CPU_SUBTYPE_SH7707 is not set
@@ -105,6 +123,8 @@ CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7709 is not set
# CONFIG_CPU_SUBTYPE_SH7710 is not set
# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
# CONFIG_CPU_SUBTYPE_SH7091 is not set
# CONFIG_CPU_SUBTYPE_SH7750R is not set
@@ -113,14 +133,15 @@ CONFIG_CPU_SH4=y
CONFIG_CPU_SUBTYPE_SH7751R=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
# CONFIG_CPU_SUBTYPE_SH4_202 is not set
-# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
-# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
# CONFIG_CPU_SUBTYPE_SH7770 is not set
# CONFIG_CPU_SUBTYPE_SH7780 is not set
# CONFIG_CPU_SUBTYPE_SH7785 is not set
# CONFIG_CPU_SUBTYPE_SHX3 is not set
# CONFIG_CPU_SUBTYPE_SH7343 is not set
# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH5_101 is not set
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
#
# Memory management options
@@ -130,6 +151,7 @@ CONFIG_MMU=y
CONFIG_PAGE_OFFSET=0x80000000
CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_29BIT=y
CONFIG_VSYSCALL=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
@@ -147,6 +169,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
@@ -168,23 +191,22 @@ CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SH_FPU=y
# CONFIG_SH_STORE_QUEUES is not set
CONFIG_CPU_HAS_INTEVT=y
-CONFIG_CPU_HAS_INTC_IRQ=y
CONFIG_CPU_HAS_SR_RB=y
CONFIG_CPU_HAS_PTEA=y
+CONFIG_CPU_HAS_FPU=y
#
# Board support
#
# CONFIG_SH_7751_SYSTEMH is not set
# CONFIG_SH_SECUREEDGE5410 is not set
-# CONFIG_SH_HS7751RVOIP is not set
CONFIG_SH_RTS7751R2D=y
# CONFIG_SH_LANDISK is not set
# CONFIG_SH_TITAN is not set
# CONFIG_SH_LBOX_RE2 is not set
#
-# RTS7751R2D options
+# RTS7751R2D Board Revision
#
CONFIG_RTS7751R2D_PLUS=y
# CONFIG_RTS7751R2D_1 is not set
@@ -198,6 +220,7 @@ CONFIG_SH_PCLK_FREQ=60000000
# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
#
# CPU Frequency scaling
@@ -227,11 +250,15 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
# CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
+CONFIG_RCU_TRACE=y
+CONFIG_GUSA=y
+# CONFIG_GUSA_RB is not set
#
# Boot options
@@ -250,10 +277,7 @@ CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+CONFIG_PCI_LEGACY=y
# CONFIG_PCCARD is not set
CONFIG_HOTPLUG_PCI=y
# CONFIG_HOTPLUG_PCI_FAKE is not set
@@ -281,6 +305,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -299,6 +324,7 @@ CONFIG_IP_FIB_HASH=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -324,10 +350,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
#
@@ -335,6 +357,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
@@ -356,6 +379,7 @@ CONFIG_WIRELESS_EXT=y
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=m
@@ -371,6 +395,7 @@ CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
@@ -420,6 +445,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_FC_ATTRS is not set
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
@@ -493,7 +519,9 @@ CONFIG_ATA=y
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OPTI is not set
# CONFIG_PATA_OPTIDMA is not set
# CONFIG_PATA_PDC_OLD is not set
@@ -508,14 +536,7 @@ CONFIG_ATA=y
# CONFIG_PATA_WINBOND is not set
CONFIG_PATA_PLATFORM=y
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
@@ -530,25 +551,31 @@ CONFIG_NETDEVICES=y
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
+# CONFIG_VETH is not set
# CONFIG_ARCNET is not set
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
+# CONFIG_AX88796 is not set
# CONFIG_STNIC is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
+# CONFIG_ENC28J60 is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
@@ -560,6 +587,7 @@ CONFIG_8139TOO=y
# CONFIG_8139TOO_TUNE_TWISTER is not set
# CONFIG_8139TOO_8129 is not set
# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
@@ -570,6 +598,10 @@ CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_E1000E_ENABLED is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -577,6 +609,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
@@ -585,11 +618,15 @@ CONFIG_NETDEV_1000=y
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
# CONFIG_TR is not set
#
@@ -597,13 +634,21 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -622,7 +667,6 @@ CONFIG_INPUT=y
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -650,6 +694,7 @@ CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
#
# Serial drivers
@@ -674,11 +719,9 @@ CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
@@ -687,16 +730,30 @@ CONFIG_DEVPORT=y
#
# SPI support
#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_SH_SCI=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM70 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
@@ -708,6 +765,13 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
#
# Multifunction device drivers
@@ -720,16 +784,12 @@ CONFIG_MFD_SM501=y
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_DRM is not set
# CONFIG_VGASTATE is not set
CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_FB=y
@@ -738,6 +798,7 @@ CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
@@ -777,6 +838,12 @@ CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_PM3 is not set
CONFIG_FB_SM501=y
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
#
# Console display driver support
@@ -844,6 +911,7 @@ CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_BT87X is not set
# CONFIG_SND_CA0106 is not set
# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
# CONFIG_SND_DARLA20 is not set
@@ -868,6 +936,7 @@ CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_HDA_INTEL is not set
# CONFIG_SND_HDSP is not set
# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
# CONFIG_SND_ICE1712 is not set
# CONFIG_SND_ICE1724 is not set
# CONFIG_SND_INTEL8X0 is not set
@@ -885,16 +954,27 @@ CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_TRIDENT is not set
# CONFIG_SND_VIA82XX is not set
# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
# CONFIG_SND_VX222 is not set
CONFIG_SND_YMFPCI=m
CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL=y
# CONFIG_SND_AC97_POWER_SAVE is not set
#
+# SPI devices
+#
+
+#
# SUPERH devices
#
#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
# System on Chip audio support
#
# CONFIG_SND_SOC is not set
@@ -904,6 +984,10 @@ CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL=y
#
#
+# ALSA SoC audio for Freescale SOCs
+#
+
+#
# Open Sound System
#
CONFIG_SOUND_PRIME=m
@@ -914,19 +998,104 @@ CONFIG_AC97_BUS=m
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
-# USB Gadget Support
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
# CONFIG_NEW_LEDS is not set
@@ -949,13 +1118,17 @@ CONFIG_RTC_INTF_DEV=y
#
# SPI RTC drivers
#
+# CONFIG_RTC_DRV_MAX6902 is not set
+CONFIG_RTC_DRV_R9701=y
+# CONFIG_RTC_DRV_RS5C348 is not set
#
# Platform RTC drivers
#
+# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_M48T59 is not set
# CONFIG_RTC_DRV_V3020 is not set
@@ -963,20 +1136,7 @@ CONFIG_RTC_INTF_DEV=y
#
# on-CPU RTC drivers
#
-CONFIG_RTC_DRV_SH=y
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
+# CONFIG_RTC_DRV_SH is not set
#
# Userspace I/O
@@ -1034,7 +1194,6 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -1053,10 +1212,7 @@ CONFIG_RAMFS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
# CONFIG_SMB_FS is not set
@@ -1070,10 +1226,6 @@ CONFIG_RAMFS=y
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
@@ -1114,30 +1266,22 @@ CONFIG_NLS_CODEPAGE_932=y
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
#
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-
-#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
# CONFIG_SH_STANDARD_BIOS is not set
CONFIG_EARLY_SCIF_CONSOLE=y
CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
@@ -1149,7 +1293,53 @@ CONFIG_EARLY_PRINTK=y
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
-# CONFIG_CRYPTO is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_SEQIV is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
#
# Library routines
diff --git a/arch/sh/configs/se7705_defconfig b/arch/sh/configs/se7705_defconfig
index 87ae5c1f862..84717d85486 100644
--- a/arch/sh/configs/se7705_defconfig
+++ b/arch/sh/configs/se7705_defconfig
@@ -231,7 +231,6 @@ CONFIG_CPU_LITTLE_ENDIAN=y
# CONFIG_SH_DSP is not set
# CONFIG_SH_ADC is not set
CONFIG_CPU_HAS_INTEVT=y
-CONFIG_CPU_HAS_PINT_IRQ=y
CONFIG_CPU_HAS_IPR_IRQ=y
CONFIG_CPU_HAS_SR_RB=y
diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c
index 76ed816d9a2..727126e907e 100644
--- a/arch/sh/drivers/dma/dma-api.c
+++ b/arch/sh/drivers/dma/dma-api.c
@@ -350,7 +350,7 @@ int register_dmac(struct dma_info *info)
BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels);
- info->pdev = platform_device_register_simple((char *)info->name, -1,
+ info->pdev = platform_device_register_simple(info->name, -1,
NULL, 0);
if (IS_ERR(info->pdev))
return PTR_ERR(info->pdev);
diff --git a/arch/sh/drivers/pci/fixups-lboxre2.c b/arch/sh/drivers/pci/fixups-lboxre2.c
index 40b19bdfb89..1c1d41255ec 100644
--- a/arch/sh/drivers/pci/fixups-lboxre2.c
+++ b/arch/sh/drivers/pci/fixups-lboxre2.c
@@ -18,7 +18,7 @@ int pci_fixup_pcic(void)
{
unsigned long bcr1, mcr;
- bcr1 = inl(SH7751_BCR1);
+ bcr1 = ctrl_inl(SH7751_BCR1);
bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
pci_write_reg(bcr1, SH4_PCIBCR1);
@@ -28,7 +28,7 @@ int pci_fixup_pcic(void)
pci_write_reg(0xfb900047, SH7751_PCICONF1);
pci_write_reg(0xab000001, SH7751_PCICONF4);
- mcr = inl(SH7751_MCR);
+ mcr = ctrl_inl(SH7751_MCR);
mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
pci_write_reg(mcr, SH4_PCIMCR);
diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
index e72ceb560d5..904bce8768d 100644
--- a/arch/sh/drivers/pci/fixups-rts7751r2d.c
+++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
@@ -19,7 +19,7 @@ int pci_fixup_pcic(void)
{
unsigned long bcr1, mcr;
- bcr1 = inl(SH7751_BCR1);
+ bcr1 = ctrl_inl(SH7751_BCR1);
bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */
pci_write_reg(bcr1, SH4_PCIBCR1);
@@ -30,7 +30,7 @@ int pci_fixup_pcic(void)
pci_write_reg(0xfb900047, SH7751_PCICONF1);
pci_write_reg(0xab000001, SH7751_PCICONF4);
- mcr = inl(SH7751_MCR);
+ mcr = ctrl_inl(SH7751_MCR);
mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
pci_write_reg(mcr, SH4_PCIMCR);
diff --git a/arch/sh/drivers/pci/ops-dreamcast.c b/arch/sh/drivers/pci/ops-dreamcast.c
index e1284fc6936..0dac87b1962 100644
--- a/arch/sh/drivers/pci/ops-dreamcast.c
+++ b/arch/sh/drivers/pci/ops-dreamcast.c
@@ -83,9 +83,9 @@ static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int
return PCIBIOS_DEVICE_NOT_FOUND;
switch (size) {
- case 1: *val = inb(GAPSPCI_BBA_CONFIG+where); break;
- case 2: *val = inw(GAPSPCI_BBA_CONFIG+where); break;
- case 4: *val = inl(GAPSPCI_BBA_CONFIG+where); break;
+ case 1: *val = ctrl_inb(GAPSPCI_BBA_CONFIG+where); break;
+ case 2: *val = ctrl_inw(GAPSPCI_BBA_CONFIG+where); break;
+ case 4: *val = ctrl_inl(GAPSPCI_BBA_CONFIG+where); break;
}
return PCIBIOS_SUCCESSFUL;
@@ -97,9 +97,9 @@ static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int
return PCIBIOS_DEVICE_NOT_FOUND;
switch (size) {
- case 1: outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break;
- case 2: outw((u16)val, GAPSPCI_BBA_CONFIG+where); break;
- case 4: outl((u32)val, GAPSPCI_BBA_CONFIG+where); break;
+ case 1: ctrl_outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break;
+ case 2: ctrl_outw((u16)val, GAPSPCI_BBA_CONFIG+where); break;
+ case 4: ctrl_outl((u32)val, GAPSPCI_BBA_CONFIG+where); break;
}
return PCIBIOS_SUCCESSFUL;
@@ -127,36 +127,36 @@ int __init gapspci_init(void)
*/
for (i=0; i<16; i++)
- idbuf[i] = inb(GAPSPCI_REGS+i);
+ idbuf[i] = ctrl_inb(GAPSPCI_REGS+i);
if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
return -ENODEV;
- outl(0x5a14a501, GAPSPCI_REGS+0x18);
+ ctrl_outl(0x5a14a501, GAPSPCI_REGS+0x18);
for (i=0; i<1000000; i++)
;
- if (inl(GAPSPCI_REGS+0x18) != 1)
+ if (ctrl_inl(GAPSPCI_REGS+0x18) != 1)
return -EINVAL;
- outl(0x01000000, GAPSPCI_REGS+0x20);
- outl(0x01000000, GAPSPCI_REGS+0x24);
+ ctrl_outl(0x01000000, GAPSPCI_REGS+0x20);
+ ctrl_outl(0x01000000, GAPSPCI_REGS+0x24);
- outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
- outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
+ ctrl_outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
+ ctrl_outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
- outl(1, GAPSPCI_REGS+0x14);
- outl(1, GAPSPCI_REGS+0x34);
+ ctrl_outl(1, GAPSPCI_REGS+0x14);
+ ctrl_outl(1, GAPSPCI_REGS+0x34);
/* Setting Broadband Adapter */
- outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
- outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
- outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
- outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
- outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
- outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
- outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
+ ctrl_outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
+ ctrl_outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
+ ctrl_outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
+ ctrl_outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
+ ctrl_outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
+ ctrl_outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
+ ctrl_outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
return 0;
}
diff --git a/arch/sh/drivers/pci/ops-rts7751r2d.c b/arch/sh/drivers/pci/ops-rts7751r2d.c
index ec8430c8d2d..b3fa3e2ef18 100644
--- a/arch/sh/drivers/pci/ops-rts7751r2d.c
+++ b/arch/sh/drivers/pci/ops-rts7751r2d.c
@@ -33,7 +33,7 @@ int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
static struct resource sh7751_io_resource = {
.name = "SH7751_IO",
.start = 0x4000,
- .end = 0x4000 + SH7751_PCI_IO_SIZE - 1,
+ .end = SH7751_PCI_IO_SIZE - 1,
.flags = IORESOURCE_IO
};
@@ -68,6 +68,7 @@ static struct sh4_pci_address_map sh7751_pci_map = {
int __init pcibios_init_platform(void)
{
+ __set_io_port_base(SH7751_PCI_IO_BASE);
return sh7751_pcic_init(&sh7751_pci_map);
}
diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
index 4925c79ea95..07e29506080 100644
--- a/arch/sh/drivers/pci/pci-sh4.h
+++ b/arch/sh/drivers/pci/pci-sh4.h
@@ -172,11 +172,11 @@ struct sh4_pci_address_map {
static inline void pci_write_reg(unsigned long val, unsigned long reg)
{
- outl(val, PCI_REG(reg));
+ ctrl_outl(val, PCI_REG(reg));
}
static inline unsigned long pci_read_reg(unsigned long reg)
{
- return inl(PCI_REG(reg));
+ return ctrl_inl(PCI_REG(reg));
}
#endif /* __PCI_SH4_H */
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index 1aca7fe5783..3065eb184f0 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -58,7 +58,7 @@ static int __init __area_sdram_check(unsigned int area)
{
u32 word;
- word = inl(SH7751_BCR1);
+ word = ctrl_inl(SH7751_BCR1);
/* check BCR for SDRAM in area */
if (((word >> area) & 1) == 0) {
printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%x\n",
@@ -67,7 +67,7 @@ static int __init __area_sdram_check(unsigned int area)
}
pci_write_reg(word, SH4_PCIBCR1);
- word = (u16)inw(SH7751_BCR2);
+ word = (u16)ctrl_inw(SH7751_BCR2);
/* check BCR2 for 32bit SDRAM interface*/
if (((word >> (area << 1)) & 0x3) != 0x3) {
printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%x\n",
@@ -85,9 +85,9 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
u32 word;
/* Set the BCR's to enable PCI access */
- reg = inl(SH7751_BCR1);
+ reg = ctrl_inl(SH7751_BCR1);
reg |= 0x80000;
- outl(reg, SH7751_BCR1);
+ ctrl_outl(reg, SH7751_BCR1);
/* Turn the clocks back on (not done in reset)*/
pci_write_reg(0, SH4_PCICLKR);
@@ -179,13 +179,13 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
return 0;
/* configure the wait control registers */
- word = inl(SH7751_WCR1);
+ word = ctrl_inl(SH7751_WCR1);
pci_write_reg(word, SH4_PCIWCR1);
- word = inl(SH7751_WCR2);
+ word = ctrl_inl(SH7751_WCR2);
pci_write_reg(word, SH4_PCIWCR2);
- word = inl(SH7751_WCR3);
+ word = ctrl_inl(SH7751_WCR3);
pci_write_reg(word, SH4_PCIWCR3);
- word = inl(SH7751_MCR);
+ word = ctrl_inl(SH7751_MCR);
pci_write_reg(word, SH4_PCIMCR);
/* NOTE: I'm ignoring the PCI error IRQs for now..
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
index 7d797f4de5e..b2a2bfa3c1b 100644
--- a/arch/sh/drivers/pci/pci-sh7780.c
+++ b/arch/sh/drivers/pci/pci-sh7780.c
@@ -52,7 +52,7 @@ static int __init sh7780_pci_init(void)
pr_debug("PCI: Starting intialization.\n");
- outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */
+ ctrl_outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */
/* check for SH7780/SH7780R hardware */
id = pci_read_reg(SH7780_PCIVID);
diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32
index c8928983105..62bf373266f 100644
--- a/arch/sh/kernel/Makefile_32
+++ b/arch/sh/kernel/Makefile_32
@@ -22,5 +22,6 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_BINFMT_ELF) += dump_task.o
+obj-$(CONFIG_IO_TRAPPED) += io_trapped.o
EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64
index 1ef21cc087f..e01283d49cb 100644
--- a/arch/sh/kernel/Makefile_64
+++ b/arch/sh/kernel/Makefile_64
@@ -18,5 +18,6 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_BINFMT_ELF) += dump_task.o
+obj-$(CONFIG_IO_TRAPPED) += io_trapped.o
EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile
index cc1836e47a5..462a8f6dfee 100644
--- a/arch/sh/kernel/cpu/irq/Makefile
+++ b/arch/sh/kernel/cpu/irq/Makefile
@@ -6,4 +6,3 @@ obj-y += intc.o
obj-$(CONFIG_SUPERH32) += imask.o
obj-$(CONFIG_CPU_SH5) += intc-sh5.o
obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o
-obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o
diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c
index 43ee7a9a4f0..d6e0e2bdaad 100644
--- a/arch/sh/kernel/cpu/irq/intc-sh5.c
+++ b/arch/sh/kernel/cpu/irq/intc-sh5.c
@@ -75,21 +75,6 @@ int intc_evt_to_irq[(0xE20/0x20)+1] = {
-1, -1 /* 0xE00 - 0xE20 */
};
-/*
- * Opposite mapper.
- */
-static int IRQ_to_vectorN[NR_INTC_IRQS] = {
- 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */
- -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */
- 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */
- 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */
- -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */
-
-};
-
static unsigned long intc_virt;
static unsigned int startup_intc_irq(unsigned int irq);
@@ -176,6 +161,18 @@ void make_intc_irq(unsigned int irq)
}
#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
+static int IRQ_to_vectorN[NR_INTC_IRQS] = {
+ 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */
+ -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */
+ 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */
+ 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */
+ -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */
+
+};
+
int intc_irq_describe(char* p, int irq)
{
if (irq < NR_INTC_IRQS)
diff --git a/arch/sh/kernel/cpu/irq/maskreg.c b/arch/sh/kernel/cpu/irq/maskreg.c
deleted file mode 100644
index 978992e367a..00000000000
--- a/arch/sh/kernel/cpu/irq/maskreg.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Interrupt handling for Simple external interrupt mask register
- *
- * Copyright (C) 2001 A&D Co., Ltd. <http://www.aandd.co.jp>
- *
- * This is for the machine which have single 16 bit register
- * for masking external IRQ individually.
- * Each bit of the register is for masking each interrupt.
- *
- * This file may be copied or modified under the terms of the GNU
- * General Public License. See linux/COPYING for more information.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-/* address of external interrupt mask register */
-unsigned long irq_mask_register;
-
-/* forward declaration */
-static unsigned int startup_maskreg_irq(unsigned int irq);
-static void shutdown_maskreg_irq(unsigned int irq);
-static void enable_maskreg_irq(unsigned int irq);
-static void disable_maskreg_irq(unsigned int irq);
-static void mask_and_ack_maskreg(unsigned int);
-static void end_maskreg_irq(unsigned int irq);
-
-/* hw_interrupt_type */
-static struct hw_interrupt_type maskreg_irq_type = {
- .typename = "Mask Register",
- .startup = startup_maskreg_irq,
- .shutdown = shutdown_maskreg_irq,
- .enable = enable_maskreg_irq,
- .disable = disable_maskreg_irq,
- .ack = mask_and_ack_maskreg,
- .end = end_maskreg_irq
-};
-
-/* actual implementation */
-static unsigned int startup_maskreg_irq(unsigned int irq)
-{
- enable_maskreg_irq(irq);
- return 0; /* never anything pending */
-}
-
-static void shutdown_maskreg_irq(unsigned int irq)
-{
- disable_maskreg_irq(irq);
-}
-
-static void disable_maskreg_irq(unsigned int irq)
-{
- unsigned short val, mask = 0x01 << irq;
-
- BUG_ON(!irq_mask_register);
-
- /* Set "irq"th bit */
- val = ctrl_inw(irq_mask_register);
- val |= mask;
- ctrl_outw(val, irq_mask_register);
-}
-
-static void enable_maskreg_irq(unsigned int irq)
-{
- unsigned short val, mask = ~(0x01 << irq);
-
- BUG_ON(!irq_mask_register);
-
- /* Clear "irq"th bit */
- val = ctrl_inw(irq_mask_register);
- val &= mask;
- ctrl_outw(val, irq_mask_register);
-}
-
-static void mask_and_ack_maskreg(unsigned int irq)
-{
- disable_maskreg_irq(irq);
-}
-
-static void end_maskreg_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- enable_maskreg_irq(irq);
-}
-
-void make_maskreg_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- irq_desc[irq].handler = &maskreg_irq_type;
- disable_maskreg_irq(irq);
-}
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index f2b9238cda0..9e89984c4f1 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -126,12 +126,18 @@ int __init detect_cpu_and_cache_system(void)
CPU_HAS_LLSC;
break;
case 0x3008:
- if (prr == 0xa0) {
+ if (prr == 0xa0 || prr == 0xa1) {
boot_cpu_data.type = CPU_SH7722;
boot_cpu_data.icache.ways = 4;
boot_cpu_data.dcache.ways = 4;
boot_cpu_data.flags |= CPU_HAS_LLSC;
}
+ else if (prr == 0x70) {
+ boot_cpu_data.type = CPU_SH7366;
+ boot_cpu_data.icache.ways = 4;
+ boot_cpu_data.dcache.ways = 4;
+ boot_cpu_data.flags |= CPU_HAS_LLSC;
+ }
break;
case 0x4000: /* 1st cut */
case 0x4001: /* 2nd cut */
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 3008c00eea6..8250e017bd4 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -263,7 +263,7 @@ struct sq_sysfs_attr {
ssize_t (*store)(const char *buf, size_t count);
};
-#define to_sq_sysfs_attr(attr) container_of(attr, struct sq_sysfs_attr, attr)
+#define to_sq_sysfs_attr(a) container_of(a, struct sq_sysfs_attr, attr)
static ssize_t sq_sysfs_show(struct kobject *kobj, struct attribute *attr,
char *buf)
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index 08ac6387bf1..5d890ac8e79 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o
obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o
obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7366) += setup-sh7366.o
obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o
# SMP setup
@@ -21,6 +22,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7722.o
clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o
obj-y += $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index a0fd8bb21f7..299138ebe16 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -1,7 +1,7 @@
/*
* arch/sh/kernel/cpu/sh4a/clock-sh7722.c
*
- * SH7722 support for the clock framework
+ * SH7722 & SH7366 support for the clock framework
*
* Copyright (c) 2006-2007 Nomad Global Solutions Inc
* Based on code for sh7343 by Paul Mundt
@@ -417,15 +417,19 @@ static int sh7722_siu_which(struct clk *clk)
return 0;
if (!strcmp(clk->name, "siu_b_clk"))
return 1;
+#if defined(CONFIG_CPU_SUBTYPE_SH7722)
if (!strcmp(clk->name, "irda_clk"))
return 2;
+#endif
return -EINVAL;
}
static unsigned long sh7722_siu_regs[] = {
[0] = SCLKACR,
[1] = SCLKBCR,
+#if defined(CONFIG_CPU_SUBTYPE_SH7722)
[2] = IrDACLKCR,
+#endif
};
static int sh7722_siu_start_stop(struct clk *clk, int enable)
@@ -571,10 +575,12 @@ static struct clk sh7722_siu_b_clock = {
.ops = &sh7722_siu_clk_ops,
};
+#if defined(CONFIG_CPU_SUBTYPE_SH7722)
static struct clk sh7722_irda_clock = {
.name = "irda_clk",
.ops = &sh7722_siu_clk_ops,
};
+#endif
static struct clk sh7722_video_clock = {
.name = "video_clk",
@@ -588,7 +594,9 @@ static struct clk *sh7722_clocks[] = {
&sh7722_sdram_clock,
&sh7722_siu_a_clock,
&sh7722_siu_b_clock,
+#if defined(CONFIG_CPU_SUBTYPE_SH7722)
&sh7722_irda_clock,
+#endif
&sh7722_video_clock,
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
new file mode 100644
index 00000000000..967e8b69a2f
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -0,0 +1,177 @@
+/*
+ * SH7366 Setup
+ *
+ * Copyright (C) 2008 Renesas Solutions
+ *
+ * Based on linux/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+ *
+ * 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.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+ {
+ .mapbase = 0xffe00000,
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .irqs = { 80, 80, 80, 80 },
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device sci_device = {
+ .name = "sh-sci",
+ .id = -1,
+ .dev = {
+ .platform_data = sci_platform_data,
+ },
+};
+
+static struct platform_device *sh7366_devices[] __initdata = {
+ &sci_device,
+};
+
+static int __init sh7366_devices_setup(void)
+{
+ return platform_add_devices(sh7366_devices,
+ ARRAY_SIZE(sh7366_devices));
+}
+__initcall(sh7366_devices_setup);
+
+enum {
+ UNUSED=0,
+
+ /* interrupt sources */
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+ ICB,
+ DMAC0, DMAC1, DMAC2, DMAC3,
+ VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU,
+ MFI, VPU, USB,
+ MMC_MMC1I, MMC_MMC2I, MMC_MMC3I,
+ DMAC4, DMAC5, DMAC_DADERR,
+ SCIF, SCIFA1, SCIFA2,
+ DENC, MSIOF,
+ FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
+ I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI,
+ SDHI0, SDHI1, SDHI2, SDHI3,
+ CMT, TSIF, SIU,
+ TMU0, TMU1, TMU2,
+ VEU2, LCDC,
+
+ /* interrupt groups */
+
+ DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C, SDHI,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
+ INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
+ INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
+ INTC_VECT(IRQ6, 0x6c0), INTC_VECT(IRQ7, 0x6e0),
+ INTC_VECT(ICB, 0x700),
+ INTC_VECT(DMAC0, 0x800), INTC_VECT(DMAC1, 0x820),
+ INTC_VECT(DMAC2, 0x840), INTC_VECT(DMAC3, 0x860),
+ INTC_VECT(VIO_CEUI, 0x880), INTC_VECT(VIO_BEUI, 0x8a0),
+ INTC_VECT(VIO_VEUI, 0x8c0), INTC_VECT(VOU, 0x8e0),
+ INTC_VECT(MFI, 0x900), INTC_VECT(VPU, 0x980), INTC_VECT(USB, 0xa20),
+ INTC_VECT(MMC_MMC1I, 0xb00), INTC_VECT(MMC_MMC2I, 0xb20),
+ INTC_VECT(MMC_MMC3I, 0xb40),
+ INTC_VECT(DMAC4, 0xb80), INTC_VECT(DMAC5, 0xba0),
+ INTC_VECT(DMAC_DADERR, 0xbc0),
+ INTC_VECT(SCIF, 0xc00), INTC_VECT(SCIFA1, 0xc20),
+ INTC_VECT(SCIFA2, 0xc40),
+ INTC_VECT(DENC, 0xc60), INTC_VECT(MSIOF, 0xc80),
+ INTC_VECT(FLCTL_FLSTEI, 0xd80), INTC_VECT(FLCTL_FLENDI, 0xda0),
+ INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0),
+ INTC_VECT(I2C_ALI, 0xe00), INTC_VECT(I2C_TACKI, 0xe20),
+ INTC_VECT(I2C_WAITI, 0xe40), INTC_VECT(I2C_DTEI, 0xe60),
+ INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0),
+ INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0),
+ INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20),
+ INTC_VECT(SIU, 0xf80),
+ INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+ INTC_VECT(TMU2, 0x440),
+ INTC_VECT(VEU2, 0x580), INTC_VECT(LCDC, 0x580),
+};
+
+static struct intc_group groups[] __initdata = {
+ INTC_GROUP(DMAC0123, DMAC0, DMAC1, DMAC2, DMAC3),
+ INTC_GROUP(VIOVOU, VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU),
+ INTC_GROUP(MMC, MMC_MMC1I, MMC_MMC2I, MMC_MMC3I),
+ INTC_GROUP(DMAC45, DMAC4, DMAC5, DMAC_DADERR),
+ INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLENDI,
+ FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
+ INTC_GROUP(I2C, I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI),
+ INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3),
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
+ { } },
+ { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
+ { VOU, VIO_VEUI, VIO_BEUI, VIO_CEUI, DMAC3, DMAC2, DMAC1, DMAC0 } },
+ { 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */
+ { 0, 0, 0, VPU, 0, 0, 0, MFI } },
+ { 0xa408008c, 0xa40800cc, 8, /* IMR3 / IMCR3 */
+ { 0, 0, 0, ICB } },
+ { 0xa4080090, 0xa40800d0, 8, /* IMR4 / IMCR4 */
+ { 0, TMU2, TMU1, TMU0, VEU2, 0, 0, LCDC } },
+ { 0xa4080094, 0xa40800d4, 8, /* IMR5 / IMCR5 */
+ { 0, DMAC_DADERR, DMAC5, DMAC4, DENC, SCIFA2, SCIFA1, SCIF } },
+ { 0xa4080098, 0xa40800d8, 8, /* IMR6 / IMCR6 */
+ { 0, 0, 0, 0, 0, 0, 0, MSIOF } },
+ { 0xa408009c, 0xa40800dc, 8, /* IMR7 / IMCR7 */
+ { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI,
+ FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } },
+ { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
+ { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, 0, SIU } },
+ { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
+ { 0, 0, 0, CMT, 0, USB, } },
+ { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
+ { 0, MMC_MMC3I, MMC_MMC2I, MMC_MMC1I } },
+ { 0xa40800ac, 0xa40800ec, 8, /* IMR11 / IMCR11 */
+ { 0, 0, 0, 0, 0, 0, 0, TSIF } },
+ { 0xa4140044, 0xa4140064, 8, /* INTMSK00 / INTMSKCLR00 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xa4080000, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2 } },
+ { 0xa4080004, 0, 16, 4, /* IPRB */ { VEU2, LCDC, ICB } },
+ { 0xa4080008, 0, 16, 4, /* IPRC */ { } },
+ { 0xa408000c, 0, 16, 4, /* IPRD */ { } },
+ { 0xa4080010, 0, 16, 4, /* IPRE */ { DMAC0123, VIOVOU, MFI, VPU } },
+ { 0xa4080014, 0, 16, 4, /* IPRF */ { 0, DMAC45, USB, CMT } },
+ { 0xa4080018, 0, 16, 4, /* IPRG */ { SCIF, SCIFA1, SCIFA2, DENC } },
+ { 0xa408001c, 0, 16, 4, /* IPRH */ { MSIOF, 0, FLCTL, I2C } },
+ { 0xa4080020, 0, 16, 4, /* IPRI */ { 0, 0, TSIF, } },
+ { 0xa4080024, 0, 16, 4, /* IPRJ */ { 0, 0, SIU } },
+ { 0xa4080028, 0, 16, 4, /* IPRK */ { 0, MMC, 0, SDHI } },
+ { 0xa408002c, 0, 16, 4, /* IPRL */ { } },
+ { 0xa4140010, 0, 32, 4, /* INTPRI00 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_sense_reg sense_registers[] __initdata = {
+ { 0xa414001c, 16, 2, /* ICR1 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7366", vectors, groups,
+ mask_registers, prio_registers, sense_registers);
+
+void __init plat_irq_setup(void)
+{
+ register_intc_controller(&intc_desc);
+}
+
+void __init plat_mem_setup(void)
+{
+ /* TODO: Register Node 1 */
+}
diff --git a/arch/sh/kernel/cpu/sh5/probe.c b/arch/sh/kernel/cpu/sh5/probe.c
index 15d167fd0ae..31f8cb0f637 100644
--- a/arch/sh/kernel/cpu/sh5/probe.c
+++ b/arch/sh/kernel/cpu/sh5/probe.c
@@ -20,19 +20,18 @@ int __init detect_cpu_and_cache_system(void)
{
unsigned long long cir;
- /* Do peeks in real mode to avoid having to set up a mapping for the
- WPC registers. On SH5-101 cut2, such a mapping would be exposed to
- an address translation erratum which would make it hard to set up
- correctly. */
+ /*
+ * Do peeks in real mode to avoid having to set up a mapping for
+ * the WPC registers. On SH5-101 cut2, such a mapping would be
+ * exposed to an address translation erratum which would make it
+ * hard to set up correctly.
+ */
cir = peek_real_address_q(0x0d000008);
- if ((cir & 0xffff) == 0x5103) {
+ if ((cir & 0xffff) == 0x5103)
boot_cpu_data.type = CPU_SH5_103;
- } else if (((cir >> 32) & 0xffff) == 0x51e2) {
+ else if (((cir >> 32) & 0xffff) == 0x51e2)
/* CPU.VCR aliased at CIR address on SH5-101 */
boot_cpu_data.type = CPU_SH5_101;
- } else {
- boot_cpu_data.type = CPU_SH_NONE;
- }
/*
* First, setup some sane values for the I-cache.
@@ -40,37 +39,33 @@ int __init detect_cpu_and_cache_system(void)
boot_cpu_data.icache.ways = 4;
boot_cpu_data.icache.sets = 256;
boot_cpu_data.icache.linesz = L1_CACHE_BYTES;
+ boot_cpu_data.icache.way_incr = (1 << 13);
+ boot_cpu_data.icache.entry_shift = 5;
+ boot_cpu_data.icache.way_size = boot_cpu_data.icache.sets *
+ boot_cpu_data.icache.linesz;
+ boot_cpu_data.icache.entry_mask = 0x1fe0;
+ boot_cpu_data.icache.flags = 0;
-#if 0
/*
- * FIXME: This can probably be cleaned up a bit as well.. for example,
- * do we really need the way shift _and_ the way_step_shift ?? Judging
- * by the existing code, I would guess no.. is there any valid reason
- * why we need to be tracking this around?
+ * Next, setup some sane values for the D-cache.
+ *
+ * On the SH5, these are pretty consistent with the I-cache settings,
+ * so we just copy over the existing definitions.. these can be fixed
+ * up later, especially if we add runtime CPU probing.
+ *
+ * Though in the meantime it saves us from having to duplicate all of
+ * the above definitions..
*/
- boot_cpu_data.icache.way_shift = 13;
- boot_cpu_data.icache.entry_shift = 5;
- boot_cpu_data.icache.set_shift = 4;
- boot_cpu_data.icache.way_step_shift = 16;
- boot_cpu_data.icache.asid_shift = 2;
+ boot_cpu_data.dcache = boot_cpu_data.icache;
/*
- * way offset = cache size / associativity, so just don't factor in
- * associativity in the first place..
+ * Setup any cache-related flags here
*/
- boot_cpu_data.icache.way_ofs = boot_cpu_data.icache.sets *
- boot_cpu_data.icache.linesz;
-
- boot_cpu_data.icache.asid_mask = 0x3fc;
- boot_cpu_data.icache.idx_mask = 0x1fe0;
- boot_cpu_data.icache.epn_mask = 0xffffe000;
+#if defined(CONFIG_CACHE_WRITETHROUGH)
+ set_bit(SH_CACHE_MODE_WT, &(boot_cpu_data.dcache.flags));
+#elif defined(CONFIG_CACHE_WRITEBACK)
+ set_bit(SH_CACHE_MODE_WB, &(boot_cpu_data.dcache.flags));
#endif
- boot_cpu_data.icache.flags = 0;
-
- /* A trivial starting point.. */
- memcpy(&boot_cpu_data.dcache,
- &boot_cpu_data.icache, sizeof(struct cache_info));
-
return 0;
}
diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c
index 71c9fde2fd9..2b899122990 100644
--- a/arch/sh/kernel/io.c
+++ b/arch/sh/kernel/io.c
@@ -63,7 +63,13 @@ EXPORT_SYMBOL(memset_io);
void __iomem *ioport_map(unsigned long port, unsigned int nr)
{
- return sh_mv.mv_ioport_map(port, nr);
+ void __iomem *ret;
+
+ ret = __ioport_map_trapped(port, nr);
+ if (ret)
+ return ret;
+
+ return __ioport_map(port, nr);
}
EXPORT_SYMBOL(ioport_map);
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c
index 771ea423044..db769449f5a 100644
--- a/arch/sh/kernel/io_generic.c
+++ b/arch/sh/kernel/io_generic.c
@@ -33,17 +33,17 @@ static inline void delay(void)
u8 generic_inb(unsigned long port)
{
- return ctrl_inb((unsigned long __force)ioport_map(port, 1));
+ return ctrl_inb((unsigned long __force)__ioport_map(port, 1));
}
u16 generic_inw(unsigned long port)
{
- return ctrl_inw((unsigned long __force)ioport_map(port, 2));
+ return ctrl_inw((unsigned long __force)__ioport_map(port, 2));
}
u32 generic_inl(unsigned long port)
{
- return ctrl_inl((unsigned long __force)ioport_map(port, 4));
+ return ctrl_inl((unsigned long __force)__ioport_map(port, 4));
}
u8 generic_inb_p(unsigned long port)
@@ -81,7 +81,7 @@ void generic_insb(unsigned long port, void *dst, unsigned long count)
volatile u8 *port_addr;
u8 *buf = dst;
- port_addr = (volatile u8 *)ioport_map(port, 1);
+ port_addr = (volatile u8 *)__ioport_map(port, 1);
while (count--)
*buf++ = *port_addr;
}
@@ -91,7 +91,7 @@ void generic_insw(unsigned long port, void *dst, unsigned long count)
volatile u16 *port_addr;
u16 *buf = dst;
- port_addr = (volatile u16 *)ioport_map(port, 2);
+ port_addr = (volatile u16 *)__ioport_map(port, 2);
while (count--)
*buf++ = *port_addr;
@@ -103,7 +103,7 @@ void generic_insl(unsigned long port, void *dst, unsigned long count)
volatile u32 *port_addr;
u32 *buf = dst;
- port_addr = (volatile u32 *)ioport_map(port, 4);
+ port_addr = (volatile u32 *)__ioport_map(port, 4);
while (count--)
*buf++ = *port_addr;
@@ -112,17 +112,17 @@ void generic_insl(unsigned long port, void *dst, unsigned long count)
void generic_outb(u8 b, unsigned long port)
{
- ctrl_outb(b, (unsigned long __force)ioport_map(port, 1));
+ ctrl_outb(b, (unsigned long __force)__ioport_map(port, 1));
}
void generic_outw(u16 b, unsigned long port)
{
- ctrl_outw(b, (unsigned long __force)ioport_map(port, 2));
+ ctrl_outw(b, (unsigned long __force)__ioport_map(port, 2));
}
void generic_outl(u32 b, unsigned long port)
{
- ctrl_outl(b, (unsigned long __force)ioport_map(port, 4));
+ ctrl_outl(b, (unsigned long __force)__ioport_map(port, 4));
}
void generic_outb_p(u8 b, unsigned long port)
@@ -153,7 +153,7 @@ void generic_outsb(unsigned long port, const void *src, unsigned long count)
volatile u8 *port_addr;
const u8 *buf = src;
- port_addr = (volatile u8 __force *)ioport_map(port, 1);
+ port_addr = (volatile u8 __force *)__ioport_map(port, 1);
while (count--)
*port_addr = *buf++;
@@ -164,7 +164,7 @@ void generic_outsw(unsigned long port, const void *src, unsigned long count)
volatile u16 *port_addr;
const u16 *buf = src;
- port_addr = (volatile u16 __force *)ioport_map(port, 2);
+ port_addr = (volatile u16 __force *)__ioport_map(port, 2);
while (count--)
*port_addr = *buf++;
@@ -177,7 +177,7 @@ void generic_outsl(unsigned long port, const void *src, unsigned long count)
volatile u32 *port_addr;
const u32 *buf = src;
- port_addr = (volatile u32 __force *)ioport_map(port, 4);
+ port_addr = (volatile u32 __force *)__ioport_map(port, 4);
while (count--)
*port_addr = *buf++;
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c
new file mode 100644
index 00000000000..86a665d9220
--- /dev/null
+++ b/arch/sh/kernel/io_trapped.c
@@ -0,0 +1,276 @@
+/*
+ * Trapped io support
+ *
+ * Copyright (C) 2008 Magnus Damm
+ *
+ * Intercept io operations by trapping.
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/bitops.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/io_trapped.h>
+
+#define TRAPPED_PAGES_MAX 16
+
+#ifdef CONFIG_HAS_IOPORT
+LIST_HEAD(trapped_io);
+EXPORT_SYMBOL_GPL(trapped_io);
+#endif
+#ifdef CONFIG_HAS_IOMEM
+LIST_HEAD(trapped_mem);
+EXPORT_SYMBOL_GPL(trapped_mem);
+#endif
+static DEFINE_SPINLOCK(trapped_lock);
+
+int __init register_trapped_io(struct trapped_io *tiop)
+{
+ struct resource *res;
+ unsigned long len = 0, flags = 0;
+ struct page *pages[TRAPPED_PAGES_MAX];
+ int k, n;
+
+ /* structure must be page aligned */
+ if ((unsigned long)tiop & (PAGE_SIZE - 1))
+ goto bad;
+
+ for (k = 0; k < tiop->num_resources; k++) {
+ res = tiop->resource + k;
+ len += roundup((res->end - res->start) + 1, PAGE_SIZE);
+ flags |= res->flags;
+ }
+
+ /* support IORESOURCE_IO _or_ MEM, not both */
+ if (hweight_long(flags) != 1)
+ goto bad;
+
+ n = len >> PAGE_SHIFT;
+
+ if (n >= TRAPPED_PAGES_MAX)
+ goto bad;
+
+ for (k = 0; k < n; k++)
+ pages[k] = virt_to_page(tiop);
+
+ tiop->virt_base = vmap(pages, n, VM_MAP, PAGE_NONE);
+ if (!tiop->virt_base)
+ goto bad;
+
+ len = 0;
+ for (k = 0; k < tiop->num_resources; k++) {
+ res = tiop->resource + k;
+ pr_info("trapped io 0x%08lx overrides %s 0x%08lx\n",
+ (unsigned long)(tiop->virt_base + len),
+ res->flags & IORESOURCE_IO ? "io" : "mmio",
+ (unsigned long)res->start);
+ len += roundup((res->end - res->start) + 1, PAGE_SIZE);
+ }
+
+ tiop->magic = IO_TRAPPED_MAGIC;
+ INIT_LIST_HEAD(&tiop->list);
+ spin_lock_irq(&trapped_lock);
+ if (flags & IORESOURCE_IO)
+ list_add(&tiop->list, &trapped_io);
+ if (flags & IORESOURCE_MEM)
+ list_add(&tiop->list, &trapped_mem);
+ spin_unlock_irq(&trapped_lock);
+
+ return 0;
+ bad:
+ pr_warning("unable to install trapped io filter\n");
+ return -1;
+}
+EXPORT_SYMBOL_GPL(register_trapped_io);
+
+void __iomem *match_trapped_io_handler(struct list_head *list,
+ unsigned long offset,
+ unsigned long size)
+{
+ unsigned long voffs;
+ struct trapped_io *tiop;
+ struct resource *res;
+ int k, len;
+
+ spin_lock_irq(&trapped_lock);
+ list_for_each_entry(tiop, list, list) {
+ voffs = 0;
+ for (k = 0; k < tiop->num_resources; k++) {
+ res = tiop->resource + k;
+ if (res->start == offset) {
+ spin_unlock_irq(&trapped_lock);
+ return tiop->virt_base + voffs;
+ }
+
+ len = (res->end - res->start) + 1;
+ voffs += roundup(len, PAGE_SIZE);
+ }
+ }
+ spin_unlock_irq(&trapped_lock);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(match_trapped_io_handler);
+
+static struct trapped_io *lookup_tiop(unsigned long address)
+{
+ pgd_t *pgd_k;
+ pud_t *pud_k;
+ pmd_t *pmd_k;
+ pte_t *pte_k;
+ pte_t entry;
+
+ pgd_k = swapper_pg_dir + pgd_index(address);
+ if (!pgd_present(*pgd_k))
+ return NULL;
+
+ pud_k = pud_offset(pgd_k, address);
+ if (!pud_present(*pud_k))
+ return NULL;
+
+ pmd_k = pmd_offset(pud_k, address);
+ if (!pmd_present(*pmd_k))
+ return NULL;
+
+ pte_k = pte_offset_kernel(pmd_k, address);
+ entry = *pte_k;
+
+ return pfn_to_kaddr(pte_pfn(entry));
+}
+
+static unsigned long lookup_address(struct trapped_io *tiop,
+ unsigned long address)
+{
+ struct resource *res;
+ unsigned long vaddr = (unsigned long)tiop->virt_base;
+ unsigned long len;
+ int k;
+
+ for (k = 0; k < tiop->num_resources; k++) {
+ res = tiop->resource + k;
+ len = roundup((res->end - res->start) + 1, PAGE_SIZE);
+ if (address < (vaddr + len))
+ return res->start + (address - vaddr);
+ vaddr += len;
+ }
+ return 0;
+}
+
+static unsigned long long copy_word(unsigned long src_addr, int src_len,
+ unsigned long dst_addr, int dst_len)
+{
+ unsigned long long tmp = 0;
+
+ switch (src_len) {
+ case 1:
+ tmp = ctrl_inb(src_addr);
+ break;
+ case 2:
+ tmp = ctrl_inw(src_addr);
+ break;
+ case 4:
+ tmp = ctrl_inl(src_addr);
+ break;
+ case 8:
+ tmp = ctrl_inq(src_addr);
+ break;
+ }
+
+ switch (dst_len) {
+ case 1:
+ ctrl_outb(tmp, dst_addr);
+ break;
+ case 2:
+ ctrl_outw(tmp, dst_addr);
+ break;
+ case 4:
+ ctrl_outl(tmp, dst_addr);
+ break;
+ case 8:
+ ctrl_outq(tmp, dst_addr);
+ break;
+ }
+
+ return tmp;
+}
+
+static unsigned long from_device(void *dst, const void *src, unsigned long cnt)
+{
+ struct trapped_io *tiop;
+ unsigned long src_addr = (unsigned long)src;
+ unsigned long long tmp;
+
+ pr_debug("trapped io read 0x%08lx (%ld)\n", src_addr, cnt);
+ tiop = lookup_tiop(src_addr);
+ WARN_ON(!tiop || (tiop->magic != IO_TRAPPED_MAGIC));
+
+ src_addr = lookup_address(tiop, src_addr);
+ if (!src_addr)
+ return cnt;
+
+ tmp = copy_word(src_addr,
+ max_t(unsigned long, cnt,
+ (tiop->minimum_bus_width / 8)),
+ (unsigned long)dst, cnt);
+
+ pr_debug("trapped io read 0x%08lx -> 0x%08llx\n", src_addr, tmp);
+ return 0;
+}
+
+static unsigned long to_device(void *dst, const void *src, unsigned long cnt)
+{
+ struct trapped_io *tiop;
+ unsigned long dst_addr = (unsigned long)dst;
+ unsigned long long tmp;
+
+ pr_debug("trapped io write 0x%08lx (%ld)\n", dst_addr, cnt);
+ tiop = lookup_tiop(dst_addr);
+ WARN_ON(!tiop || (tiop->magic != IO_TRAPPED_MAGIC));
+
+ dst_addr = lookup_address(tiop, dst_addr);
+ if (!dst_addr)
+ return cnt;
+
+ tmp = copy_word((unsigned long)src, cnt,
+ dst_addr, max_t(unsigned long, cnt,
+ (tiop->minimum_bus_width / 8)));
+
+ pr_debug("trapped io write 0x%08lx -> 0x%08llx\n", dst_addr, tmp);
+ return 0;
+}
+
+static struct mem_access trapped_io_access = {
+ from_device,
+ to_device,
+};
+
+int handle_trapped_io(struct pt_regs *regs, unsigned long address)
+{
+ mm_segment_t oldfs;
+ opcode_t instruction;
+ int tmp;
+
+ if (!lookup_tiop(address))
+ return 0;
+
+ WARN_ON(user_mode(regs));
+
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ if (copy_from_user(&instruction, (void *)(regs->pc),
+ sizeof(instruction))) {
+ set_fs(oldfs);
+ return 0;
+ }
+
+ tmp = handle_unaligned_access(instruction, regs, &trapped_io_access);
+ set_fs(oldfs);
+ return tmp == 0;
+}
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 0586bc62ad9..9bf19b00696 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -248,9 +248,6 @@ asmlinkage void do_softirq(void)
void __init init_IRQ(void)
{
-#ifdef CONFIG_CPU_HAS_PINT_IRQ
- init_IRQ_pint();
-#endif
plat_irq_setup();
/* Perform the machine specific initialisation */
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c
index cff3b7dc9c5..046999b1d1a 100644
--- a/arch/sh/kernel/process_64.c
+++ b/arch/sh/kernel/process_64.c
@@ -623,6 +623,7 @@ extern void interruptible_sleep_on(wait_queue_head_t *q);
#define mid_sched ((unsigned long) interruptible_sleep_on)
+#ifdef CONFIG_FRAME_POINTER
static int in_sh64_switch_to(unsigned long pc)
{
extern char __sh64_switch_to_end;
@@ -631,12 +632,10 @@ static int in_sh64_switch_to(unsigned long pc)
return (pc >= (unsigned long) sh64_switch_to) &&
(pc < (unsigned long) &__sh64_switch_to_end);
}
+#endif
unsigned long get_wchan(struct task_struct *p)
{
- unsigned long schedule_fp;
- unsigned long sh64_switch_to_fp;
- unsigned long schedule_caller_pc;
unsigned long pc;
if (!p || p == current || p->state == TASK_RUNNING)
@@ -649,6 +648,10 @@ unsigned long get_wchan(struct task_struct *p)
#ifdef CONFIG_FRAME_POINTER
if (in_sh64_switch_to(pc)) {
+ unsigned long schedule_fp;
+ unsigned long sh64_switch_to_fp;
+ unsigned long schedule_caller_pc;
+
sh64_switch_to_fp = (long) p->thread.sp;
/* r14 is saved at offset 4 in the sh64_switch_to frame */
schedule_fp = *(unsigned long *) (long)(sh64_switch_to_fp + 4);
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index ce0664a58b4..fddb547f3c2 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -220,7 +220,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
dp = ((unsigned long) child) + THREAD_SIZE -
sizeof(struct pt_dspregs);
if (*((int *) (dp - 4)) == SR_FD) {
- copy_to_user(addr, (void *) dp,
+ copy_to_user((void *)addr, (void *) dp,
sizeof(struct pt_dspregs));
ret = 0;
}
@@ -234,7 +234,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
dp = ((unsigned long) child) + THREAD_SIZE -
sizeof(struct pt_dspregs);
if (*((int *) (dp - 4)) == SR_FD) {
- copy_from_user((void *) dp, addr,
+ copy_from_user((void *) dp, (void *)addr,
sizeof(struct pt_dspregs));
ret = 0;
}
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 855cdf9d85b..ff4f54a47c0 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -140,18 +140,26 @@ static void __init reserve_crashkernel(void)
ret = parse_crashkernel(boot_command_line, free_mem,
&crash_size, &crash_base);
if (ret == 0 && crash_size) {
- if (crash_base > 0) {
- printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
- "for crashkernel (System RAM: %ldMB)\n",
- (unsigned long)(crash_size >> 20),
- (unsigned long)(crash_base >> 20),
- (unsigned long)(free_mem >> 20));
- crashk_res.start = crash_base;
- crashk_res.end = crash_base + crash_size - 1;
- reserve_bootmem(crash_base, crash_size);
- } else
+ if (crash_base <= 0) {
printk(KERN_INFO "crashkernel reservation failed - "
"you have to specify a base address\n");
+ return;
+ }
+
+ if (reserve_bootmem(crash_base, crash_size,
+ BOOTMEM_EXCLUSIVE) < 0) {
+ printk(KERN_INFO "crashkernel reservation failed - "
+ "memory is in use\n");
+ return;
+ }
+
+ printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+ "for crashkernel (System RAM: %ldMB)\n",
+ (unsigned long)(crash_size >> 20),
+ (unsigned long)(crash_base >> 20),
+ (unsigned long)(free_mem >> 20));
+ crashk_res.start = crash_base;
+ crashk_res.end = crash_base + crash_size - 1;
}
}
#else
@@ -184,13 +192,14 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
* an invalid RAM area.
*/
reserve_bootmem(__MEMORY_START+PAGE_SIZE,
- (PFN_PHYS(free_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
+ (PFN_PHYS(free_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START,
+ BOOTMEM_DEFAULT);
/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
* enabling clean reboots, SMP operation, laptop functions.
*/
- reserve_bootmem(__MEMORY_START, PAGE_SIZE);
+ reserve_bootmem(__MEMORY_START, PAGE_SIZE, BOOTMEM_DEFAULT);
sparse_memory_present_with_active_regions(0);
@@ -200,7 +209,7 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
reserve_bootmem(INITRD_START + __MEMORY_START,
- INITRD_SIZE);
+ INITRD_SIZE, BOOTMEM_DEFAULT);
initrd_start = INITRD_START + PAGE_OFFSET +
__MEMORY_START;
initrd_end = initrd_start + INITRD_SIZE;
@@ -324,7 +333,7 @@ static const char *cpu_name[] = {
[CPU_SH7343] = "SH7343", [CPU_SH7785] = "SH7785",
[CPU_SH7722] = "SH7722", [CPU_SHX3] = "SH-X3",
[CPU_SH5_101] = "SH5-101", [CPU_SH5_103] = "SH5-103",
- [CPU_SH_NONE] = "Unknown"
+ [CPU_SH7366] = "SH7366", [CPU_SH_NONE] = "Unknown"
};
const char *get_cpu_subtype(struct sh_cpuinfo *c)
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S
index 10bec45415b..a46cc3a4114 100644
--- a/arch/sh/kernel/syscalls_32.S
+++ b/arch/sh/kernel/syscalls_32.S
@@ -338,6 +338,8 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_timerfd_create
.long sys_eventfd
.long sys_fallocate
+ .long sys_timerfd_settime /* 325 */
+ .long sys_timerfd_gettime
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S
index 98a93efe369..d5d7843aad9 100644
--- a/arch/sh/kernel/syscalls_64.S
+++ b/arch/sh/kernel/syscalls_64.S
@@ -376,6 +376,8 @@ sys_call_table:
.long sys_epoll_pwait
.long sys_utimensat
.long sys_signalfd
- .long sys_timerfd /* 350 */
+ .long sys_timerfd_create /* 350 */
.long sys_eventfd
.long sys_fallocate
+ .long sys_timerfd_settime
+ .long sys_timerfd_gettime
diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c
index 2bc04bfee73..7281342c044 100644
--- a/arch/sh/kernel/time_32.c
+++ b/arch/sh/kernel/time_32.c
@@ -120,10 +120,6 @@ static long last_rtc_update;
*/
void handle_timer_tick(void)
{
- do_timer(1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
if (current->pid)
profile_tick(CPU_PROFILING);
@@ -133,6 +129,16 @@ void handle_timer_tick(void)
#endif
/*
+ * Here we are in the timer irq handler. We just have irqs locally
+ * disabled but we don't know if the timer_bh is running on the other
+ * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
+ * the irq version of write_lock because as just said we have irq
+ * locally disabled. -arca
+ */
+ write_seqlock(&xtime_lock);
+ do_timer(1);
+
+ /*
* If we have an externally synchronized Linux clock, then update
* RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
* called as close as possible to 500 ms before the new second starts.
@@ -147,6 +153,11 @@ void handle_timer_tick(void)
/* do it again in 60s */
last_rtc_update = xtime.tv_sec - 600;
}
+ write_sequnlock(&xtime_lock);
+
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(get_irq_regs()));
+#endif
}
#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
diff --git a/arch/sh/kernel/time_64.c b/arch/sh/kernel/time_64.c
index f819ba38a6c..898977ee203 100644
--- a/arch/sh/kernel/time_64.c
+++ b/arch/sh/kernel/time_64.c
@@ -229,15 +229,22 @@ static long last_rtc_update;
static inline void do_timer_interrupt(void)
{
unsigned long long current_ctc;
+
+ if (current->pid)
+ profile_tick(CPU_PROFILING);
+
+ /*
+ * Here we are in the timer irq handler. We just have irqs locally
+ * disabled but we don't know if the timer_bh is running on the other
+ * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
+ * the irq version of write_lock because as just said we have irq
+ * locally disabled. -arca
+ */
+ write_lock(&xtime_lock);
asm ("getcon cr62, %0" : "=r" (current_ctc));
ctc_last_interrupt = (unsigned long) current_ctc;
do_timer(1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
- if (current->pid)
- profile_tick(CPU_PROFILING);
#ifdef CONFIG_HEARTBEAT
if (sh_mv.mv_heartbeat != NULL)
@@ -259,6 +266,11 @@ static inline void do_timer_interrupt(void)
/* do it again in 60 s */
last_rtc_update = xtime.tv_sec - 600;
}
+ write_unlock(&xtime_lock);
+
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(get_irq_regs()));
+#endif
}
/*
@@ -275,16 +287,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
timer_status &= ~0x100;
ctrl_outw(timer_status, TMU0_TCR);
- /*
- * Here we are in the timer irq handler. We just have irqs locally
- * disabled but we don't know if the timer_bh is running on the other
- * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
- * the irq version of write_lock because as just said we have irq
- * locally disabled. -arca
- */
- write_lock(&xtime_lock);
do_timer_interrupt();
- write_unlock(&xtime_lock);
return IRQ_HANDLED;
}
diff --git a/arch/sh/kernel/timers/timer-cmt.c b/arch/sh/kernel/timers/timer-cmt.c
index 499e07beebe..71312324b5d 100644
--- a/arch/sh/kernel/timers/timer-cmt.c
+++ b/arch/sh/kernel/timers/timer-cmt.c
@@ -100,16 +100,7 @@ static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id)
timer_status &= ~0x80;
ctrl_outw(timer_status, CMT_CMCSR_0);
- /*
- * Here we are in the timer irq handler. We just have irqs locally
- * disabled but we don't know if the timer_bh is running on the other
- * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
- * the irq version of write_lock because as just said we have irq
- * locally disabled. -arca
- */
- write_seqlock(&xtime_lock);
handle_timer_tick();
- write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c
index b7499a2a918..ade9d6eb29f 100644
--- a/arch/sh/kernel/timers/timer-mtu2.c
+++ b/arch/sh/kernel/timers/timer-mtu2.c
@@ -100,9 +100,7 @@ static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id)
ctrl_outb(timer_status, MTU2_TSR_1);
/* Do timer tick */
- write_seqlock(&xtime_lock);
handle_timer_tick();
- write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
@@ -156,7 +154,6 @@ static int mtu2_timer_stop(void)
static int mtu2_timer_init(void)
{
- u8 tmp;
unsigned long interval;
setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq);
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 2e58f7a6b74..baa4fa368dc 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -147,6 +147,36 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
return -EFAULT;
}
+static inline void sign_extend(unsigned int count, unsigned char *dst)
+{
+#ifdef __LITTLE_ENDIAN__
+ if ((count == 1) && dst[0] & 0x80) {
+ dst[1] = 0xff;
+ dst[2] = 0xff;
+ dst[3] = 0xff;
+ }
+ if ((count == 2) && dst[1] & 0x80) {
+ dst[2] = 0xff;
+ dst[3] = 0xff;
+ }
+#else
+ if ((count == 1) && dst[3] & 0x80) {
+ dst[2] = 0xff;
+ dst[1] = 0xff;
+ dst[0] = 0xff;
+ }
+ if ((count == 2) && dst[2] & 0x80) {
+ dst[1] = 0xff;
+ dst[0] = 0xff;
+ }
+#endif
+}
+
+static struct mem_access user_mem_access = {
+ copy_from_user,
+ copy_to_user,
+};
+
/*
* handle an instruction that does an unaligned memory access by emulating the
* desired behaviour
@@ -154,7 +184,8 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
* (if that instruction is in a branch delay slot)
* - return 0 if emulation okay, -EFAULT on existential error
*/
-static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
+static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
+ struct mem_access *ma)
{
int ret, index, count;
unsigned long *rm, *rn;
@@ -178,25 +209,13 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
dst = (unsigned char*) rn;
*(unsigned long*)dst = 0;
-#ifdef __LITTLE_ENDIAN__
- if (copy_from_user(dst, src, count))
- goto fetch_fault;
-
- if ((count == 2) && dst[1] & 0x80) {
- dst[2] = 0xff;
- dst[3] = 0xff;
- }
-#else
+#if !defined(__LITTLE_ENDIAN__)
dst += 4-count;
-
- if (__copy_user(dst, src, count))
+#endif
+ if (ma->from(dst, src, count))
goto fetch_fault;
- if ((count == 2) && dst[2] & 0x80) {
- dst[0] = 0xff;
- dst[1] = 0xff;
- }
-#endif
+ sign_extend(count, dst);
} else {
/* to memory */
src = (unsigned char*) rm;
@@ -206,7 +225,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
dst = (unsigned char*) *rn;
dst += regs->regs[0];
- if (copy_to_user(dst, src, count))
+ if (ma->to(dst, src, count))
goto fetch_fault;
}
ret = 0;
@@ -217,7 +236,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
dst = (unsigned char*) *rn;
dst += (instruction&0x000F)<<2;
- if (copy_to_user(dst,src,4))
+ if (ma->to(dst, src, 4))
goto fetch_fault;
ret = 0;
break;
@@ -230,7 +249,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
#if !defined(__LITTLE_ENDIAN__)
src += 4-count;
#endif
- if (copy_to_user(dst, src, count))
+ if (ma->to(dst, src, count))
goto fetch_fault;
ret = 0;
break;
@@ -241,7 +260,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
dst = (unsigned char*) rn;
*(unsigned long*)dst = 0;
- if (copy_from_user(dst,src,4))
+ if (ma->from(dst, src, 4))
goto fetch_fault;
ret = 0;
break;
@@ -253,25 +272,12 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
dst = (unsigned char*) rn;
*(unsigned long*)dst = 0;
-#ifdef __LITTLE_ENDIAN__
- if (copy_from_user(dst, src, count))
- goto fetch_fault;
-
- if ((count == 2) && dst[1] & 0x80) {
- dst[2] = 0xff;
- dst[3] = 0xff;
- }
-#else
+#if !defined(__LITTLE_ENDIAN__)
dst += 4-count;
-
- if (copy_from_user(dst, src, count))
- goto fetch_fault;
-
- if ((count == 2) && dst[2] & 0x80) {
- dst[0] = 0xff;
- dst[1] = 0xff;
- }
#endif
+ if (ma->from(dst, src, count))
+ goto fetch_fault;
+ sign_extend(count, dst);
ret = 0;
break;
@@ -285,7 +291,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
dst = (unsigned char*) *rm; /* called Rn in the spec */
dst += (instruction&0x000F)<<1;
- if (copy_to_user(dst, src, 2))
+ if (ma->to(dst, src, 2))
goto fetch_fault;
ret = 0;
break;
@@ -299,21 +305,9 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
#if !defined(__LITTLE_ENDIAN__)
dst += 2;
#endif
-
- if (copy_from_user(dst, src, 2))
+ if (ma->from(dst, src, 2))
goto fetch_fault;
-
-#ifdef __LITTLE_ENDIAN__
- if (dst[1] & 0x80) {
- dst[2] = 0xff;
- dst[3] = 0xff;
- }
-#else
- if (dst[2] & 0x80) {
- dst[0] = 0xff;
- dst[1] = 0xff;
- }
-#endif
+ sign_extend(2, dst);
ret = 0;
break;
}
@@ -332,11 +326,14 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
* emulate the instruction in the delay slot
* - fetches the instruction from PC+2
*/
-static inline int handle_unaligned_delayslot(struct pt_regs *regs)
+static inline int handle_delayslot(struct pt_regs *regs,
+ opcode_t old_instruction,
+ struct mem_access *ma)
{
- u16 instruction;
+ opcode_t instruction;
+ void *addr = (void *)(regs->pc + instruction_size(old_instruction));
- if (copy_from_user(&instruction, (u16 *)(regs->pc+2), 2)) {
+ if (copy_from_user(&instruction, addr, sizeof(instruction))) {
/* the instruction-fetch faulted */
if (user_mode(regs))
return -EFAULT;
@@ -346,7 +343,7 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
regs, 0);
}
- return handle_unaligned_ins(instruction,regs);
+ return handle_unaligned_ins(instruction, regs, ma);
}
/*
@@ -369,10 +366,11 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
* XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit
* opcodes..
*/
-#ifndef CONFIG_CPU_SH2A
+
static int handle_unaligned_notify_count = 10;
-static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
+int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs,
+ struct mem_access *ma)
{
u_int rm;
int ret, index;
@@ -387,7 +385,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
printk(KERN_NOTICE "Fixing up unaligned userspace access "
"in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
current->comm, task_pid_nr(current),
- (u16 *)regs->pc, instruction);
+ (void *)regs->pc, instruction);
}
ret = -EFAULT;
@@ -395,19 +393,19 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
case 0x0000:
if (instruction==0x000B) {
/* rts */
- ret = handle_unaligned_delayslot(regs);
+ ret = handle_delayslot(regs, instruction, ma);
if (ret==0)
regs->pc = regs->pr;
}
else if ((instruction&0x00FF)==0x0023) {
/* braf @Rm */
- ret = handle_unaligned_delayslot(regs);
+ ret = handle_delayslot(regs, instruction, ma);
if (ret==0)
regs->pc += rm + 4;
}
else if ((instruction&0x00FF)==0x0003) {
/* bsrf @Rm */
- ret = handle_unaligned_delayslot(regs);
+ ret = handle_delayslot(regs, instruction, ma);
if (ret==0) {
regs->pr = regs->pc + 4;
regs->pc += rm + 4;
@@ -428,13 +426,13 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
case 0x4000:
if ((instruction&0x00FF)==0x002B) {
/* jmp @Rm */
- ret = handle_unaligned_delayslot(regs);
+ ret = handle_delayslot(regs, instruction, ma);
if (ret==0)
regs->pc = rm;
}
else if ((instruction&0x00FF)==0x000B) {
/* jsr @Rm */
- ret = handle_unaligned_delayslot(regs);
+ ret = handle_delayslot(regs, instruction, ma);
if (ret==0) {
regs->pr = regs->pc + 4;
regs->pc = rm;
@@ -461,7 +459,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
case 0x0B00: /* bf lab - no delayslot*/
break;
case 0x0F00: /* bf/s lab */
- ret = handle_unaligned_delayslot(regs);
+ ret = handle_delayslot(regs, instruction, ma);
if (ret==0) {
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
if ((regs->sr & 0x00000001) != 0)
@@ -474,7 +472,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
case 0x0900: /* bt lab - no delayslot */
break;
case 0x0D00: /* bt/s lab */
- ret = handle_unaligned_delayslot(regs);
+ ret = handle_delayslot(regs, instruction, ma);
if (ret==0) {
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
if ((regs->sr & 0x00000001) == 0)
@@ -488,13 +486,13 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
break;
case 0xA000: /* bra label */
- ret = handle_unaligned_delayslot(regs);
+ ret = handle_delayslot(regs, instruction, ma);
if (ret==0)
regs->pc += SH_PC_12BIT_OFFSET(instruction);
break;
case 0xB000: /* bsr label */
- ret = handle_unaligned_delayslot(regs);
+ ret = handle_delayslot(regs, instruction, ma);
if (ret==0) {
regs->pr = regs->pc + 4;
regs->pc += SH_PC_12BIT_OFFSET(instruction);
@@ -505,12 +503,11 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
/* handle non-delay-slot instruction */
simple:
- ret = handle_unaligned_ins(instruction,regs);
+ ret = handle_unaligned_ins(instruction, regs, ma);
if (ret==0)
regs->pc += instruction_size(instruction);
return ret;
}
-#endif /* CONFIG_CPU_SH2A */
#ifdef CONFIG_CPU_HAS_SR_RB
#define lookup_exception_vector(x) \
@@ -538,10 +535,8 @@ asmlinkage void do_address_error(struct pt_regs *regs,
unsigned long error_code = 0;
mm_segment_t oldfs;
siginfo_t info;
-#ifndef CONFIG_CPU_SH2A
- u16 instruction;
+ opcode_t instruction;
int tmp;
-#endif
/* Intentional ifdef */
#ifdef CONFIG_CPU_HAS_SR_RB
@@ -561,9 +556,9 @@ asmlinkage void do_address_error(struct pt_regs *regs,
goto uspace_segv;
}
-#ifndef CONFIG_CPU_SH2A
set_fs(USER_DS);
- if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
+ if (copy_from_user(&instruction, (void *)(regs->pc),
+ sizeof(instruction))) {
/* Argh. Fault on the instruction itself.
This should never happen non-SMP
*/
@@ -571,13 +566,12 @@ asmlinkage void do_address_error(struct pt_regs *regs,
goto uspace_segv;
}
- tmp = handle_unaligned_access(instruction, regs);
+ tmp = handle_unaligned_access(instruction, regs,
+ &user_mem_access);
set_fs(oldfs);
if (tmp==0)
return; /* sorted */
-#endif
-
uspace_segv:
printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned "
"access (PC %lx PR %lx)\n", current->comm, regs->pc,
@@ -592,9 +586,9 @@ uspace_segv:
if (regs->pc & 1)
die("unaligned program counter", regs, error_code);
-#ifndef CONFIG_CPU_SH2A
set_fs(KERNEL_DS);
- if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
+ if (copy_from_user(&instruction, (void *)(regs->pc),
+ sizeof(instruction))) {
/* Argh. Fault on the instruction itself.
This should never happen non-SMP
*/
@@ -602,14 +596,8 @@ uspace_segv:
die("insn faulting in do_address_error", regs, 0);
}
- handle_unaligned_access(instruction, regs);
+ handle_unaligned_access(instruction, regs, &user_mem_access);
set_fs(oldfs);
-#else
- printk(KERN_NOTICE "Killing process \"%s\" due to unaligned "
- "access\n", current->comm);
-
- force_sig(SIGSEGV, current);
-#endif
}
}
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index c0b3c6f6edb..a55ac81d795 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -630,7 +630,7 @@ static int misaligned_fpu_load(struct pt_regs *regs,
current->thread.fpu.hard.fp_regs[destreg] = buflo;
current->thread.fpu.hard.fp_regs[destreg+1] = bufhi;
} else {
-#if defined(CONFIG_LITTLE_ENDIAN)
+#if defined(CONFIG_CPU_LITTLE_ENDIAN)
current->thread.fpu.hard.fp_regs[destreg] = bufhi;
current->thread.fpu.hard.fp_regs[destreg+1] = buflo;
#else
@@ -700,7 +700,7 @@ static int misaligned_fpu_store(struct pt_regs *regs,
buflo = current->thread.fpu.hard.fp_regs[srcreg];
bufhi = current->thread.fpu.hard.fp_regs[srcreg+1];
} else {
-#if defined(CONFIG_LITTLE_ENDIAN)
+#if defined(CONFIG_CPU_LITTLE_ENDIAN)
bufhi = current->thread.fpu.hard.fp_regs[srcreg];
buflo = current->thread.fpu.hard.fp_regs[srcreg+1];
#else
diff --git a/arch/sh/kernel/vmlinux_64.lds.S b/arch/sh/kernel/vmlinux_64.lds.S
index 3f1bd6392bb..d1e177009a4 100644
--- a/arch/sh/kernel/vmlinux_64.lds.S
+++ b/arch/sh/kernel/vmlinux_64.lds.S
@@ -51,7 +51,7 @@ SECTIONS
KPROBES_TEXT
*(.fixup)
*(.gnu.warning)
-#ifdef CONFIG_LITTLE_ENDIAN
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
} = 0x6ff0fff0
#else
} = 0xf0fff06f
diff --git a/arch/sh/mm/cache-sh5.c b/arch/sh/mm/cache-sh5.c
index 4617e3aeee7..3877321fced 100644
--- a/arch/sh/mm/cache-sh5.c
+++ b/arch/sh/mm/cache-sh5.c
@@ -1,10 +1,10 @@
/*
* arch/sh/mm/cache-sh5.c
*
- * Original version Copyright (C) 2000, 2001 Paolo Alberelli
- * Second version Copyright (C) benedict.gaster@superh.com 2002
- * Third version Copyright Richard.Curnow@superh.com 2003
- * Hacks to third version Copyright (C) 2003 Paul Mundt
+ * Copyright (C) 2000, 2001 Paolo Alberelli
+ * Copyright (C) 2002 Benedict Gaster
+ * Copyright (C) 2003 Richard Curnow
+ * Copyright (C) 2003 - 2008 Paul Mundt
*
* 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
@@ -13,101 +13,20 @@
#include <linux/init.h>
#include <linux/mman.h>
#include <linux/mm.h>
-#include <linux/threads.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
+#include <asm/tlb.h>
#include <asm/processor.h>
#include <asm/cache.h>
-#include <asm/tlb.h>
-#include <asm/io.h>
+#include <asm/pgalloc.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
-#include <asm/pgalloc.h> /* for flush_itlb_range */
-
-#include <linux/proc_fs.h>
-
-/* This function is in entry.S */
-extern unsigned long switch_and_save_asid(unsigned long new_asid);
/* Wired TLB entry for the D-cache */
static unsigned long long dtlb_cache_slot;
-/**
- * sh64_cache_init()
- *
- * This is pretty much just a straightforward clone of the SH
- * detect_cpu_and_cache_system().
- *
- * This function is responsible for setting up all of the cache
- * info dynamically as well as taking care of CPU probing and
- * setting up the relevant subtype data.
- *
- * FIXME: For the time being, we only really support the SH5-101
- * out of the box, and don't support dynamic probing for things
- * like the SH5-103 or even cut2 of the SH5-101. Implement this
- * later!
- */
-int __init sh64_cache_init(void)
+void __init p3_cache_init(void)
{
- /*
- * First, setup some sane values for the I-cache.
- */
- cpu_data->icache.ways = 4;
- cpu_data->icache.sets = 256;
- cpu_data->icache.linesz = L1_CACHE_BYTES;
-
- /*
- * FIXME: This can probably be cleaned up a bit as well.. for example,
- * do we really need the way shift _and_ the way_step_shift ?? Judging
- * by the existing code, I would guess no.. is there any valid reason
- * why we need to be tracking this around?
- */
- cpu_data->icache.way_shift = 13;
- cpu_data->icache.entry_shift = 5;
- cpu_data->icache.set_shift = 4;
- cpu_data->icache.way_step_shift = 16;
- cpu_data->icache.asid_shift = 2;
-
- /*
- * way offset = cache size / associativity, so just don't factor in
- * associativity in the first place..
- */
- cpu_data->icache.way_ofs = cpu_data->icache.sets *
- cpu_data->icache.linesz;
-
- cpu_data->icache.asid_mask = 0x3fc;
- cpu_data->icache.idx_mask = 0x1fe0;
- cpu_data->icache.epn_mask = 0xffffe000;
- cpu_data->icache.flags = 0;
-
- /*
- * Next, setup some sane values for the D-cache.
- *
- * On the SH5, these are pretty consistent with the I-cache settings,
- * so we just copy over the existing definitions.. these can be fixed
- * up later, especially if we add runtime CPU probing.
- *
- * Though in the meantime it saves us from having to duplicate all of
- * the above definitions..
- */
- cpu_data->dcache = cpu_data->icache;
-
- /*
- * Setup any cache-related flags here
- */
-#if defined(CONFIG_DCACHE_WRITE_THROUGH)
- set_bit(SH_CACHE_MODE_WT, &(cpu_data->dcache.flags));
-#elif defined(CONFIG_DCACHE_WRITE_BACK)
- set_bit(SH_CACHE_MODE_WB, &(cpu_data->dcache.flags));
-#endif
-
- /*
- * We also need to reserve a slot for the D-cache in the DTLB, so we
- * do this now ..
- */
- dtlb_cache_slot = sh64_get_wired_dtlb_entry();
-
- return 0;
+ /* Reserve a slot for dcache colouring in the DTLB */
+ dtlb_cache_slot = sh64_get_wired_dtlb_entry();
}
#ifdef CONFIG_DCACHE_DISABLED
@@ -116,73 +35,48 @@ int __init sh64_cache_init(void)
#define sh64_dcache_purge_user_range(mm, start, end) do { } while (0)
#define sh64_dcache_purge_phy_page(paddr) do { } while (0)
#define sh64_dcache_purge_virt_page(mm, eaddr) do { } while (0)
-#define sh64_dcache_purge_kernel_range(start, end) do { } while (0)
-#define sh64_dcache_wback_current_user_range(start, end) do { } while (0)
#endif
-/*##########################################################################*/
-
-/* From here onwards, a rewrite of the implementation,
- by Richard.Curnow@superh.com.
-
- The major changes in this compared to the old version are;
- 1. use more selective purging through OCBP instead of using ALLOCO to purge
- by natural replacement. This avoids purging out unrelated cache lines
- that happen to be in the same set.
- 2. exploit the APIs copy_user_page and clear_user_page better
- 3. be more selective about I-cache purging, in particular use invalidate_all
- more sparingly.
-
- */
-
-/*##########################################################################
- SUPPORT FUNCTIONS
- ##########################################################################*/
-
-/****************************************************************************/
-/* The following group of functions deal with mapping and unmapping a temporary
- page into the DTLB slot that have been set aside for our exclusive use. */
-/* In order to accomplish this, we use the generic interface for adding and
- removing a wired slot entry as defined in arch/sh/mm/tlb-sh5.c */
-/****************************************************************************/
-
-static unsigned long slot_own_flags;
-
-static inline void sh64_setup_dtlb_cache_slot(unsigned long eaddr, unsigned long asid, unsigned long paddr)
+/*
+ * The following group of functions deal with mapping and unmapping a
+ * temporary page into a DTLB slot that has been set aside for exclusive
+ * use.
+ */
+static inline void
+sh64_setup_dtlb_cache_slot(unsigned long eaddr, unsigned long asid,
+ unsigned long paddr)
{
- local_irq_save(slot_own_flags);
+ local_irq_disable();
sh64_setup_tlb_slot(dtlb_cache_slot, eaddr, asid, paddr);
}
static inline void sh64_teardown_dtlb_cache_slot(void)
{
sh64_teardown_tlb_slot(dtlb_cache_slot);
- local_irq_restore(slot_own_flags);
+ local_irq_enable();
}
-/****************************************************************************/
-
#ifndef CONFIG_ICACHE_DISABLED
-
-static void __inline__ sh64_icache_inv_all(void)
+static inline void sh64_icache_inv_all(void)
{
unsigned long long addr, flag, data;
unsigned int flags;
- addr=ICCR0;
- flag=ICCR0_ICI;
- data=0;
+ addr = ICCR0;
+ flag = ICCR0_ICI;
+ data = 0;
/* Make this a critical section for safety (probably not strictly necessary.) */
local_irq_save(flags);
/* Without %1 it gets unexplicably wrong */
- asm volatile("getcfg %3, 0, %0\n\t"
- "or %0, %2, %0\n\t"
- "putcfg %3, 0, %0\n\t"
- "synci"
- : "=&r" (data)
- : "0" (data), "r" (flag), "r" (addr));
+ __asm__ __volatile__ (
+ "getcfg %3, 0, %0\n\t"
+ "or %0, %2, %0\n\t"
+ "putcfg %3, 0, %0\n\t"
+ "synci"
+ : "=&r" (data)
+ : "0" (data), "r" (flag), "r" (addr));
local_irq_restore(flags);
}
@@ -193,20 +87,12 @@ static void sh64_icache_inv_kernel_range(unsigned long start, unsigned long end)
* the addresses lie in the kernel superpage. */
unsigned long long ullend, addr, aligned_start;
-#if (NEFF == 32)
aligned_start = (unsigned long long)(signed long long)(signed long) start;
-#else
-#error "NEFF != 32"
-#endif
- aligned_start &= L1_CACHE_ALIGN_MASK;
- addr = aligned_start;
-#if (NEFF == 32)
+ addr = L1_CACHE_ALIGN(aligned_start);
ullend = (unsigned long long) (signed long long) (signed long) end;
-#else
-#error "NEFF != 32"
-#endif
+
while (addr <= ullend) {
- asm __volatile__ ("icbi %0, 0" : : "r" (addr));
+ __asm__ __volatile__ ("icbi %0, 0" : : "r" (addr));
addr += L1_CACHE_BYTES;
}
}
@@ -215,7 +101,7 @@ static void sh64_icache_inv_user_page(struct vm_area_struct *vma, unsigned long
{
/* If we get called, we know that vma->vm_flags contains VM_EXEC.
Also, eaddr is page-aligned. */
-
+ unsigned int cpu = smp_processor_id();
unsigned long long addr, end_addr;
unsigned long flags = 0;
unsigned long running_asid, vma_asid;
@@ -237,17 +123,17 @@ static void sh64_icache_inv_user_page(struct vm_area_struct *vma, unsigned long
*/
running_asid = get_asid();
- vma_asid = (vma->vm_mm->context & MMU_CONTEXT_ASID_MASK);
+ vma_asid = cpu_asid(cpu, vma->vm_mm);
if (running_asid != vma_asid) {
local_irq_save(flags);
switch_and_save_asid(vma_asid);
}
while (addr < end_addr) {
/* Worth unrolling a little */
- asm __volatile__("icbi %0, 0" : : "r" (addr));
- asm __volatile__("icbi %0, 32" : : "r" (addr));
- asm __volatile__("icbi %0, 64" : : "r" (addr));
- asm __volatile__("icbi %0, 96" : : "r" (addr));
+ __asm__ __volatile__("icbi %0, 0" : : "r" (addr));
+ __asm__ __volatile__("icbi %0, 32" : : "r" (addr));
+ __asm__ __volatile__("icbi %0, 64" : : "r" (addr));
+ __asm__ __volatile__("icbi %0, 96" : : "r" (addr));
addr += 128;
}
if (running_asid != vma_asid) {
@@ -256,8 +142,6 @@ static void sh64_icache_inv_user_page(struct vm_area_struct *vma, unsigned long
}
}
-/****************************************************************************/
-
static void sh64_icache_inv_user_page_range(struct mm_struct *mm,
unsigned long start, unsigned long end)
{
@@ -275,10 +159,10 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm,
possible with the D-cache. Just assume 64 for now as a working
figure.
*/
-
int n_pages;
- if (!mm) return;
+ if (!mm)
+ return;
n_pages = ((end - start) >> PAGE_SHIFT);
if (n_pages >= 64) {
@@ -290,7 +174,7 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm,
unsigned long mm_asid, current_asid;
unsigned long long flags = 0ULL;
- mm_asid = mm->context & MMU_CONTEXT_ASID_MASK;
+ mm_asid = cpu_asid(smp_processor_id(), mm);
current_asid = get_asid();
if (mm_asid != current_asid) {
@@ -322,6 +206,7 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm,
}
aligned_start = vma->vm_end; /* Skip to start of next region */
}
+
if (mm_asid != current_asid) {
switch_and_save_asid(current_asid);
local_irq_restore(flags);
@@ -329,47 +214,46 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm,
}
}
+/*
+ * Invalidate a small range of user context I-cache, not necessarily page
+ * (or even cache-line) aligned.
+ *
+ * Since this is used inside ptrace, the ASID in the mm context typically
+ * won't match current_asid. We'll have to switch ASID to do this. For
+ * safety, and given that the range will be small, do all this under cli.
+ *
+ * Note, there is a hazard that the ASID in mm->context is no longer
+ * actually associated with mm, i.e. if the mm->context has started a new
+ * cycle since mm was last active. However, this is just a performance
+ * issue: all that happens is that we invalidate lines belonging to
+ * another mm, so the owning process has to refill them when that mm goes
+ * live again. mm itself can't have any cache entries because there will
+ * have been a flush_cache_all when the new mm->context cycle started.
+ */
static void sh64_icache_inv_user_small_range(struct mm_struct *mm,
unsigned long start, int len)
{
-
- /* Invalidate a small range of user context I-cache, not necessarily
- page (or even cache-line) aligned. */
-
unsigned long long eaddr = start;
unsigned long long eaddr_end = start + len;
unsigned long current_asid, mm_asid;
unsigned long long flags;
unsigned long long epage_start;
- /* Since this is used inside ptrace, the ASID in the mm context
- typically won't match current_asid. We'll have to switch ASID to do
- this. For safety, and given that the range will be small, do all
- this under cli.
-
- Note, there is a hazard that the ASID in mm->context is no longer
- actually associated with mm, i.e. if the mm->context has started a
- new cycle since mm was last active. However, this is just a
- performance issue: all that happens is that we invalidate lines
- belonging to another mm, so the owning process has to refill them
- when that mm goes live again. mm itself can't have any cache
- entries because there will have been a flush_cache_all when the new
- mm->context cycle started. */
-
- /* Align to start of cache line. Otherwise, suppose len==8 and start
- was at 32N+28 : the last 4 bytes wouldn't get invalidated. */
- eaddr = start & L1_CACHE_ALIGN_MASK;
+ /*
+ * Align to start of cache line. Otherwise, suppose len==8 and
+ * start was at 32N+28 : the last 4 bytes wouldn't get invalidated.
+ */
+ eaddr = L1_CACHE_ALIGN(start);
eaddr_end = start + len;
+ mm_asid = cpu_asid(smp_processor_id(), mm);
local_irq_save(flags);
- mm_asid = mm->context & MMU_CONTEXT_ASID_MASK;
current_asid = switch_and_save_asid(mm_asid);
epage_start = eaddr & PAGE_MASK;
- while (eaddr < eaddr_end)
- {
- asm __volatile__("icbi %0, 0" : : "r" (eaddr));
+ while (eaddr < eaddr_end) {
+ __asm__ __volatile__("icbi %0, 0" : : "r" (eaddr));
eaddr += L1_CACHE_BYTES;
}
switch_and_save_asid(current_asid);
@@ -394,30 +278,24 @@ static void sh64_icache_inv_current_user_range(unsigned long start, unsigned lon
been recycled since we were last active in which case we might just
invalidate another processes I-cache entries : no worries, just a
performance drop for him. */
- aligned_start = start & L1_CACHE_ALIGN_MASK;
+ aligned_start = L1_CACHE_ALIGN(start);
addr = aligned_start;
while (addr < ull_end) {
- asm __volatile__ ("icbi %0, 0" : : "r" (addr));
- asm __volatile__ ("nop");
- asm __volatile__ ("nop");
+ __asm__ __volatile__ ("icbi %0, 0" : : "r" (addr));
+ __asm__ __volatile__ ("nop");
+ __asm__ __volatile__ ("nop");
addr += L1_CACHE_BYTES;
}
}
-
#endif /* !CONFIG_ICACHE_DISABLED */
-/****************************************************************************/
-
#ifndef CONFIG_DCACHE_DISABLED
-
/* Buffer used as the target of alloco instructions to purge data from cache
sets by natural eviction. -- RPC */
-#define DUMMY_ALLOCO_AREA_SIZE L1_CACHE_SIZE_BYTES + (1024 * 4)
+#define DUMMY_ALLOCO_AREA_SIZE ((L1_CACHE_BYTES << 10) + (1024 * 4))
static unsigned char dummy_alloco_area[DUMMY_ALLOCO_AREA_SIZE] __cacheline_aligned = { 0, };
-/****************************************************************************/
-
-static void __inline__ sh64_dcache_purge_sets(int sets_to_purge_base, int n_sets)
+static void inline sh64_dcache_purge_sets(int sets_to_purge_base, int n_sets)
{
/* Purge all ways in a particular block of sets, specified by the base
set number and number of sets. Can handle wrap-around, if that's
@@ -428,102 +306,86 @@ static void __inline__ sh64_dcache_purge_sets(int sets_to_purge_base, int n_sets
int j;
int set_offset;
- dummy_buffer_base_set = ((int)&dummy_alloco_area & cpu_data->dcache.idx_mask) >> cpu_data->dcache.entry_shift;
+ dummy_buffer_base_set = ((int)&dummy_alloco_area &
+ cpu_data->dcache.entry_mask) >>
+ cpu_data->dcache.entry_shift;
set_offset = sets_to_purge_base - dummy_buffer_base_set;
- for (j=0; j<n_sets; j++, set_offset++) {
+ for (j = 0; j < n_sets; j++, set_offset++) {
set_offset &= (cpu_data->dcache.sets - 1);
- eaddr0 = (unsigned long long)dummy_alloco_area + (set_offset << cpu_data->dcache.entry_shift);
-
- /* Do one alloco which hits the required set per cache way. For
- write-back mode, this will purge the #ways resident lines. There's
- little point unrolling this loop because the allocos stall more if
- they're too close together. */
- eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways;
- for (eaddr=eaddr0; eaddr<eaddr1; eaddr+=cpu_data->dcache.way_ofs) {
- asm __volatile__ ("alloco %0, 0" : : "r" (eaddr));
- asm __volatile__ ("synco"); /* TAKum03020 */
+ eaddr0 = (unsigned long long)dummy_alloco_area +
+ (set_offset << cpu_data->dcache.entry_shift);
+
+ /*
+ * Do one alloco which hits the required set per cache
+ * way. For write-back mode, this will purge the #ways
+ * resident lines. There's little point unrolling this
+ * loop because the allocos stall more if they're too
+ * close together.
+ */
+ eaddr1 = eaddr0 + cpu_data->dcache.way_size *
+ cpu_data->dcache.ways;
+
+ for (eaddr = eaddr0; eaddr < eaddr1;
+ eaddr += cpu_data->dcache.way_size) {
+ __asm__ __volatile__ ("alloco %0, 0" : : "r" (eaddr));
+ __asm__ __volatile__ ("synco"); /* TAKum03020 */
}
- eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways;
- for (eaddr=eaddr0; eaddr<eaddr1; eaddr+=cpu_data->dcache.way_ofs) {
- /* Load from each address. Required because alloco is a NOP if
- the cache is write-through. Write-through is a config option. */
+ eaddr1 = eaddr0 + cpu_data->dcache.way_size *
+ cpu_data->dcache.ways;
+
+ for (eaddr = eaddr0; eaddr < eaddr1;
+ eaddr += cpu_data->dcache.way_size) {
+ /*
+ * Load from each address. Required because
+ * alloco is a NOP if the cache is write-through.
+ */
if (test_bit(SH_CACHE_MODE_WT, &(cpu_data->dcache.flags)))
- *(volatile unsigned char *)(int)eaddr;
+ ctrl_inb(eaddr);
}
}
- /* Don't use OCBI to invalidate the lines. That costs cycles directly.
- If the dummy block is just left resident, it will naturally get
- evicted as required. */
-
- return;
+ /*
+ * Don't use OCBI to invalidate the lines. That costs cycles
+ * directly. If the dummy block is just left resident, it will
+ * naturally get evicted as required.
+ */
}
-/****************************************************************************/
-
+/*
+ * Purge the entire contents of the dcache. The most efficient way to
+ * achieve this is to use alloco instructions on a region of unused
+ * memory equal in size to the cache, thereby causing the current
+ * contents to be discarded by natural eviction. The alternative, namely
+ * reading every tag, setting up a mapping for the corresponding page and
+ * doing an OCBP for the line, would be much more expensive.
+ */
static void sh64_dcache_purge_all(void)
{
- /* Purge the entire contents of the dcache. The most efficient way to
- achieve this is to use alloco instructions on a region of unused
- memory equal in size to the cache, thereby causing the current
- contents to be discarded by natural eviction. The alternative,
- namely reading every tag, setting up a mapping for the corresponding
- page and doing an OCBP for the line, would be much more expensive.
- */
sh64_dcache_purge_sets(0, cpu_data->dcache.sets);
-
- return;
-
}
-/****************************************************************************/
-
-static void sh64_dcache_purge_kernel_range(unsigned long start, unsigned long end)
-{
- /* Purge the range of addresses [start,end] from the D-cache. The
- addresses lie in the superpage mapping. There's no harm if we
- overpurge at either end - just a small performance loss. */
- unsigned long long ullend, addr, aligned_start;
-#if (NEFF == 32)
- aligned_start = (unsigned long long)(signed long long)(signed long) start;
-#else
-#error "NEFF != 32"
-#endif
- aligned_start &= L1_CACHE_ALIGN_MASK;
- addr = aligned_start;
-#if (NEFF == 32)
- ullend = (unsigned long long) (signed long long) (signed long) end;
-#else
-#error "NEFF != 32"
-#endif
- while (addr <= ullend) {
- asm __volatile__ ("ocbp %0, 0" : : "r" (addr));
- addr += L1_CACHE_BYTES;
- }
- return;
-}
/* Assumes this address (+ (2**n_synbits) pages up from it) aren't used for
anything else in the kernel */
#define MAGIC_PAGE0_START 0xffffffffec000000ULL
-static void sh64_dcache_purge_coloured_phy_page(unsigned long paddr, unsigned long eaddr)
+/* Purge the physical page 'paddr' from the cache. It's known that any
+ * cache lines requiring attention have the same page colour as the the
+ * address 'eaddr'.
+ *
+ * This relies on the fact that the D-cache matches on physical tags when
+ * no virtual tag matches. So we create an alias for the original page
+ * and purge through that. (Alternatively, we could have done this by
+ * switching ASID to match the original mapping and purged through that,
+ * but that involves ASID switching cost + probably a TLBMISS + refill
+ * anyway.)
+ */
+static void sh64_dcache_purge_coloured_phy_page(unsigned long paddr,
+ unsigned long eaddr)
{
- /* Purge the physical page 'paddr' from the cache. It's known that any
- cache lines requiring attention have the same page colour as the the
- address 'eaddr'.
-
- This relies on the fact that the D-cache matches on physical tags
- when no virtual tag matches. So we create an alias for the original
- page and purge through that. (Alternatively, we could have done
- this by switching ASID to match the original mapping and purged
- through that, but that involves ASID switching cost + probably a
- TLBMISS + refill anyway.)
- */
-
unsigned long long magic_page_start;
unsigned long long magic_eaddr, magic_eaddr_end;
@@ -531,47 +393,45 @@ static void sh64_dcache_purge_coloured_phy_page(unsigned long paddr, unsigned lo
/* As long as the kernel is not pre-emptible, this doesn't need to be
under cli/sti. */
-
sh64_setup_dtlb_cache_slot(magic_page_start, get_asid(), paddr);
magic_eaddr = magic_page_start;
magic_eaddr_end = magic_eaddr + PAGE_SIZE;
+
while (magic_eaddr < magic_eaddr_end) {
/* Little point in unrolling this loop - the OCBPs are blocking
and won't go any quicker (i.e. the loop overhead is parallel
to part of the OCBP execution.) */
- asm __volatile__ ("ocbp %0, 0" : : "r" (magic_eaddr));
+ __asm__ __volatile__ ("ocbp %0, 0" : : "r" (magic_eaddr));
magic_eaddr += L1_CACHE_BYTES;
}
sh64_teardown_dtlb_cache_slot();
}
-/****************************************************************************/
-
+/*
+ * Purge a page given its physical start address, by creating a temporary
+ * 1 page mapping and purging across that. Even if we know the virtual
+ * address (& vma or mm) of the page, the method here is more elegant
+ * because it avoids issues of coping with page faults on the purge
+ * instructions (i.e. no special-case code required in the critical path
+ * in the TLB miss handling).
+ */
static void sh64_dcache_purge_phy_page(unsigned long paddr)
{
- /* Pure a page given its physical start address, by creating a
- temporary 1 page mapping and purging across that. Even if we know
- the virtual address (& vma or mm) of the page, the method here is
- more elegant because it avoids issues of coping with page faults on
- the purge instructions (i.e. no special-case code required in the
- critical path in the TLB miss handling). */
-
unsigned long long eaddr_start, eaddr, eaddr_end;
int i;
/* As long as the kernel is not pre-emptible, this doesn't need to be
under cli/sti. */
-
eaddr_start = MAGIC_PAGE0_START;
- for (i=0; i < (1 << CACHE_OC_N_SYNBITS); i++) {
+ for (i = 0; i < (1 << CACHE_OC_N_SYNBITS); i++) {
sh64_setup_dtlb_cache_slot(eaddr_start, get_asid(), paddr);
eaddr = eaddr_start;
eaddr_end = eaddr + PAGE_SIZE;
while (eaddr < eaddr_end) {
- asm __volatile__ ("ocbp %0, 0" : : "r" (eaddr));
+ __asm__ __volatile__ ("ocbp %0, 0" : : "r" (eaddr));
eaddr += L1_CACHE_BYTES;
}
@@ -584,6 +444,7 @@ static void sh64_dcache_purge_user_pages(struct mm_struct *mm,
unsigned long addr, unsigned long end)
{
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte;
pte_t entry;
@@ -597,7 +458,11 @@ static void sh64_dcache_purge_user_pages(struct mm_struct *mm,
if (pgd_bad(*pgd))
return;
- pmd = pmd_offset(pgd, addr);
+ pud = pud_offset(pgd, addr);
+ if (pud_none(*pud) || pud_bad(*pud))
+ return;
+
+ pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd) || pmd_bad(*pmd))
return;
@@ -611,419 +476,357 @@ static void sh64_dcache_purge_user_pages(struct mm_struct *mm,
} while (pte++, addr += PAGE_SIZE, addr != end);
pte_unmap_unlock(pte - 1, ptl);
}
-/****************************************************************************/
+/*
+ * There are at least 5 choices for the implementation of this, with
+ * pros (+), cons(-), comments(*):
+ *
+ * 1. ocbp each line in the range through the original user's ASID
+ * + no lines spuriously evicted
+ * - tlbmiss handling (must either handle faults on demand => extra
+ * special-case code in tlbmiss critical path), or map the page in
+ * advance (=> flush_tlb_range in advance to avoid multiple hits)
+ * - ASID switching
+ * - expensive for large ranges
+ *
+ * 2. temporarily map each page in the range to a special effective
+ * address and ocbp through the temporary mapping; relies on the
+ * fact that SH-5 OCB* always do TLB lookup and match on ptags (they
+ * never look at the etags)
+ * + no spurious evictions
+ * - expensive for large ranges
+ * * surely cheaper than (1)
+ *
+ * 3. walk all the lines in the cache, check the tags, if a match
+ * occurs create a page mapping to ocbp the line through
+ * + no spurious evictions
+ * - tag inspection overhead
+ * - (especially for small ranges)
+ * - potential cost of setting up/tearing down page mapping for
+ * every line that matches the range
+ * * cost partly independent of range size
+ *
+ * 4. walk all the lines in the cache, check the tags, if a match
+ * occurs use 4 * alloco to purge the line (+3 other probably
+ * innocent victims) by natural eviction
+ * + no tlb mapping overheads
+ * - spurious evictions
+ * - tag inspection overhead
+ *
+ * 5. implement like flush_cache_all
+ * + no tag inspection overhead
+ * - spurious evictions
+ * - bad for small ranges
+ *
+ * (1) can be ruled out as more expensive than (2). (2) appears best
+ * for small ranges. The choice between (3), (4) and (5) for large
+ * ranges and the range size for the large/small boundary need
+ * benchmarking to determine.
+ *
+ * For now use approach (2) for small ranges and (5) for large ones.
+ */
static void sh64_dcache_purge_user_range(struct mm_struct *mm,
unsigned long start, unsigned long end)
{
- /* There are at least 5 choices for the implementation of this, with
- pros (+), cons(-), comments(*):
-
- 1. ocbp each line in the range through the original user's ASID
- + no lines spuriously evicted
- - tlbmiss handling (must either handle faults on demand => extra
- special-case code in tlbmiss critical path), or map the page in
- advance (=> flush_tlb_range in advance to avoid multiple hits)
- - ASID switching
- - expensive for large ranges
-
- 2. temporarily map each page in the range to a special effective
- address and ocbp through the temporary mapping; relies on the
- fact that SH-5 OCB* always do TLB lookup and match on ptags (they
- never look at the etags)
- + no spurious evictions
- - expensive for large ranges
- * surely cheaper than (1)
-
- 3. walk all the lines in the cache, check the tags, if a match
- occurs create a page mapping to ocbp the line through
- + no spurious evictions
- - tag inspection overhead
- - (especially for small ranges)
- - potential cost of setting up/tearing down page mapping for
- every line that matches the range
- * cost partly independent of range size
-
- 4. walk all the lines in the cache, check the tags, if a match
- occurs use 4 * alloco to purge the line (+3 other probably
- innocent victims) by natural eviction
- + no tlb mapping overheads
- - spurious evictions
- - tag inspection overhead
-
- 5. implement like flush_cache_all
- + no tag inspection overhead
- - spurious evictions
- - bad for small ranges
-
- (1) can be ruled out as more expensive than (2). (2) appears best
- for small ranges. The choice between (3), (4) and (5) for large
- ranges and the range size for the large/small boundary need
- benchmarking to determine.
-
- For now use approach (2) for small ranges and (5) for large ones.
-
- */
-
- int n_pages;
+ int n_pages = ((end - start) >> PAGE_SHIFT);
- n_pages = ((end - start) >> PAGE_SHIFT);
if (n_pages >= 64 || ((start ^ (end - 1)) & PMD_MASK)) {
-#if 1
sh64_dcache_purge_all();
-#else
- unsigned long long set, way;
- unsigned long mm_asid = mm->context & MMU_CONTEXT_ASID_MASK;
- for (set = 0; set < cpu_data->dcache.sets; set++) {
- unsigned long long set_base_config_addr = CACHE_OC_ADDRESS_ARRAY + (set << cpu_data->dcache.set_shift);
- for (way = 0; way < cpu_data->dcache.ways; way++) {
- unsigned long long config_addr = set_base_config_addr + (way << cpu_data->dcache.way_step_shift);
- unsigned long long tag0;
- unsigned long line_valid;
-
- asm __volatile__("getcfg %1, 0, %0" : "=r" (tag0) : "r" (config_addr));
- line_valid = tag0 & SH_CACHE_VALID;
- if (line_valid) {
- unsigned long cache_asid;
- unsigned long epn;
-
- cache_asid = (tag0 & cpu_data->dcache.asid_mask) >> cpu_data->dcache.asid_shift;
- /* The next line needs some
- explanation. The virtual tags
- encode bits [31:13] of the virtual
- address, bit [12] of the 'tag' being
- implied by the cache set index. */
- epn = (tag0 & cpu_data->dcache.epn_mask) | ((set & 0x80) << cpu_data->dcache.entry_shift);
-
- if ((cache_asid == mm_asid) && (start <= epn) && (epn < end)) {
- /* TODO : could optimise this
- call by batching multiple
- adjacent sets together. */
- sh64_dcache_purge_sets(set, 1);
- break; /* Don't waste time inspecting other ways for this set */
- }
- }
- }
- }
-#endif
} else {
/* Small range, covered by a single page table page */
start &= PAGE_MASK; /* should already be so */
end = PAGE_ALIGN(end); /* should already be so */
sh64_dcache_purge_user_pages(mm, start, end);
}
- return;
}
-static void sh64_dcache_wback_current_user_range(unsigned long start, unsigned long end)
+/*
+ * Purge the range of addresses from the D-cache.
+ *
+ * The addresses lie in the superpage mapping. There's no harm if we
+ * overpurge at either end - just a small performance loss.
+ */
+void __flush_purge_region(void *start, int size)
{
- unsigned long long aligned_start;
- unsigned long long ull_end;
- unsigned long long addr;
-
- ull_end = end;
+ unsigned long long ullend, addr, aligned_start;
- /* Just wback over the range using the natural addresses. TLB miss
- handling will be OK (TBC) : the range has just been written to by
- the signal frame setup code, so the PTEs must exist.
+ aligned_start = (unsigned long long)(signed long long)(signed long) start;
+ addr = L1_CACHE_ALIGN(aligned_start);
+ ullend = (unsigned long long) (signed long long) (signed long) start + size;
- Note, if we have CONFIG_PREEMPT and get preempted inside this loop,
- it doesn't matter, even if the pid->ASID mapping changes whilst
- we're away. In that case the cache will have been flushed when the
- mapping was renewed. So the writebacks below will be nugatory (and
- we'll doubtless have to fault the TLB entry/ies in again with the
- new ASID), but it's a rare case.
- */
- aligned_start = start & L1_CACHE_ALIGN_MASK;
- addr = aligned_start;
- while (addr < ull_end) {
- asm __volatile__ ("ocbwb %0, 0" : : "r" (addr));
+ while (addr <= ullend) {
+ __asm__ __volatile__ ("ocbp %0, 0" : : "r" (addr));
addr += L1_CACHE_BYTES;
}
}
-/****************************************************************************/
-
-/* These *MUST* lie in an area of virtual address space that's otherwise unused. */
-#define UNIQUE_EADDR_START 0xe0000000UL
-#define UNIQUE_EADDR_END 0xe8000000UL
-
-static unsigned long sh64_make_unique_eaddr(unsigned long user_eaddr, unsigned long paddr)
+void __flush_wback_region(void *start, int size)
{
- /* Given a physical address paddr, and a user virtual address
- user_eaddr which will eventually be mapped to it, create a one-off
- kernel-private eaddr mapped to the same paddr. This is used for
- creating special destination pages for copy_user_page and
- clear_user_page */
+ unsigned long long ullend, addr, aligned_start;
- static unsigned long current_pointer = UNIQUE_EADDR_START;
- unsigned long coloured_pointer;
+ aligned_start = (unsigned long long)(signed long long)(signed long) start;
+ addr = L1_CACHE_ALIGN(aligned_start);
+ ullend = (unsigned long long) (signed long long) (signed long) start + size;
- if (current_pointer == UNIQUE_EADDR_END) {
- sh64_dcache_purge_all();
- current_pointer = UNIQUE_EADDR_START;
+ while (addr < ullend) {
+ __asm__ __volatile__ ("ocbwb %0, 0" : : "r" (addr));
+ addr += L1_CACHE_BYTES;
}
-
- coloured_pointer = (current_pointer & ~CACHE_OC_SYN_MASK) | (user_eaddr & CACHE_OC_SYN_MASK);
- sh64_setup_dtlb_cache_slot(coloured_pointer, get_asid(), paddr);
-
- current_pointer += (PAGE_SIZE << CACHE_OC_N_SYNBITS);
-
- return coloured_pointer;
-}
-
-/****************************************************************************/
-
-static void sh64_copy_user_page_coloured(void *to, void *from, unsigned long address)
-{
- void *coloured_to;
-
- /* Discard any existing cache entries of the wrong colour. These are
- present quite often, if the kernel has recently used the page
- internally, then given it up, then it's been allocated to the user.
- */
- sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long) to);
-
- coloured_to = (void *) sh64_make_unique_eaddr(address, __pa(to));
- sh64_page_copy(from, coloured_to);
-
- sh64_teardown_dtlb_cache_slot();
}
-static void sh64_clear_user_page_coloured(void *to, unsigned long address)
+void __flush_invalidate_region(void *start, int size)
{
- void *coloured_to;
-
- /* Discard any existing kernel-originated lines of the wrong colour (as
- above) */
- sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long) to);
+ unsigned long long ullend, addr, aligned_start;
- coloured_to = (void *) sh64_make_unique_eaddr(address, __pa(to));
- sh64_page_clear(coloured_to);
+ aligned_start = (unsigned long long)(signed long long)(signed long) start;
+ addr = L1_CACHE_ALIGN(aligned_start);
+ ullend = (unsigned long long) (signed long long) (signed long) start + size;
- sh64_teardown_dtlb_cache_slot();
+ while (addr < ullend) {
+ __asm__ __volatile__ ("ocbi %0, 0" : : "r" (addr));
+ addr += L1_CACHE_BYTES;
+ }
}
-
#endif /* !CONFIG_DCACHE_DISABLED */
-/****************************************************************************/
-
-/*##########################################################################
- EXTERNALLY CALLABLE API.
- ##########################################################################*/
-
-/* These functions are described in Documentation/cachetlb.txt.
- Each one of these functions varies in behaviour depending on whether the
- I-cache and/or D-cache are configured out.
-
- Note that the Linux term 'flush' corresponds to what is termed 'purge' in
- the sh/sh64 jargon for the D-cache, i.e. write back dirty data then
- invalidate the cache lines, and 'invalidate' for the I-cache.
- */
-
-#undef FLUSH_TRACE
-
+/*
+ * Invalidate the entire contents of both caches, after writing back to
+ * memory any dirty data from the D-cache.
+ */
void flush_cache_all(void)
{
- /* Invalidate the entire contents of both caches, after writing back to
- memory any dirty data from the D-cache. */
sh64_dcache_purge_all();
sh64_icache_inv_all();
}
-/****************************************************************************/
-
+/*
+ * Invalidate an entire user-address space from both caches, after
+ * writing back dirty data (e.g. for shared mmap etc).
+ *
+ * This could be coded selectively by inspecting all the tags then
+ * doing 4*alloco on any set containing a match (as for
+ * flush_cache_range), but fork/exit/execve (where this is called from)
+ * are expensive anyway.
+ *
+ * Have to do a purge here, despite the comments re I-cache below.
+ * There could be odd-coloured dirty data associated with the mm still
+ * in the cache - if this gets written out through natural eviction
+ * after the kernel has reused the page there will be chaos.
+ *
+ * The mm being torn down won't ever be active again, so any Icache
+ * lines tagged with its ASID won't be visible for the rest of the
+ * lifetime of this ASID cycle. Before the ASID gets reused, there
+ * will be a flush_cache_all. Hence we don't need to touch the
+ * I-cache. This is similar to the lack of action needed in
+ * flush_tlb_mm - see fault.c.
+ */
void flush_cache_mm(struct mm_struct *mm)
{
- /* Invalidate an entire user-address space from both caches, after
- writing back dirty data (e.g. for shared mmap etc). */
-
- /* This could be coded selectively by inspecting all the tags then
- doing 4*alloco on any set containing a match (as for
- flush_cache_range), but fork/exit/execve (where this is called from)
- are expensive anyway. */
-
- /* Have to do a purge here, despite the comments re I-cache below.
- There could be odd-coloured dirty data associated with the mm still
- in the cache - if this gets written out through natural eviction
- after the kernel has reused the page there will be chaos.
- */
-
sh64_dcache_purge_all();
-
- /* The mm being torn down won't ever be active again, so any Icache
- lines tagged with its ASID won't be visible for the rest of the
- lifetime of this ASID cycle. Before the ASID gets reused, there
- will be a flush_cache_all. Hence we don't need to touch the
- I-cache. This is similar to the lack of action needed in
- flush_tlb_mm - see fault.c. */
}
-/****************************************************************************/
-
+/*
+ * Invalidate (from both caches) the range [start,end) of virtual
+ * addresses from the user address space specified by mm, after writing
+ * back any dirty data.
+ *
+ * Note, 'end' is 1 byte beyond the end of the range to flush.
+ */
void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
{
struct mm_struct *mm = vma->vm_mm;
- /* Invalidate (from both caches) the range [start,end) of virtual
- addresses from the user address space specified by mm, after writing
- back any dirty data.
-
- Note, 'end' is 1 byte beyond the end of the range to flush. */
-
sh64_dcache_purge_user_range(mm, start, end);
sh64_icache_inv_user_page_range(mm, start, end);
}
-/****************************************************************************/
-
-void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr, unsigned long pfn)
+/*
+ * Invalidate any entries in either cache for the vma within the user
+ * address space vma->vm_mm for the page starting at virtual address
+ * 'eaddr'. This seems to be used primarily in breaking COW. Note,
+ * the I-cache must be searched too in case the page in question is
+ * both writable and being executed from (e.g. stack trampolines.)
+ *
+ * Note, this is called with pte lock held.
+ */
+void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr,
+ unsigned long pfn)
{
- /* Invalidate any entries in either cache for the vma within the user
- address space vma->vm_mm for the page starting at virtual address
- 'eaddr'. This seems to be used primarily in breaking COW. Note,
- the I-cache must be searched too in case the page in question is
- both writable and being executed from (e.g. stack trampolines.)
-
- Note, this is called with pte lock held.
- */
-
sh64_dcache_purge_phy_page(pfn << PAGE_SHIFT);
- if (vma->vm_flags & VM_EXEC) {
+ if (vma->vm_flags & VM_EXEC)
sh64_icache_inv_user_page(vma, eaddr);
- }
}
-/****************************************************************************/
+void flush_dcache_page(struct page *page)
+{
+ sh64_dcache_purge_phy_page(page_to_phys(page));
+ wmb();
+}
-#ifndef CONFIG_DCACHE_DISABLED
+/*
+ * Flush the range [start,end] of kernel virtual adddress space from
+ * the I-cache. The corresponding range must be purged from the
+ * D-cache also because the SH-5 doesn't have cache snooping between
+ * the caches. The addresses will be visible through the superpage
+ * mapping, therefore it's guaranteed that there no cache entries for
+ * the range in cache sets of the wrong colour.
+ */
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+ __flush_purge_region((void *)start, end);
+ wmb();
+ sh64_icache_inv_kernel_range(start, end);
+}
-void copy_user_page(void *to, void *from, unsigned long address, struct page *page)
+/*
+ * Flush the range of user (defined by vma->vm_mm) address space starting
+ * at 'addr' for 'len' bytes from the cache. The range does not straddle
+ * a page boundary, the unique physical page containing the range is
+ * 'page'. This seems to be used mainly for invalidating an address
+ * range following a poke into the program text through the ptrace() call
+ * from another process (e.g. for BRK instruction insertion).
+ */
+void flush_icache_user_range(struct vm_area_struct *vma,
+ struct page *page, unsigned long addr, int len)
{
- /* 'from' and 'to' are kernel virtual addresses (within the superpage
- mapping of the physical RAM). 'address' is the user virtual address
- where the copy 'to' will be mapped after. This allows a custom
- mapping to be used to ensure that the new copy is placed in the
- right cache sets for the user to see it without having to bounce it
- out via memory. Note however : the call to flush_page_to_ram in
- (generic)/mm/memory.c:(break_cow) undoes all this good work in that one
- very important case!
-
- TBD : can we guarantee that on every call, any cache entries for
- 'from' are in the same colour sets as 'address' also? i.e. is this
- always used just to deal with COW? (I suspect not). */
-
- /* There are two possibilities here for when the page 'from' was last accessed:
- * by the kernel : this is OK, no purge required.
- * by the/a user (e.g. for break_COW) : need to purge.
-
- If the potential user mapping at 'address' is the same colour as
- 'from' there is no need to purge any cache lines from the 'from'
- page mapped into cache sets of colour 'address'. (The copy will be
- accessing the page through 'from').
- */
- if (((address ^ (unsigned long) from) & CACHE_OC_SYN_MASK) != 0) {
- sh64_dcache_purge_coloured_phy_page(__pa(from), address);
- }
+ sh64_dcache_purge_coloured_phy_page(page_to_phys(page), addr);
+ mb();
- if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0) {
- /* No synonym problem on destination */
- sh64_page_copy(from, to);
- } else {
- sh64_copy_user_page_coloured(to, from, address);
- }
+ if (vma->vm_flags & VM_EXEC)
+ sh64_icache_inv_user_small_range(vma->vm_mm, addr, len);
+}
+
+/*
+ * For the address range [start,end), write back the data from the
+ * D-cache and invalidate the corresponding region of the I-cache for the
+ * current process. Used to flush signal trampolines on the stack to
+ * make them executable.
+ */
+void flush_cache_sigtramp(unsigned long vaddr)
+{
+ unsigned long end = vaddr + L1_CACHE_BYTES;
- /* Note, don't need to flush 'from' page from the cache again - it's
- done anyway by the generic code */
+ __flush_wback_region((void *)vaddr, L1_CACHE_BYTES);
+ wmb();
+ sh64_icache_inv_current_user_range(vaddr, end);
}
-void clear_user_page(void *to, unsigned long address, struct page *page)
+/*
+ * These *MUST* lie in an area of virtual address space that's otherwise
+ * unused.
+ */
+#define UNIQUE_EADDR_START 0xe0000000UL
+#define UNIQUE_EADDR_END 0xe8000000UL
+
+/*
+ * Given a physical address paddr, and a user virtual address user_eaddr
+ * which will eventually be mapped to it, create a one-off kernel-private
+ * eaddr mapped to the same paddr. This is used for creating special
+ * destination pages for copy_user_page and clear_user_page.
+ */
+static unsigned long sh64_make_unique_eaddr(unsigned long user_eaddr,
+ unsigned long paddr)
{
- /* 'to' is a kernel virtual address (within the superpage
- mapping of the physical RAM). 'address' is the user virtual address
- where the 'to' page will be mapped after. This allows a custom
- mapping to be used to ensure that the new copy is placed in the
- right cache sets for the user to see it without having to bounce it
- out via memory.
- */
+ static unsigned long current_pointer = UNIQUE_EADDR_START;
+ unsigned long coloured_pointer;
- if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0) {
- /* No synonym problem on destination */
- sh64_page_clear(to);
- } else {
- sh64_clear_user_page_coloured(to, address);
+ if (current_pointer == UNIQUE_EADDR_END) {
+ sh64_dcache_purge_all();
+ current_pointer = UNIQUE_EADDR_START;
}
-}
-#endif /* !CONFIG_DCACHE_DISABLED */
+ coloured_pointer = (current_pointer & ~CACHE_OC_SYN_MASK) |
+ (user_eaddr & CACHE_OC_SYN_MASK);
+ sh64_setup_dtlb_cache_slot(coloured_pointer, get_asid(), paddr);
-/****************************************************************************/
+ current_pointer += (PAGE_SIZE << CACHE_OC_N_SYNBITS);
-void flush_dcache_page(struct page *page)
-{
- sh64_dcache_purge_phy_page(page_to_phys(page));
- wmb();
+ return coloured_pointer;
}
-/****************************************************************************/
-
-void flush_icache_range(unsigned long start, unsigned long end)
+static void sh64_copy_user_page_coloured(void *to, void *from,
+ unsigned long address)
{
- /* Flush the range [start,end] of kernel virtual adddress space from
- the I-cache. The corresponding range must be purged from the
- D-cache also because the SH-5 doesn't have cache snooping between
- the caches. The addresses will be visible through the superpage
- mapping, therefore it's guaranteed that there no cache entries for
- the range in cache sets of the wrong colour.
+ void *coloured_to;
- Primarily used for cohering the I-cache after a module has
- been loaded. */
+ /*
+ * Discard any existing cache entries of the wrong colour. These are
+ * present quite often, if the kernel has recently used the page
+ * internally, then given it up, then it's been allocated to the user.
+ */
+ sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long)to);
- /* We also make sure to purge the same range from the D-cache since
- flush_page_to_ram() won't be doing this for us! */
+ coloured_to = (void *)sh64_make_unique_eaddr(address, __pa(to));
+ copy_page(from, coloured_to);
- sh64_dcache_purge_kernel_range(start, end);
- wmb();
- sh64_icache_inv_kernel_range(start, end);
+ sh64_teardown_dtlb_cache_slot();
}
-/****************************************************************************/
-
-void flush_icache_user_range(struct vm_area_struct *vma,
- struct page *page, unsigned long addr, int len)
+static void sh64_clear_user_page_coloured(void *to, unsigned long address)
{
- /* Flush the range of user (defined by vma->vm_mm) address space
- starting at 'addr' for 'len' bytes from the cache. The range does
- not straddle a page boundary, the unique physical page containing
- the range is 'page'. This seems to be used mainly for invalidating
- an address range following a poke into the program text through the
- ptrace() call from another process (e.g. for BRK instruction
- insertion). */
+ void *coloured_to;
- sh64_dcache_purge_coloured_phy_page(page_to_phys(page), addr);
- mb();
+ /*
+ * Discard any existing kernel-originated lines of the wrong
+ * colour (as above)
+ */
+ sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long)to);
- if (vma->vm_flags & VM_EXEC) {
- sh64_icache_inv_user_small_range(vma->vm_mm, addr, len);
- }
-}
+ coloured_to = (void *)sh64_make_unique_eaddr(address, __pa(to));
+ clear_page(coloured_to);
-/*##########################################################################
- ARCH/SH64 PRIVATE CALLABLE API.
- ##########################################################################*/
+ sh64_teardown_dtlb_cache_slot();
+}
-void flush_cache_sigtramp(unsigned long start, unsigned long end)
+/*
+ * 'from' and 'to' are kernel virtual addresses (within the superpage
+ * mapping of the physical RAM). 'address' is the user virtual address
+ * where the copy 'to' will be mapped after. This allows a custom
+ * mapping to be used to ensure that the new copy is placed in the
+ * right cache sets for the user to see it without having to bounce it
+ * out via memory. Note however : the call to flush_page_to_ram in
+ * (generic)/mm/memory.c:(break_cow) undoes all this good work in that one
+ * very important case!
+ *
+ * TBD : can we guarantee that on every call, any cache entries for
+ * 'from' are in the same colour sets as 'address' also? i.e. is this
+ * always used just to deal with COW? (I suspect not).
+ *
+ * There are two possibilities here for when the page 'from' was last accessed:
+ * - by the kernel : this is OK, no purge required.
+ * - by the/a user (e.g. for break_COW) : need to purge.
+ *
+ * If the potential user mapping at 'address' is the same colour as
+ * 'from' there is no need to purge any cache lines from the 'from'
+ * page mapped into cache sets of colour 'address'. (The copy will be
+ * accessing the page through 'from').
+ */
+void copy_user_page(void *to, void *from, unsigned long address,
+ struct page *page)
{
- /* For the address range [start,end), write back the data from the
- D-cache and invalidate the corresponding region of the I-cache for
- the current process. Used to flush signal trampolines on the stack
- to make them executable. */
+ if (((address ^ (unsigned long) from) & CACHE_OC_SYN_MASK) != 0)
+ sh64_dcache_purge_coloured_phy_page(__pa(from), address);
- sh64_dcache_wback_current_user_range(start, end);
- wmb();
- sh64_icache_inv_current_user_range(start, end);
+ if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0)
+ copy_page(to, from);
+ else
+ sh64_copy_user_page_coloured(to, from, address);
}
+/*
+ * 'to' is a kernel virtual address (within the superpage mapping of the
+ * physical RAM). 'address' is the user virtual address where the 'to'
+ * page will be mapped after. This allows a custom mapping to be used to
+ * ensure that the new copy is placed in the right cache sets for the
+ * user to see it without having to bounce it out via memory.
+ */
+void clear_user_page(void *to, unsigned long address, struct page *page)
+{
+ if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0)
+ clear_page(to);
+ else
+ sh64_clear_user_page_coloured(to, address);
+}
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index 7b2131c9eed..d3c33fc5b1c 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -26,7 +26,7 @@ struct dma_coherent_mem {
void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
- void *ret;
+ void *ret, *ret_nocache;
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
int order = get_order(size);
@@ -44,17 +44,24 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
}
ret = (void *)__get_free_pages(gfp, order);
-
- if (ret != NULL) {
- memset(ret, 0, size);
- /*
- * Pages from the page allocator may have data present in
- * cache. So flush the cache before using uncached memory.
- */
- dma_cache_sync(NULL, ret, size, DMA_BIDIRECTIONAL);
- *dma_handle = virt_to_phys(ret);
+ if (!ret)
+ return NULL;
+
+ memset(ret, 0, size);
+ /*
+ * Pages from the page allocator may have data present in
+ * cache. So flush the cache before using uncached memory.
+ */
+ dma_cache_sync(dev, ret, size, DMA_BIDIRECTIONAL);
+
+ ret_nocache = ioremap_nocache(virt_to_phys(ret), size);
+ if (!ret_nocache) {
+ free_pages((unsigned long)ret, order);
+ return NULL;
}
- return ret;
+
+ *dma_handle = virt_to_phys(ret);
+ return ret_nocache;
}
EXPORT_SYMBOL(dma_alloc_coherent);
@@ -71,7 +78,8 @@ void dma_free_coherent(struct device *dev, size_t size,
} else {
WARN_ON(irqs_disabled()); /* for portability */
BUG_ON(mem && mem->flags & DMA_MEMORY_EXCLUSIVE);
- free_pages((unsigned long)vaddr, order);
+ free_pages((unsigned long)phys_to_virt(dma_handle), order);
+ iounmap(vaddr);
}
}
EXPORT_SYMBOL(dma_free_coherent);
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
index 33b43d20e9f..d1fa27594c6 100644
--- a/arch/sh/mm/fault_32.c
+++ b/arch/sh/mm/fault_32.c
@@ -15,6 +15,7 @@
#include <linux/mm.h>
#include <linux/hardirq.h>
#include <linux/kprobes.h>
+#include <asm/io_trapped.h>
#include <asm/system.h>
#include <asm/mmu_context.h>
#include <asm/tlbflush.h>
@@ -163,6 +164,8 @@ no_context:
if (fixup_exception(regs))
return;
+ if (handle_trapped_io(regs, address))
+ return;
/*
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
@@ -296,6 +299,14 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
entry = pte_mkdirty(entry);
entry = pte_mkyoung(entry);
+#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SMP)
+ /*
+ * ITLB is not affected by "ldtlb" instruction.
+ * So, we need to flush the entry by ourselves.
+ */
+ local_flush_tlb_one(get_asid(), address & PAGE_MASK);
+#endif
+
set_pte(pte, entry);
update_mmu_cache(NULL, address, entry);
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 2918c6b1465..e2ed6dd252b 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -203,6 +203,7 @@ void __init paging_init(void)
free_area_init_nodes(max_zone_pfns);
+#ifdef CONFIG_SUPERH32
/* Set up the uncached fixmap */
set_fixmap_nocache(FIX_UNCACHED, __pa(&__uncached_start));
@@ -214,6 +215,7 @@ void __init paging_init(void)
*/
cached_to_uncached = P2SEG - P1SEG;
#endif
+#endif
}
static struct kcore_list kcore_mem, kcore_vmalloc;
diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c
index 8aff065dd30..2de7302724f 100644
--- a/arch/sh/mm/numa.c
+++ b/arch/sh/mm/numa.c
@@ -80,9 +80,9 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
/* Reserve the pgdat and bootmap space with the bootmem allocator */
reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
- sizeof(struct pglist_data));
+ sizeof(struct pglist_data), BOOTMEM_DEFAULT);
reserve_bootmem_node(NODE_DATA(nid), free_pfn << PAGE_SHIFT,
- bootmap_pages << PAGE_SHIFT);
+ bootmap_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
/* It's up */
node_set_online(nid);
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index 25810670a0f..67997af25c0 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -45,3 +45,5 @@ MAGICPANELR2 SH_MAGIC_PANEL_R2
R2D_PLUS RTS7751R2D_PLUS
R2D_1 RTS7751R2D_1
CAYMAN SH_CAYMAN
+SDK7780 SH_SDK7780
+MIGOR SH_MIGOR
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 99f8971716d..c40343c5492 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -27,6 +27,13 @@ config ARCH_NO_VIRT_TO_BUS
config OF
def_bool y
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
+config HZ
+ int
+ default 100
+
source "init/Kconfig"
menu "General machine setup"
@@ -62,6 +69,7 @@ config NR_CPUS
config SPARC
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
# Identify this as a Sparc32 build
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 88d2cefd01b..c2eed8f7151 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -1224,23 +1224,6 @@ sys_nis_syscall:
call c_sys_nis_syscall
mov %l5, %o7
- .align 4
- .globl sys_ptrace
-sys_ptrace:
- call do_ptrace
- add %sp, STACKFRAME_SZ, %o0
-
- ld [%curptr + TI_FLAGS], %l5
- andcc %l5, _TIF_SYSCALL_TRACE, %g0
- be 1f
- nop
-
- call syscall_trace
- nop
-
-1:
- RESTORE_ALL
-
.align 4
.globl sys_execve
sys_execve:
diff --git a/arch/sparc/kernel/errtbls.c b/arch/sparc/kernel/errtbls.c
index bb36f6eadfe..ed14df7116e 100644
--- a/arch/sparc/kernel/errtbls.c
+++ b/arch/sparc/kernel/errtbls.c
@@ -1,21 +1,18 @@
-/* $Id: errtbls.c,v 1.2 1995/11/25 00:57:55 davem Exp $
- * errtbls.c: Error number conversion tables between various syscall
- * OS semantics.
+/* errtbls.c: Error number conversion tables.
*
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
*
* Based upon preliminary work which is:
*
* Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
*/
-#include <asm/bsderrno.h> /* NetBSD (bsd4.4) errnos */
#include <asm/solerrno.h> /* Solaris errnos */
-/* Here are tables which convert between Linux/SunOS error number
- * values to the equivalent in other OSs. Note that since the Linux
- * ones have been set up to match exactly those of SunOS, no
- * translation table is needed for that OS.
+/* Here is the table which converts between Linux error number values
+ * to the equivalent under Solaris. Note that since the Linux ones
+ * have been set up to match exactly those of SunOS, no translation
+ * table is needed for that OS.
*/
int solaris_errno[] = {
@@ -145,132 +142,3 @@ int solaris_errno[] = {
SOL_ELIBMAX,
SOL_ELIBSCN,
};
-
-int netbsd_errno[] = {
- 0,
- BSD_EPERM,
- BSD_ENOENT,
- BSD_ESRCH,
- BSD_EINTR,
- BSD_EIO,
- BSD_ENXIO,
- BSD_E2BIG,
- BSD_ENOEXEC,
- BSD_EBADF,
- BSD_ECHILD,
- BSD_EAGAIN,
- BSD_ENOMEM,
- BSD_EACCES,
- BSD_EFAULT,
- BSD_NOTBLK,
- BSD_EBUSY,
- BSD_EEXIST,
- BSD_EXDEV,
- BSD_ENODEV,
- BSD_ENOTDIR,
- BSD_EISDIR,
- BSD_EINVAL,
- BSD_ENFILE,
- BSD_EMFILE,
- BSD_ENOTTY,
- BSD_ETXTBSY,
- BSD_EFBIG,
- BSD_ENOSPC,
- BSD_ESPIPE,
- BSD_EROFS,
- BSD_EMLINK,
- BSD_EPIPE,
- BSD_EDOM,
- BSD_ERANGE,
- BSD_EWOULDBLOCK,
- BSD_EINPROGRESS,
- BSD_EALREADY,
- BSD_ENOTSOCK,
- BSD_EDESTADDRREQ,
- BSD_EMSGSIZE,
- BSD_EPROTOTYPE,
- BSD_ENOPROTOOPT,
- BSD_EPROTONOSUPPORT,
- BSD_ESOCKTNOSUPPORT,
- BSD_EOPNOTSUPP,
- BSD_EPFNOSUPPORT,
- BSD_EAFNOSUPPORT,
- BSD_EADDRINUSE,
- BSD_EADDRNOTAVAIL,
- BSD_ENETDOWN,
- BSD_ENETUNREACH,
- BSD_ENETRESET,
- BSD_ECONNABORTED,
- BSD_ECONNRESET,
- BSD_ENOBUFS,
- BSD_EISCONN,
- BSD_ENOTONN,
- BSD_ESHUTDOWN,
- BSD_ETOOMANYREFS,
- BSD_ETIMEDOUT,
- BSD_ECONNREFUSED,
- BSD_ELOOP,
- BSD_ENAMETOOLONG,
- BSD_EHOSTDOWN,
- BSD_EHOSTUNREACH,
- BSD_ENOTEMPTY,
- BSD_EPROCLIM,
- BSD_EUSERS,
- BSD_EDQUOT,
- BSD_ESTALE,
- BSD_EREMOTE,
- BSD_ENOSTR,
- BSD_ETIME,
- BSD_ENOSR,
- BSD_ENOMSG,
- BSD_EBADMSG,
- BSD_IDRM,
- BSD_EDEADLK,
- BSD_ENOLCK,
- BSD_ENONET,
- BSD_ERREMOTE,
- BSD_ENOLINK,
- BSD_EADV,
- BSD_ESRMNT,
- BSD_ECOMM,
- BSD_EPROTO,
- BSD_EMULTIHOP,
- BSD_EINVAL, /* EDOTDOT XXX??? */
- BSD_REMCHG,
- BSD_NOSYS,
- BSD_STRPIPE,
- BSD_EOVERFLOW,
- BSD_EBADFD,
- BSD_ECHRNG,
- BSD_EL2NSYNC,
- BSD_EL3HLT,
- BSD_EL3RST,
- BSD_NRNG,
- BSD_EUNATCH,
- BSD_ENOCSI,
- BSD_EL2HLT,
- BSD_EBADE,
- BSD_EBADR,
- BSD_EXFULL,
- BSD_ENOANO,
- BSD_EBADRQC,
- BSD_EBADSLT,
- BSD_EDEADLOCK,
- BSD_EBFONT,
- BSD_ELIBEXEC,
- BSD_ENODATA,
- BSD_ELIBBAD,
- BSD_ENOPKG,
- BSD_ELIBACC,
- BSD_ENOTUNIQ,
- BSD_ERESTART,
- BSD_EUCLEAN,
- BSD_ENOTNAM,
- BSD_ENAVAIL,
- BSD_EISNAM,
- BSD_EREMOTEIO,
- BSD_EILSEQ,
- BSD_ELIBMAX,
- BSD_ELIBSCN,
-};
-
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
index 3ea000d15e3..cc4c235c4f5 100644
--- a/arch/sparc/kernel/of_device.c
+++ b/arch/sparc/kernel/of_device.c
@@ -584,30 +584,3 @@ static int __init of_debug(char *str)
}
__setup("of_debug=", of_debug);
-
-struct of_device* of_platform_device_create(struct device_node *np,
- const char *bus_id,
- struct device *parent,
- struct bus_type *bus)
-{
- struct of_device *dev;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return NULL;
-
- dev->dev.parent = parent;
- dev->dev.bus = bus;
- dev->dev.release = of_release_dev;
-
- strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
-
- if (of_device_register(dev) != 0) {
- kfree(dev);
- return NULL;
- }
-
- return dev;
-}
-
-EXPORT_SYMBOL(of_platform_device_create);
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 4cd5d7818dc..a6a6f982337 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -713,10 +713,10 @@ static irqreturn_t pcic_timer_handler (int irq, void *h)
write_seqlock(&xtime_lock); /* Dummy, to show that we remember */
pcic_clear_clock_irq();
do_timer(1);
+ write_sequnlock(&xtime_lock);
#ifndef CONFIG_SMP
update_process_times(user_mode(get_irq_regs()));
#endif
- write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 77460e316a0..19186ce8850 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -20,7 +20,6 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/smp.h>
#include <linux/reboot.h>
#include <linux/delay.h>
@@ -567,38 +566,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
}
/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
- unsigned long first_stack_page;
-
- dump->magic = SUNOS_CORE_MAGIC;
- dump->len = sizeof(struct user);
- dump->regs.psr = regs->psr;
- dump->regs.pc = regs->pc;
- dump->regs.npc = regs->npc;
- dump->regs.y = regs->y;
- /* fuck me plenty */
- memcpy(&dump->regs.regs[0], &regs->u_regs[1], (sizeof(unsigned long) * 15));
- dump->uexec = current->thread.core_exec;
- dump->u_tsize = (((unsigned long) current->mm->end_code) -
- ((unsigned long) current->mm->start_code)) & ~(PAGE_SIZE - 1);
- dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1)));
- dump->u_dsize -= dump->u_tsize;
- dump->u_dsize &= ~(PAGE_SIZE - 1);
- first_stack_page = (regs->u_regs[UREG_FP] & ~(PAGE_SIZE - 1));
- dump->u_ssize = (TASK_SIZE - first_stack_page) & ~(PAGE_SIZE - 1);
- memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->thread.float_regs[0], (sizeof(unsigned long) * 32));
- dump->fpu.fpstatus.fsr = current->thread.fsr;
- dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0;
- dump->fpu.fpstatus.fpq_count = current->thread.fpqdepth;
- memcpy(&dump->fpu.fpstatus.fpq[0], &current->thread.fpqueue[0],
- ((sizeof(unsigned long) * 2) * 16));
- dump->sigcode = 0;
-}
-
-/*
* fill in the fpu structure for a core dump.
*/
int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 7452269bba2..5b54f11f4e5 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -1,6 +1,6 @@
/* ptrace.c: Sparc process tracing support.
*
- * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
+ * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
*
* Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
* and David Mosberger.
@@ -19,389 +19,343 @@
#include <linux/smp_lock.h>
#include <linux/security.h>
#include <linux/signal.h>
+#include <linux/regset.h>
+#include <linux/elf.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-#define MAGIC_CONSTANT 0x80000000
-
+/* #define ALLOW_INIT_TRACING */
-/* Returning from ptrace is a bit tricky because the syscall return
- * low level code assumes any value returned which is negative and
- * is a valid errno will mean setting the condition codes to indicate
- * an error return. This doesn't work, so we have this hook.
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure single step bits etc are not set.
*/
-static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
+void ptrace_disable(struct task_struct *child)
{
- regs->u_regs[UREG_I0] = error;
- regs->psr |= PSR_C;
- regs->pc = regs->npc;
- regs->npc += 4;
+ /* nothing to do */
}
-static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
-{
- regs->u_regs[UREG_I0] = value;
- regs->psr &= ~PSR_C;
- regs->pc = regs->npc;
- regs->npc += 4;
-}
+enum sparc_regset {
+ REGSET_GENERAL,
+ REGSET_FP,
+};
-static void
-pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long __user *addr)
+static int genregs32_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
{
- if (put_user(value, addr)) {
- pt_error_return(regs, EFAULT);
- return;
+ const struct pt_regs *regs = target->thread.kregs;
+ unsigned long __user *reg_window;
+ unsigned long *k = kbuf;
+ unsigned long __user *u = ubuf;
+ unsigned long reg;
+
+ if (target == current)
+ flush_user_windows();
+
+ pos /= sizeof(reg);
+ count /= sizeof(reg);
+
+ if (kbuf) {
+ for (; count > 0 && pos < 16; count--)
+ *k++ = regs->u_regs[pos++];
+
+ reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
+ for (; count > 0 && pos < 32; count--) {
+ if (get_user(*k++, &reg_window[pos++]))
+ return -EFAULT;
+ }
+ } else {
+ for (; count > 0 && pos < 16; count--) {
+ if (put_user(regs->u_regs[pos++], u++))
+ return -EFAULT;
+ }
+
+ reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
+ for (; count > 0 && pos < 32; count--) {
+ if (get_user(reg, &reg_window[pos++]) ||
+ put_user(reg, u++))
+ return -EFAULT;
+ }
}
- regs->u_regs[UREG_I0] = 0;
- regs->psr &= ~PSR_C;
- regs->pc = regs->npc;
- regs->npc += 4;
-}
+ while (count > 0) {
+ switch (pos) {
+ case 32: /* PSR */
+ reg = regs->psr;
+ break;
+ case 33: /* PC */
+ reg = regs->pc;
+ break;
+ case 34: /* NPC */
+ reg = regs->npc;
+ break;
+ case 35: /* Y */
+ reg = regs->y;
+ break;
+ case 36: /* WIM */
+ case 37: /* TBR */
+ reg = 0;
+ break;
+ default:
+ goto finish;
+ }
-static void
-pt_os_succ_return (struct pt_regs *regs, unsigned long val, long __user *addr)
-{
- if (current->personality == PER_SUNOS)
- pt_succ_return (regs, val);
- else
- pt_succ_return_linux (regs, val, addr);
+ if (kbuf)
+ *k++ = reg;
+ else if (put_user(reg, u++))
+ return -EFAULT;
+ pos++;
+ count--;
+ }
+finish:
+ pos *= sizeof(reg);
+ count *= sizeof(reg);
+
+ return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ 38 * sizeof(reg), -1);
}
-/* Fuck me gently with a chainsaw... */
-static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,
- struct task_struct *tsk, long __user *addr)
+static int genregs32_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
{
- struct pt_regs *cregs = tsk->thread.kregs;
- struct thread_info *t = task_thread_info(tsk);
- int v;
-
- if(offset >= 1024)
- offset -= 1024; /* whee... */
- if(offset & ((sizeof(unsigned long) - 1))) {
- pt_error_return(regs, EIO);
- return;
- }
- if(offset >= 16 && offset < 784) {
- offset -= 16; offset >>= 2;
- pt_os_succ_return(regs, *(((unsigned long *)(&t->reg_window[0]))+offset), addr);
- return;
- }
- if(offset >= 784 && offset < 832) {
- offset -= 784; offset >>= 2;
- pt_os_succ_return(regs, *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset), addr);
- return;
- }
- switch(offset) {
- case 0:
- v = t->ksp;
- break;
- case 4:
- v = t->kpc;
- break;
- case 8:
- v = t->kpsr;
- break;
- case 12:
- v = t->uwinmask;
- break;
- case 832:
- v = t->w_saved;
- break;
- case 896:
- v = cregs->u_regs[UREG_I0];
- break;
- case 900:
- v = cregs->u_regs[UREG_I1];
- break;
- case 904:
- v = cregs->u_regs[UREG_I2];
- break;
- case 908:
- v = cregs->u_regs[UREG_I3];
- break;
- case 912:
- v = cregs->u_regs[UREG_I4];
- break;
- case 916:
- v = cregs->u_regs[UREG_I5];
- break;
- case 920:
- v = cregs->u_regs[UREG_I6];
- break;
- case 924:
- if(tsk->thread.flags & MAGIC_CONSTANT)
- v = cregs->u_regs[UREG_G1];
- else
- v = 0;
- break;
- case 940:
- v = cregs->u_regs[UREG_I0];
- break;
- case 944:
- v = cregs->u_regs[UREG_I1];
- break;
+ struct pt_regs *regs = target->thread.kregs;
+ unsigned long __user *reg_window;
+ const unsigned long *k = kbuf;
+ const unsigned long __user *u = ubuf;
+ unsigned long reg;
+
+ if (target == current)
+ flush_user_windows();
+
+ pos /= sizeof(reg);
+ count /= sizeof(reg);
+
+ if (kbuf) {
+ for (; count > 0 && pos < 16; count--)
+ regs->u_regs[pos++] = *k++;
+
+ reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
+ for (; count > 0 && pos < 32; count--) {
+ if (put_user(*k++, &reg_window[pos++]))
+ return -EFAULT;
+ }
+ } else {
+ for (; count > 0 && pos < 16; count--) {
+ if (get_user(reg, u++))
+ return -EFAULT;
+ regs->u_regs[pos++] = reg;
+ }
- case 948:
- /* Isn't binary compatibility _fun_??? */
- if(cregs->psr & PSR_C)
- v = cregs->u_regs[UREG_I0] << 24;
- else
- v = 0;
- break;
+ reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
+ for (; count > 0 && pos < 32; count--) {
+ if (get_user(reg, u++) ||
+ put_user(reg, &reg_window[pos++]))
+ return -EFAULT;
+ }
+ }
+ while (count > 0) {
+ unsigned long psr;
+
+ if (kbuf)
+ reg = *k++;
+ else if (get_user(reg, u++))
+ return -EFAULT;
+
+ switch (pos) {
+ case 32: /* PSR */
+ psr = regs->psr;
+ psr &= ~PSR_ICC;
+ psr |= (reg & PSR_ICC);
+ regs->psr = psr;
+ break;
+ case 33: /* PC */
+ regs->pc = reg;
+ break;
+ case 34: /* NPC */
+ regs->npc = reg;
+ break;
+ case 35: /* Y */
+ regs->y = reg;
+ break;
+ case 36: /* WIM */
+ case 37: /* TBR */
+ break;
+ default:
+ goto finish;
+ }
- /* Rest of them are completely unsupported. */
- default:
- printk("%s [%d]: Wants to read user offset %ld\n",
- current->comm, task_pid_nr(current), offset);
- pt_error_return(regs, EIO);
- return;
+ pos++;
+ count--;
}
- if (current->personality == PER_SUNOS)
- pt_succ_return (regs, v);
- else
- pt_succ_return_linux (regs, v, addr);
- return;
+finish:
+ pos *= sizeof(reg);
+ count *= sizeof(reg);
+
+ return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 38 * sizeof(reg), -1);
}
-static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,
- struct task_struct *tsk)
+static int fpregs32_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
{
- struct pt_regs *cregs = tsk->thread.kregs;
- struct thread_info *t = task_thread_info(tsk);
- unsigned long value = regs->u_regs[UREG_I3];
-
- if(offset >= 1024)
- offset -= 1024; /* whee... */
- if(offset & ((sizeof(unsigned long) - 1)))
- goto failure;
- if(offset >= 16 && offset < 784) {
- offset -= 16; offset >>= 2;
- *(((unsigned long *)(&t->reg_window[0]))+offset) = value;
- goto success;
- }
- if(offset >= 784 && offset < 832) {
- offset -= 784; offset >>= 2;
- *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset) = value;
- goto success;
- }
- switch(offset) {
- case 896:
- cregs->u_regs[UREG_I0] = value;
- break;
- case 900:
- cregs->u_regs[UREG_I1] = value;
- break;
- case 904:
- cregs->u_regs[UREG_I2] = value;
- break;
- case 908:
- cregs->u_regs[UREG_I3] = value;
- break;
- case 912:
- cregs->u_regs[UREG_I4] = value;
- break;
- case 916:
- cregs->u_regs[UREG_I5] = value;
- break;
- case 920:
- cregs->u_regs[UREG_I6] = value;
- break;
- case 924:
- cregs->u_regs[UREG_I7] = value;
- break;
- case 940:
- cregs->u_regs[UREG_I0] = value;
- break;
- case 944:
- cregs->u_regs[UREG_I1] = value;
- break;
+ const unsigned long *fpregs = target->thread.float_regs;
+ int ret = 0;
- /* Rest of them are completely unsupported or "no-touch". */
- default:
- printk("%s [%d]: Wants to write user offset %ld\n",
- current->comm, task_pid_nr(current), offset);
- goto failure;
+#if 0
+ if (target == current)
+ save_and_clear_fpu();
+#endif
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ fpregs,
+ 0, 32 * sizeof(u32));
+
+ if (!ret)
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ 32 * sizeof(u32),
+ 33 * sizeof(u32));
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.fsr,
+ 33 * sizeof(u32),
+ 34 * sizeof(u32));
+
+ if (!ret) {
+ unsigned long val;
+
+ val = (1 << 8) | (8 << 16);
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &val,
+ 34 * sizeof(u32),
+ 35 * sizeof(u32));
}
-success:
- pt_succ_return(regs, 0);
- return;
-failure:
- pt_error_return(regs, EIO);
- return;
-}
-/* #define ALLOW_INIT_TRACING */
-/* #define DEBUG_PTRACE */
-
-#ifdef DEBUG_PTRACE
-char *pt_rq [] = {
- /* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR",
- /* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT",
- /* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH",
- /* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS",
- /* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT",
- /* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown",
- /* 24 */ "SYSCALL", ""
-};
-#endif
+ if (!ret)
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ 35 * sizeof(u32), -1);
-/*
- * Called by kernel/ptrace.c when detaching..
- *
- * Make sure single step bits etc are not set.
- */
-void ptrace_disable(struct task_struct *child)
-{
- /* nothing to do */
+ return ret;
}
-asmlinkage void do_ptrace(struct pt_regs *regs)
+static int fpregs32_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
{
- unsigned long request = regs->u_regs[UREG_I0];
- unsigned long pid = regs->u_regs[UREG_I1];
- unsigned long addr = regs->u_regs[UREG_I2];
- unsigned long data = regs->u_regs[UREG_I3];
- unsigned long addr2 = regs->u_regs[UREG_I4];
- struct task_struct *child;
+ unsigned long *fpregs = target->thread.float_regs;
int ret;
- lock_kernel();
-#ifdef DEBUG_PTRACE
- {
- char *s;
-
- if ((request >= 0) && (request <= 24))
- s = pt_rq [request];
- else
- s = "unknown";
-
- if (request == PTRACE_POKEDATA && data == 0x91d02001){
- printk ("do_ptrace: breakpoint pid=%d, addr=%08lx addr2=%08lx\n",
- pid, addr, addr2);
- } else
- printk("do_ptrace: rq=%s(%d) pid=%d addr=%08lx data=%08lx addr2=%08lx\n",
- s, (int) request, (int) pid, addr, data, addr2);
- }
+#if 0
+ if (target == current)
+ save_and_clear_fpu();
#endif
-
- if (request == PTRACE_TRACEME) {
- ret = ptrace_traceme();
- if (ret < 0)
- pt_error_return(regs, -ret);
- else
- pt_succ_return(regs, 0);
- goto out;
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ fpregs,
+ 0, 32 * sizeof(u32));
+ if (!ret)
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 32 * sizeof(u32),
+ 33 * sizeof(u32));
+ if (!ret && count > 0) {
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.fsr,
+ 33 * sizeof(u32),
+ 34 * sizeof(u32));
}
- child = ptrace_get_task_struct(pid);
- if (IS_ERR(child)) {
- ret = PTR_ERR(child);
- pt_error_return(regs, -ret);
- goto out;
- }
+ if (!ret)
+ ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 34 * sizeof(u32), -1);
+ return ret;
+}
- if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
- || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
- if (ptrace_attach(child)) {
- pt_error_return(regs, EPERM);
- goto out_tsk;
- }
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
+static const struct user_regset sparc32_regsets[] = {
+ /* Format is:
+ * G0 --> G7
+ * O0 --> O7
+ * L0 --> L7
+ * I0 --> I7
+ * PSR, PC, nPC, Y, WIM, TBR
+ */
+ [REGSET_GENERAL] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = 38 * sizeof(u32),
+ .size = sizeof(u32), .align = sizeof(u32),
+ .get = genregs32_get, .set = genregs32_set
+ },
+ /* Format is:
+ * F0 --> F31
+ * empty 32-bit word
+ * FSR (32--bit word)
+ * FPU QUEUE COUNT (8-bit char)
+ * FPU QUEUE ENTRYSIZE (8-bit char)
+ * FPU ENABLED (8-bit char)
+ * empty 8-bit char
+ * FPU QUEUE (64 32-bit ints)
+ */
+ [REGSET_FP] = {
+ .core_note_type = NT_PRFPREG,
+ .n = 99 * sizeof(u32),
+ .size = sizeof(u32), .align = sizeof(u32),
+ .get = fpregs32_get, .set = fpregs32_set
+ },
+};
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0) {
- pt_error_return(regs, -ret);
- goto out_tsk;
- }
+static const struct user_regset_view user_sparc32_view = {
+ .name = "sparc", .e_machine = EM_SPARC,
+ .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
+};
- switch(request) {
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
-
- if (access_process_vm(child, addr,
- &tmp, sizeof(tmp), 0) == sizeof(tmp))
- pt_os_succ_return(regs, tmp, (long __user *)data);
- else
- pt_error_return(regs, EIO);
- goto out_tsk;
- }
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+ return &user_sparc32_view;
+}
- case PTRACE_PEEKUSR:
- read_sunos_user(regs, addr, child, (long __user *) data);
- goto out_tsk;
-
- case PTRACE_POKEUSR:
- write_sunos_user(regs, addr, child);
- goto out_tsk;
-
- case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA: {
- if (access_process_vm(child, addr,
- &data, sizeof(data), 1) == sizeof(data))
- pt_succ_return(regs, 0);
- else
- pt_error_return(regs, EIO);
- goto out_tsk;
- }
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+{
+ unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4];
+ const struct user_regset_view *view;
+ int ret;
+
+ view = task_user_regset_view(child);
+ switch(request) {
case PTRACE_GETREGS: {
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
- struct pt_regs *cregs = child->thread.kregs;
- int rval;
- if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs))) {
- rval = -EFAULT;
- pt_error_return(regs, -rval);
- goto out_tsk;
- }
- __put_user(cregs->psr, (&pregs->psr));
- __put_user(cregs->pc, (&pregs->pc));
- __put_user(cregs->npc, (&pregs->npc));
- __put_user(cregs->y, (&pregs->y));
- for(rval = 1; rval < 16; rval++)
- __put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]));
- pt_succ_return(regs, 0);
-#ifdef DEBUG_PTRACE
- printk ("PC=%x nPC=%x o7=%x\n", cregs->pc, cregs->npc, cregs->u_regs [15]);
-#endif
- goto out_tsk;
+ ret = copy_regset_to_user(child, view, REGSET_GENERAL,
+ 32 * sizeof(u32),
+ 4 * sizeof(u32),
+ &pregs->psr);
+ if (!ret)
+ copy_regset_to_user(child, view, REGSET_GENERAL,
+ 1 * sizeof(u32),
+ 15 * sizeof(u32),
+ &pregs->u_regs[0]);
+ break;
}
case PTRACE_SETREGS: {
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
- struct pt_regs *cregs = child->thread.kregs;
- unsigned long psr, pc, npc, y;
- int i;
-
- /* Must be careful, tracing process can only set certain
- * bits in the psr.
- */
- if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
- }
- __get_user(psr, (&pregs->psr));
- __get_user(pc, (&pregs->pc));
- __get_user(npc, (&pregs->npc));
- __get_user(y, (&pregs->y));
- psr &= PSR_ICC;
- cregs->psr &= ~PSR_ICC;
- cregs->psr |= psr;
- if (!((pc | npc) & 3)) {
- cregs->pc = pc;
- cregs->npc =npc;
- }
- cregs->y = y;
- for(i = 1; i < 16; i++)
- __get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]));
- pt_succ_return(regs, 0);
- goto out_tsk;
+
+ ret = copy_regset_from_user(child, view, REGSET_GENERAL,
+ 32 * sizeof(u32),
+ 4 * sizeof(u32),
+ &pregs->psr);
+ if (!ret)
+ copy_regset_from_user(child, view, REGSET_GENERAL,
+ 1 * sizeof(u32),
+ 15 * sizeof(u32),
+ &pregs->u_regs[0]);
+ break;
}
case PTRACE_GETFPREGS: {
@@ -417,26 +371,25 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
} fpq[16];
};
struct fps __user *fps = (struct fps __user *) addr;
- int i;
- if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) {
- i = -EFAULT;
- pt_error_return(regs, -i);
- goto out_tsk;
- }
- for(i = 0; i < 32; i++)
- __put_user(child->thread.float_regs[i], (&fps->regs[i]));
- __put_user(child->thread.fsr, (&fps->fsr));
- __put_user(child->thread.fpqdepth, (&fps->fpqd));
- __put_user(0, (&fps->flags));
- __put_user(0, (&fps->extra));
- for(i = 0; i < 16; i++) {
- __put_user(child->thread.fpqueue[i].insn_addr,
- (&fps->fpq[i].insnaddr));
- __put_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
+ ret = copy_regset_to_user(child, view, REGSET_FP,
+ 0 * sizeof(u32),
+ 32 * sizeof(u32),
+ &fps->regs[0]);
+ if (!ret)
+ ret = copy_regset_to_user(child, view, REGSET_FP,
+ 33 * sizeof(u32),
+ 1 * sizeof(u32),
+ &fps->fsr);
+
+ if (!ret) {
+ if (__put_user(0, &fps->fpqd) ||
+ __put_user(0, &fps->flags) ||
+ __put_user(0, &fps->extra) ||
+ clear_user(fps->fpq, sizeof(fps->fpq)))
+ ret = -EFAULT;
}
- pt_succ_return(regs, 0);
- goto out_tsk;
+ break;
}
case PTRACE_SETFPREGS: {
@@ -452,137 +405,55 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
} fpq[16];
};
struct fps __user *fps = (struct fps __user *) addr;
- int i;
- if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) {
- i = -EFAULT;
- pt_error_return(regs, -i);
- goto out_tsk;
- }
- copy_from_user(&child->thread.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned long)));
- __get_user(child->thread.fsr, (&fps->fsr));
- __get_user(child->thread.fpqdepth, (&fps->fpqd));
- for(i = 0; i < 16; i++) {
- __get_user(child->thread.fpqueue[i].insn_addr,
- (&fps->fpq[i].insnaddr));
- __get_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
- }
- pt_succ_return(regs, 0);
- goto out_tsk;
+ ret = copy_regset_from_user(child, view, REGSET_FP,
+ 0 * sizeof(u32),
+ 32 * sizeof(u32),
+ &fps->regs[0]);
+ if (!ret)
+ ret = copy_regset_from_user(child, view, REGSET_FP,
+ 33 * sizeof(u32),
+ 1 * sizeof(u32),
+ &fps->fsr);
+ break;
}
case PTRACE_READTEXT:
- case PTRACE_READDATA: {
- int res = ptrace_readdata(child, addr,
- (void __user *) addr2, data);
-
- if (res == data) {
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
- /* Partial read is an IO failure */
- if (res >= 0)
- res = -EIO;
- pt_error_return(regs, -res);
- goto out_tsk;
- }
+ case PTRACE_READDATA:
+ ret = ptrace_readdata(child, addr,
+ (void __user *) addr2, data);
+
+ if (ret == data)
+ ret = 0;
+ else if (ret >= 0)
+ ret = -EIO;
+ break;
case PTRACE_WRITETEXT:
- case PTRACE_WRITEDATA: {
- int res = ptrace_writedata(child, (void __user *) addr2,
- addr, data);
-
- if (res == data) {
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
- /* Partial write is an IO failure */
- if (res >= 0)
- res = -EIO;
- pt_error_return(regs, -res);
- goto out_tsk;
- }
-
- case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
- addr = 1;
-
- case PTRACE_CONT: { /* restart after signal. */
- if (!valid_signal(data)) {
- pt_error_return(regs, EIO);
- goto out_tsk;
- }
-
- if (request == PTRACE_SYSCALL)
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- else
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-
- child->exit_code = data;
-#ifdef DEBUG_PTRACE
- printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n",
- child->comm, child->pid, child->exit_code,
- child->thread.kregs->pc,
- child->thread.kregs->npc);
-#endif
- wake_up_process(child);
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
-
-/*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL: {
- if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
- wake_up_process(child);
- child->exit_code = SIGKILL;
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
+ case PTRACE_WRITEDATA:
+ ret = ptrace_writedata(child, (void __user *) addr2,
+ addr, data);
+
+ if (ret == data)
+ ret = 0;
+ else if (ret >= 0)
+ ret = -EIO;
+ break;
- case PTRACE_SUNDETACH: { /* detach a process that was attached. */
- int err = ptrace_detach(child, data);
- if (err) {
- pt_error_return(regs, EIO);
- goto out_tsk;
- }
- pt_succ_return(regs, 0);
- goto out_tsk;
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
}
- /* PTRACE_DUMPCORE unsupported... */
-
- default: {
- int err = ptrace_request(child, request, addr, data);
- if (err)
- pt_error_return(regs, -err);
- else
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
- }
-out_tsk:
- if (child)
- put_task_struct(child);
-out:
- unlock_kernel();
+ return ret;
}
asmlinkage void syscall_trace(void)
{
-#ifdef DEBUG_PTRACE
- printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
-#endif
if (!test_thread_flag(TIF_SYSCALL_TRACE))
return;
if (!(current->ptrace & PT_PTRACED))
return;
- current->thread.flags ^= MAGIC_CONSTANT;
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0));
/*
@@ -590,10 +461,6 @@ asmlinkage void syscall_trace(void)
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
-#ifdef DEBUG_PTRACE
- printk("%s [%d]: syscall_trace exit= %x\n", current->comm,
- current->pid, current->exit_code);
-#endif
if (current->exit_code) {
send_sig (current->exit_code, current, 1);
current->exit_code = 0;
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index d07bc74773a..3cf78f16084 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -16,7 +16,6 @@
#include <linux/initrd.h>
#include <asm/smp.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/screen_info.h>
#include <linux/delay.h>
#include <linux/fs.h>
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index ef647acc479..c1025e55165 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -51,7 +51,6 @@
#ifdef CONFIG_PCI
#include <asm/ebus.h>
#endif
-#include <asm/a.out.h>
#include <asm/io-unit.h>
#include <asm/bug.h>
@@ -214,8 +213,6 @@ EXPORT_SYMBOL(kunmap_atomic);
EXPORT_SYMBOL(svr4_setcontext);
EXPORT_SYMBOL(svr4_getcontext);
-EXPORT_SYMBOL(dump_thread);
-
/* prom symbols */
EXPORT_SYMBOL(idprom);
EXPORT_SYMBOL(prom_root_node);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 89a6de95070..0def48158c7 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -19,12 +19,12 @@
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/profile.h>
+#include <linux/delay.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
#include <asm/irq_regs.h>
-#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
@@ -41,8 +41,6 @@
extern ctxd_t *srmmu_ctx_table_phys;
-extern void calibrate_delay(void);
-
static volatile int smp_processors_ready = 0;
static int smp_highest_cpu;
extern volatile unsigned long cpu_callin_map[NR_CPUS];
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 730eb5796f8..0b940726716 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -16,6 +16,8 @@
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/profile.h>
+#include <linux/delay.h>
+
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/irq_regs.h>
@@ -23,7 +25,6 @@
#include <asm/ptrace.h>
#include <asm/atomic.h>
-#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
@@ -39,8 +40,6 @@
extern ctxd_t *srmmu_ctx_table_phys;
-extern void calibrate_delay(void);
-
extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern unsigned char boot_cpu_id;
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 55722840859..9064485dc40 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -79,7 +79,8 @@ sys_call_table:
/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
/*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
/*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate
+/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
+/*315*/ .long sys_timerfd_settime, sys_timerfd_gettime
#ifdef CONFIG_SUNOS_EMUL
/* Now the SunOS syscall table. */
@@ -197,6 +198,7 @@ sunos_sys_table:
.long sunos_nosys, sunos_nosys, sunos_nosys
.long sunos_nosys
/*310*/ .long sunos_nosys, sunos_nosys, sunos_nosys
- .long sunos_nosys, sunos_nosys
+ .long sunos_nosys, sunos_nosys, sunos_nosys
+ .long sunos_nosys
#endif
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 00b393c3a4a..cfaf22c05bc 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -128,10 +128,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
clear_clock_irq();
do_timer(1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
-
/* Determine when to update the Mostek clock. */
if (ntp_synced() &&
@@ -145,6 +141,9 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
}
write_sequnlock(&xtime_lock);
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(get_irq_regs()));
+#endif
return IRQ_HANDLED;
}
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 216147d6e61..b1002c60719 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -89,6 +89,10 @@ SECTIONS
.data.cacheline_aligned : {
*(.data.cacheline_aligned)
}
+ . = ALIGN(32);
+ .data.read_mostly : {
+ *(.data.read_mostly)
+ }
__bss_start = .;
.sbss : {
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index a1bef07755a..b89837accc8 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -259,7 +259,7 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
if (initrd_start) {
/* Reserve the initrd image area. */
size = initrd_end - initrd_start;
- reserve_bootmem(initrd_start, size);
+ reserve_bootmem(initrd_start, size, BOOTMEM_DEFAULT);
*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
initrd_start = (initrd_start - phys_base) + PAGE_OFFSET;
@@ -268,7 +268,7 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
#endif
/* Reserve the kernel text/data/bss. */
size = (start_pfn << PAGE_SHIFT) - phys_base;
- reserve_bootmem(phys_base, size);
+ reserve_bootmem(phys_base, size, BOOTMEM_DEFAULT);
*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
/* Reserve the bootmem map. We do not account for it
@@ -276,7 +276,7 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
* in free_all_bootmem.
*/
size = bootmap_size;
- reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size);
+ reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size, BOOTMEM_DEFAULT);
*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
return max_pfn;
diff --git a/arch/sparc/mm/loadmmu.c b/arch/sparc/mm/loadmmu.c
index 36b4d24988f..2d9cd65160a 100644
--- a/arch/sparc/mm/loadmmu.c
+++ b/arch/sparc/mm/loadmmu.c
@@ -14,7 +14,6 @@
#include <asm/system.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <asm/a.out.h>
#include <asm/mmu_context.h>
#include <asm/oplib.h>
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 17b485f2825..23d3291a3e8 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -34,7 +34,6 @@
#include <asm/sbus.h>
#include <asm/asi.h>
#include <asm/msi.h>
-#include <asm/a.out.h>
#include <asm/mmu_context.h>
#include <asm/io-unit.h>
#include <asm/cacheflush.h>
@@ -490,14 +489,17 @@ srmmu_pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
return (pte_t *)srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
}
-static struct page *
+static pgtable_t
srmmu_pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
unsigned long pte;
+ struct page *page;
if ((pte = (unsigned long)srmmu_pte_alloc_one_kernel(mm, address)) == 0)
return NULL;
- return pfn_to_page( __nocache_pa(pte) >> PAGE_SHIFT );
+ page = pfn_to_page( __nocache_pa(pte) >> PAGE_SHIFT );
+ pgtable_page_ctor(page);
+ return page;
}
static void srmmu_free_pte_fast(pte_t *pte)
@@ -505,10 +507,11 @@ static void srmmu_free_pte_fast(pte_t *pte)
srmmu_free_nocache((unsigned long)pte, PTE_SIZE);
}
-static void srmmu_pte_free(struct page *pte)
+static void srmmu_pte_free(pgtable_t pte)
{
unsigned long p;
+ pgtable_page_dtor(pte);
p = (unsigned long)page_address(pte); /* Cached address (for test) */
if (p == 0)
BUG();
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 0729305f2f5..c0442e8c4b1 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -1947,12 +1947,17 @@ static pte_t *sun4c_pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add
return pte;
}
-static struct page *sun4c_pte_alloc_one(struct mm_struct *mm, unsigned long address)
+static pgtable_t sun4c_pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
- pte_t *pte = sun4c_pte_alloc_one_kernel(mm, address);
+ pte_t *pte;
+ struct page *page;
+
+ pte = sun4c_pte_alloc_one_kernel(mm, address);
if (pte == NULL)
return NULL;
- return virt_to_page(pte);
+ page = virt_to_page(pte);
+ pgtable_page_ctor(page);
+ return page;
}
static inline void sun4c_free_pte_fast(pte_t *pte)
@@ -1962,8 +1967,9 @@ static inline void sun4c_free_pte_fast(pte_t *pte)
pgtable_cache_size++;
}
-static void sun4c_pte_free(struct page *pte)
+static void sun4c_pte_free(pgtable_t pte)
{
+ pgtable_page_dtor(pte);
sun4c_free_pte_fast(page_address(pte));
}
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index a8c6366f05a..3af378ddb6a 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -14,6 +14,7 @@ config SPARC
config SPARC64
bool
default y
+ select HAVE_IDE
help
SPARC is a family of RISC microprocessors designed and marketed by
Sun Microsystems, incorporated. This port covers the newer 64-bit
@@ -40,6 +41,10 @@ config MMU
bool
default y
+config IOMMU_HELPER
+ bool
+ default y
+
config QUICKLIST
bool
default y
@@ -81,6 +86,9 @@ config GENERIC_HARDIRQS_NO__DO_IRQ
bool
def_bool y
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
choice
prompt "Kernel page size"
default SPARC64_PAGE_SIZE_8KB
@@ -380,17 +388,11 @@ config COMPAT
bool
depends on SPARC32_COMPAT
default y
-
-config BINFMT_ELF32
- bool "Kernel support for 32-bit ELF binaries"
- depends on SPARC32_COMPAT
- help
- This allows you to run 32-bit Linux/ELF binaries on your Ultra.
- Everybody wants this; say Y.
+ select COMPAT_BINFMT_ELF
config BINFMT_AOUT32
bool "Kernel support for 32-bit (ie. SunOS) a.out binaries"
- depends on SPARC32_COMPAT
+ depends on SPARC32_COMPAT && ARCH_SUPPORTS_AOUT
help
This allows you to run 32-bit a.out format binaries on your Ultra.
If you want to run SunOS binaries (see SunOS binary emulation below)
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index f62d9f6c5e2..833d74b2b19 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24-rc4
-# Tue Dec 4 00:37:59 2007
+# Linux kernel version: 2.6.24
+# Tue Feb 5 17:28:19 2008
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
@@ -17,6 +17,7 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_AUDIT_ARCH=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_OF=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
@@ -30,13 +31,15 @@ CONFIG_HZ_100=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_HOTPLUG_CPU=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# General setup
#
CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
# CONFIG_LOCALVERSION_AUTO is not set
@@ -76,6 +79,7 @@ CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
@@ -83,6 +87,14 @@ CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -92,6 +104,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_BLK_DEV_BSG=y
@@ -109,6 +122,8 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_RCU is not set
CONFIG_SYSVIPC_COMPAT=y
CONFIG_GENERIC_HARDIRQS=y
@@ -119,7 +134,8 @@ CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-# CONFIG_SMP is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=64
# CONFIG_CPU_FREQ is not set
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -169,9 +185,12 @@ CONFIG_BINFMT_ELF32=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
CONFIG_SOLARIS_EMUL=y
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
+# CONFIG_RCU_TRACE is not set
# CONFIG_CMDLINE_BOOL is not set
#
@@ -189,6 +208,7 @@ CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
CONFIG_NET_KEY=m
CONFIG_NET_KEY_MIGRATE=y
CONFIG_INET=y
@@ -249,9 +269,9 @@ CONFIG_IP_DCCP_ACKVEC=y
CONFIG_IP_DCCP_CCID2=m
# CONFIG_IP_DCCP_CCID2_DEBUG is not set
CONFIG_IP_DCCP_CCID3=m
-CONFIG_IP_DCCP_TFRC_LIB=m
# CONFIG_IP_DCCP_CCID3_DEBUG is not set
CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=m
#
# DCCP Kernel Hacking
@@ -279,6 +299,7 @@ CONFIG_VLAN_8021Q=m
CONFIG_NET_PKTGEN=m
CONFIG_NET_TCPPROBE=m
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
@@ -343,6 +364,7 @@ CONFIG_BLK_DEV_IDE=y
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
@@ -359,7 +381,6 @@ CONFIG_IDE_GENERIC=y
# PCI IDE chipsets support
#
CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_GENERIC is not set
# CONFIG_BLK_DEV_OPTI621 is not set
@@ -389,7 +410,6 @@ CONFIG_BLK_DEV_ALI15X3=y
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_BLK_DEV_TC86C001 is not set
-# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
CONFIG_IDE_ARCH_OBSOLETE_INIT=y
# CONFIG_BLK_DEV_HD is not set
@@ -501,7 +521,6 @@ CONFIG_NETDEVICES=y
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
-# CONFIG_IP1000 is not set
# CONFIG_ARCNET is not set
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
@@ -533,6 +552,7 @@ CONFIG_NET_PCI=y
# CONFIG_NE2K_PCI is not set
# CONFIG_8139CP is not set
# CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
@@ -545,6 +565,9 @@ CONFIG_E1000=m
CONFIG_E1000_NAPI=y
# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_E1000E is not set
+# CONFIG_E1000E_ENABLED is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
# CONFIG_MYRI_SBUS is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
@@ -570,6 +593,7 @@ CONFIG_NETDEV_10000=y
CONFIG_NIU=m
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
# CONFIG_TR is not set
#
@@ -602,7 +626,6 @@ CONFIG_PPPOE=m
# CONFIG_SLIP is not set
CONFIG_SLHC=m
# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -679,6 +702,7 @@ CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
#
# Serial drivers
@@ -747,13 +771,13 @@ CONFIG_I2C_ALGOBIT=y
#
# Miscellaneous I2C Chip support
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -990,6 +1014,7 @@ CONFIG_SND_ALI5451=m
# CONFIG_SND_BT87X is not set
# CONFIG_SND_CA0106 is not set
# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
# CONFIG_SND_DARLA20 is not set
@@ -1014,6 +1039,7 @@ CONFIG_SND_ALI5451=m
# CONFIG_SND_HDA_INTEL is not set
# CONFIG_SND_HDSP is not set
# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
# CONFIG_SND_ICE1712 is not set
# CONFIG_SND_ICE1724 is not set
# CONFIG_SND_INTEL8X0 is not set
@@ -1031,6 +1057,7 @@ CONFIG_SND_ALI5451=m
# CONFIG_SND_TRIDENT is not set
# CONFIG_SND_VIA82XX is not set
# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
# CONFIG_SND_VX222 is not set
# CONFIG_SND_YMFPCI is not set
# CONFIG_SND_AC97_POWER_SAVE is not set
@@ -1058,6 +1085,10 @@ CONFIG_SND_SUN_CS4231=m
#
#
+# ALSA SoC audio for Freescale SOCs
+#
+
+#
# Open Sound System
#
# CONFIG_SOUND_PRIME is not set
@@ -1080,6 +1111,7 @@ CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
#
# Miscellaneous USB options
@@ -1093,7 +1125,6 @@ CONFIG_USB_DEVICEFS=y
# USB Host Controller Drivers
#
CONFIG_USB_EHCI_HCD=m
-# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_ISP116X_HCD is not set
@@ -1143,10 +1174,6 @@ CONFIG_USB_STORAGE=m
#
# USB port drivers
#
-
-#
-# USB Serial Converter support
-#
# CONFIG_USB_SERIAL is not set
#
@@ -1172,14 +1199,6 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
# CONFIG_NEW_LEDS is not set
@@ -1332,11 +1351,6 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
-# CONFIG_MARKERS is not set
#
# Kernel hacking
@@ -1374,6 +1388,8 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FORCED_INLINING=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_SAMPLES is not set
@@ -1396,8 +1412,9 @@ CONFIG_ASYNC_MEMCPY=m
CONFIG_ASYNC_XOR=m
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_BLKCIPHER=y
+# CONFIG_CRYPTO_SEQIV is not set
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
@@ -1416,6 +1433,9 @@ CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_XTS=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CCM is not set
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_FCRYPT=m
@@ -1431,13 +1451,16 @@ CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_SEED=m
+# CONFIG_CRYPTO_SALSA20 is not set
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_LZO is not set
CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
#
# Library routines
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index ef50d217432..1bf5b187de4 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -11,7 +11,7 @@ obj-y := process.o setup.o cpu.o idprom.o \
traps.o auxio.o una_asm.o sysfs.o iommu.o \
irq.o ptrace.o time.o sys_sparc.o signal.o \
unaligned.o central.o pci.o starfire.o semaphore.o \
- power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
+ power.o sbus.o sparc64_ksyms.o chmc.o \
visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
@@ -21,7 +21,6 @@ obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o \
obj-$(CONFIG_PCI_MSI) += pci_msi.o
obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o
obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
-obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index 92c1b36a2e1..9877f2d7672 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -32,6 +32,7 @@
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
+#include <asm/a.out-core.h>
static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout32_library(struct file*);
@@ -101,7 +102,7 @@ static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file,
current->flags |= PF_DUMPCORE;
strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
dump.signal = signr;
- dump_thread(regs, &dump);
+ aout_dump_thread(regs, &dump);
/* If the size of the dump file exceeds the rlimit, then see what would happen
if we wrote the stack, but not the data area. */
diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c
deleted file mode 100644
index 1587a29a4b0..00000000000
--- a/arch/sparc64/kernel/binfmt_elf32.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra.
- *
- * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz)
- */
-
-#define ELF_ARCH EM_SPARC
-#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2MSB;
-
-/* For the most part we present code dumps in the format
- * Solaris does.
- */
-typedef unsigned int elf_greg_t;
-#define ELF_NGREG 38
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-/* Format is:
- * G0 --> G7
- * O0 --> O7
- * L0 --> L7
- * I0 --> I7
- * PSR, PC, nPC, Y, WIM, TBR
- */
-#include <asm/psrcompat.h>
-#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \
-do { unsigned int *dest = &(__elf_regs[0]); \
- struct pt_regs *src = (__pt_regs); \
- unsigned int __user *sp; \
- int i; \
- for(i = 0; i < 16; i++) \
- dest[i] = (unsigned int) src->u_regs[i];\
- /* Don't try this at home kids... */ \
- sp = (unsigned int __user *) (src->u_regs[14] & \
- 0x00000000fffffffc); \
- for(i = 0; i < 16; i++) \
- __get_user(dest[i+16], &sp[i]); \
- dest[32] = tstate_to_psr(src->tstate); \
- dest[33] = (unsigned int) src->tpc; \
- dest[34] = (unsigned int) src->tnpc; \
- dest[35] = src->y; \
- dest[36] = dest[37] = 0; /* XXX */ \
-} while(0);
-
-typedef struct {
- union {
- unsigned int pr_regs[32];
- unsigned long pr_dregs[16];
- } pr_fr;
- unsigned int __unused;
- unsigned int pr_fsr;
- unsigned char pr_qcnt;
- unsigned char pr_q_entrysize;
- unsigned char pr_en;
- unsigned int pr_q[64];
-} elf_fpregset_t;
-
-/* UltraSparc extensions. Still unused, but will be eventually. */
-typedef struct {
- unsigned int pr_type;
- unsigned int pr_align;
- union {
- struct {
- union {
- unsigned int pr_regs[32];
- unsigned long pr_dregs[16];
- long double pr_qregs[8];
- } pr_xfr;
- } pr_v8p;
- unsigned int pr_xfsr;
- unsigned int pr_fprs;
- unsigned int pr_xg[8];
- unsigned int pr_xo[8];
- unsigned long pr_tstate;
- unsigned int pr_filler[8];
- } pr_un;
-} elf_xregset_t;
-
-#define elf_check_arch(x) (((x)->e_machine == EM_SPARC) || ((x)->e_machine == EM_SPARC32PLUS))
-
-#define ELF_ET_DYN_BASE 0x70000000
-
-
-#include <asm/processor.h>
-#include <linux/module.h>
-#include <linux/elfcore.h>
-#include <linux/compat.h>
-
-#define elf_prstatus elf_prstatus32
-struct elf_prstatus32
-{
- struct elf_siginfo pr_info; /* Info associated with signal */
- short pr_cursig; /* Current signal */
- unsigned int pr_sigpend; /* Set of pending signals */
- unsigned int pr_sighold; /* Set of held signals */
- pid_t pr_pid;
- pid_t pr_ppid;
- pid_t pr_pgrp;
- pid_t pr_sid;
- struct compat_timeval pr_utime; /* User time */
- struct compat_timeval pr_stime; /* System time */
- struct compat_timeval pr_cutime; /* Cumulative user time */
- struct compat_timeval pr_cstime; /* Cumulative system time */
- elf_gregset_t pr_reg; /* GP registers */
- int pr_fpvalid; /* True if math co-processor being used. */
-};
-
-#define elf_prpsinfo elf_prpsinfo32
-struct elf_prpsinfo32
-{
- char pr_state; /* numeric process state */
- char pr_sname; /* char for pr_state */
- char pr_zomb; /* zombie */
- char pr_nice; /* nice val */
- unsigned int pr_flag; /* flags */
- u16 pr_uid;
- u16 pr_gid;
- pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
- /* Lots missing */
- char pr_fname[16]; /* filename of executable */
- char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
-};
-
-#include <linux/highuid.h>
-
-#undef NEW_TO_OLD_UID
-#undef NEW_TO_OLD_GID
-#define NEW_TO_OLD_UID(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
-#define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
-
-#include <linux/time.h>
-
-#undef cputime_to_timeval
-#define cputime_to_timeval cputime_to_compat_timeval
-static inline void
-cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
-{
- unsigned long jiffies = cputime_to_jiffies(cputime);
- value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
- value->tv_sec = jiffies / HZ;
-}
-
-#undef start_thread
-#define start_thread start_thread32
-#define init_elf_binfmt init_elf32_binfmt
-
-MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit SparcLinux binaries on the Ultra");
-MODULE_AUTHOR("Eric Youngdale, David S. Miller, Jakub Jelinek");
-
-#undef MODULE_DESCRIPTION
-#undef MODULE_AUTHOR
-
-#include <asm/a.out.h>
-
-#undef TASK_SIZE
-#define TASK_SIZE STACK_TOP32
-
-#include "../../../fs/binfmt_elf.c"
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index ea257e82836..6be4d2d2904 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -1477,10 +1477,6 @@ sys32_rt_sigreturn:
add %o7, 1f-.-4, %o7
nop
#endif
-sys_ptrace: add %sp, PTREGS_OFF, %o0
- call do_ptrace
- add %o7, 1f-.-4, %o7
- nop
.align 32
1: ldx [%curptr + TI_FLAGS], %l5
andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index c4147ad8677..44b105c04dd 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -632,11 +632,36 @@ tlb_fixup_done:
/* Not reached... */
1:
+ /* If we boot on a non-zero cpu, all of the per-cpu
+ * variable references we make before setting up the
+ * per-cpu areas will use a bogus offset. Put a
+ * compensating factor into __per_cpu_base to handle
+ * this cleanly.
+ *
+ * What the per-cpu code calculates is:
+ *
+ * __per_cpu_base + (cpu << __per_cpu_shift)
+ *
+ * These two variables are zero initially, so to
+ * make it all cancel out to zero we need to put
+ * "0 - (cpu << 0)" into __per_cpu_base so that the
+ * above formula evaluates to zero.
+ *
+ * We cannot even perform a printk() until this stuff
+ * is setup as that calls cpu_clock() which uses
+ * per-cpu variables.
+ */
+ sub %g0, %o0, %o1
+ sethi %hi(__per_cpu_base), %o2
+ stx %o1, [%o2 + %lo(__per_cpu_base)]
#else
mov 0, %o0
#endif
sth %o0, [%g6 + TI_CPU]
+ call prom_init_report
+ nop
+
/* Off we go.... */
call start_kernel
nop
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index 070a4846c0c..d3276ebcfb4 100644
--- a/arch/sparc64/kernel/iommu.c
+++ b/arch/sparc64/kernel/iommu.c
@@ -1,6 +1,6 @@
/* iommu.c: Generic sparc64 IOMMU support.
*
- * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1999, 2007, 2008 David S. Miller (davem@davemloft.net)
* Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com)
*/
@@ -10,6 +10,7 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h>
+#include <linux/iommu-helper.h>
#ifdef CONFIG_PCI
#include <linux/pci.h>
@@ -41,7 +42,7 @@
"i" (ASI_PHYS_BYPASS_EC_E))
/* Must be invoked under the IOMMU lock. */
-static void __iommu_flushall(struct iommu *iommu)
+static void iommu_flushall(struct iommu *iommu)
{
if (iommu->iommu_flushinv) {
iommu_write(iommu->iommu_flushinv, ~(u64)0);
@@ -83,54 +84,91 @@ static inline void iopte_make_dummy(struct iommu *iommu, iopte_t *iopte)
iopte_val(*iopte) = val;
}
-/* Based largely upon the ppc64 iommu allocator. */
-static long arena_alloc(struct iommu *iommu, unsigned long npages)
+/* Based almost entirely upon the ppc64 iommu allocator. If you use the 'handle'
+ * facility it must all be done in one pass while under the iommu lock.
+ *
+ * On sun4u platforms, we only flush the IOMMU once every time we've passed
+ * over the entire page table doing allocations. Therefore we only ever advance
+ * the hint and cannot backtrack it.
+ */
+unsigned long iommu_range_alloc(struct device *dev,
+ struct iommu *iommu,
+ unsigned long npages,
+ unsigned long *handle)
{
+ unsigned long n, end, start, limit, boundary_size;
struct iommu_arena *arena = &iommu->arena;
- unsigned long n, i, start, end, limit;
- int pass;
+ int pass = 0;
+
+ /* This allocator was derived from x86_64's bit string search */
+
+ /* Sanity check */
+ if (unlikely(npages == 0)) {
+ if (printk_ratelimit())
+ WARN_ON(1);
+ return DMA_ERROR_CODE;
+ }
+
+ if (handle && *handle)
+ start = *handle;
+ else
+ start = arena->hint;
limit = arena->limit;
- start = arena->hint;
- pass = 0;
-again:
- n = find_next_zero_bit(arena->map, limit, start);
- end = n + npages;
- if (unlikely(end >= limit)) {
+ /* The case below can happen if we have a small segment appended
+ * to a large, or when the previous alloc was at the very end of
+ * the available space. If so, go back to the beginning and flush.
+ */
+ if (start >= limit) {
+ start = 0;
+ if (iommu->flush_all)
+ iommu->flush_all(iommu);
+ }
+
+ again:
+
+ if (dev)
+ boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+ 1 << IO_PAGE_SHIFT);
+ else
+ boundary_size = ALIGN(1UL << 32, 1 << IO_PAGE_SHIFT);
+
+ n = iommu_area_alloc(arena->map, limit, start, npages, 0,
+ boundary_size >> IO_PAGE_SHIFT, 0);
+ if (n == -1) {
if (likely(pass < 1)) {
- limit = start;
+ /* First failure, rescan from the beginning. */
start = 0;
- __iommu_flushall(iommu);
+ if (iommu->flush_all)
+ iommu->flush_all(iommu);
pass++;
goto again;
} else {
- /* Scanned the whole thing, give up. */
- return -1;
+ /* Second failure, give up */
+ return DMA_ERROR_CODE;
}
}
- for (i = n; i < end; i++) {
- if (test_bit(i, arena->map)) {
- start = i + 1;
- goto again;
- }
- }
-
- for (i = n; i < end; i++)
- __set_bit(i, arena->map);
+ end = n + npages;
arena->hint = end;
+ /* Update handle for SG allocations */
+ if (handle)
+ *handle = end;
+
return n;
}
-static void arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
+void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long npages)
{
- unsigned long i;
+ struct iommu_arena *arena = &iommu->arena;
+ unsigned long entry;
- for (i = base; i < (base + npages); i++)
- __clear_bit(i, arena->map);
+ entry = (dma_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
+
+ iommu_area_free(arena->map, entry, npages);
}
int iommu_table_init(struct iommu *iommu, int tsbsize,
@@ -156,6 +194,9 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
}
iommu->arena.limit = num_tsb_entries;
+ if (tlb_type != hypervisor)
+ iommu->flush_all = iommu_flushall;
+
/* Allocate and initialize the dummy page which we
* set inactive IO PTEs to point to.
*/
@@ -192,22 +233,18 @@ out_free_map:
return -ENOMEM;
}
-static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
+static inline iopte_t *alloc_npages(struct device *dev, struct iommu *iommu,
+ unsigned long npages)
{
- long entry;
+ unsigned long entry;
- entry = arena_alloc(iommu, npages);
- if (unlikely(entry < 0))
+ entry = iommu_range_alloc(dev, iommu, npages, NULL);
+ if (unlikely(entry == DMA_ERROR_CODE))
return NULL;
return iommu->page_table + entry;
}
-static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages)
-{
- arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
-}
-
static int iommu_alloc_ctx(struct iommu *iommu)
{
int lowest = iommu->ctx_lowest_free;
@@ -258,7 +295,7 @@ static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
iommu = dev->archdata.iommu;
spin_lock_irqsave(&iommu->lock, flags);
- iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
+ iopte = alloc_npages(dev, iommu, size >> IO_PAGE_SHIFT);
spin_unlock_irqrestore(&iommu->lock, flags);
if (unlikely(iopte == NULL)) {
@@ -296,7 +333,7 @@ static void dma_4u_free_coherent(struct device *dev, size_t size,
spin_lock_irqsave(&iommu->lock, flags);
- free_npages(iommu, dvma - iommu->page_table_map_base, npages);
+ iommu_range_free(iommu, dvma, npages);
spin_unlock_irqrestore(&iommu->lock, flags);
@@ -327,7 +364,7 @@ static dma_addr_t dma_4u_map_single(struct device *dev, void *ptr, size_t sz,
npages >>= IO_PAGE_SHIFT;
spin_lock_irqsave(&iommu->lock, flags);
- base = alloc_npages(iommu, npages);
+ base = alloc_npages(dev, iommu, npages);
ctx = 0;
if (iommu->iommu_ctxflush)
ctx = iommu_alloc_ctx(iommu);
@@ -465,224 +502,219 @@ static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr,
for (i = 0; i < npages; i++)
iopte_make_dummy(iommu, base + i);
- free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
+ iommu_range_free(iommu, bus_addr, npages);
iommu_free_ctx(iommu, ctx);
spin_unlock_irqrestore(&iommu->lock, flags);
}
-#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG))))
-
-static void fill_sg(iopte_t *iopte, struct scatterlist *sg,
- int nused, int nelems,
- unsigned long iopte_protection)
-{
- struct scatterlist *dma_sg = sg;
- int i;
-
- for (i = 0; i < nused; i++) {
- unsigned long pteval = ~0UL;
- u32 dma_npages;
-
- dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) +
- dma_sg->dma_length +
- ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT;
- do {
- unsigned long offset;
- signed int len;
-
- /* If we are here, we know we have at least one
- * more page to map. So walk forward until we
- * hit a page crossing, and begin creating new
- * mappings from that spot.
- */
- for (;;) {
- unsigned long tmp;
-
- tmp = SG_ENT_PHYS_ADDRESS(sg);
- len = sg->length;
- if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) {
- pteval = tmp & IO_PAGE_MASK;
- offset = tmp & (IO_PAGE_SIZE - 1UL);
- break;
- }
- if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) {
- pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK;
- offset = 0UL;
- len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL)));
- break;
- }
- sg = sg_next(sg);
- nelems--;
- }
-
- pteval = iopte_protection | (pteval & IOPTE_PAGE);
- while (len > 0) {
- *iopte++ = __iopte(pteval);
- pteval += IO_PAGE_SIZE;
- len -= (IO_PAGE_SIZE - offset);
- offset = 0;
- dma_npages--;
- }
-
- pteval = (pteval & IOPTE_PAGE) + len;
- sg = sg_next(sg);
- nelems--;
-
- /* Skip over any tail mappings we've fully mapped,
- * adjusting pteval along the way. Stop when we
- * detect a page crossing event.
- */
- while (nelems &&
- (pteval << (64 - IO_PAGE_SHIFT)) != 0UL &&
- (pteval == SG_ENT_PHYS_ADDRESS(sg)) &&
- ((pteval ^
- (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) {
- pteval += sg->length;
- sg = sg_next(sg);
- nelems--;
- }
- if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL)
- pteval = ~0UL;
- } while (dma_npages != 0);
- dma_sg = sg_next(dma_sg);
- }
-}
-
static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- struct iommu *iommu;
+ struct scatterlist *s, *outs, *segstart;
+ unsigned long flags, handle, prot, ctx;
+ dma_addr_t dma_next = 0, dma_addr;
+ unsigned int max_seg_size;
+ int outcount, incount, i;
struct strbuf *strbuf;
- unsigned long flags, ctx, npages, iopte_protection;
- iopte_t *base;
- u32 dma_base;
- struct scatterlist *sgtmp;
- int used;
-
- /* Fast path single entry scatterlists. */
- if (nelems == 1) {
- sglist->dma_address =
- dma_4u_map_single(dev, sg_virt(sglist),
- sglist->length, direction);
- if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
- return 0;
- sglist->dma_length = sglist->length;
- return 1;
- }
+ struct iommu *iommu;
+
+ BUG_ON(direction == DMA_NONE);
iommu = dev->archdata.iommu;
strbuf = dev->archdata.stc;
-
- if (unlikely(direction == DMA_NONE))
- goto bad_no_ctx;
-
- /* Step 1: Prepare scatter list. */
-
- npages = prepare_sg(sglist, nelems);
-
- /* Step 2: Allocate a cluster and context, if necessary. */
+ if (nelems == 0 || !iommu)
+ return 0;
spin_lock_irqsave(&iommu->lock, flags);
- base = alloc_npages(iommu, npages);
ctx = 0;
if (iommu->iommu_ctxflush)
ctx = iommu_alloc_ctx(iommu);
- spin_unlock_irqrestore(&iommu->lock, flags);
+ if (strbuf->strbuf_enabled)
+ prot = IOPTE_STREAMING(ctx);
+ else
+ prot = IOPTE_CONSISTENT(ctx);
+ if (direction != DMA_TO_DEVICE)
+ prot |= IOPTE_WRITE;
+
+ outs = s = segstart = &sglist[0];
+ outcount = 1;
+ incount = nelems;
+ handle = 0;
+
+ /* Init first segment length for backout at failure */
+ outs->dma_length = 0;
+
+ max_seg_size = dma_get_max_seg_size(dev);
+ for_each_sg(sglist, s, nelems, i) {
+ unsigned long paddr, npages, entry, slen;
+ iopte_t *base;
+
+ slen = s->length;
+ /* Sanity check */
+ if (slen == 0) {
+ dma_next = 0;
+ continue;
+ }
+ /* Allocate iommu entries for that segment */
+ paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
+ npages = iommu_num_pages(paddr, slen);
+ entry = iommu_range_alloc(dev, iommu, npages, &handle);
+
+ /* Handle failure */
+ if (unlikely(entry == DMA_ERROR_CODE)) {
+ if (printk_ratelimit())
+ printk(KERN_INFO "iommu_alloc failed, iommu %p paddr %lx"
+ " npages %lx\n", iommu, paddr, npages);
+ goto iommu_map_failed;
+ }
- if (base == NULL)
- goto bad;
+ base = iommu->page_table + entry;
- dma_base = iommu->page_table_map_base +
- ((base - iommu->page_table) << IO_PAGE_SHIFT);
+ /* Convert entry to a dma_addr_t */
+ dma_addr = iommu->page_table_map_base +
+ (entry << IO_PAGE_SHIFT);
+ dma_addr |= (s->offset & ~IO_PAGE_MASK);
- /* Step 3: Normalize DMA addresses. */
- used = nelems;
+ /* Insert into HW table */
+ paddr &= IO_PAGE_MASK;
+ while (npages--) {
+ iopte_val(*base) = prot | paddr;
+ base++;
+ paddr += IO_PAGE_SIZE;
+ }
- sgtmp = sglist;
- while (used && sgtmp->dma_length) {
- sgtmp->dma_address += dma_base;
- sgtmp = sg_next(sgtmp);
- used--;
+ /* If we are in an open segment, try merging */
+ if (segstart != s) {
+ /* We cannot merge if:
+ * - allocated dma_addr isn't contiguous to previous allocation
+ */
+ if ((dma_addr != dma_next) ||
+ (outs->dma_length + s->length > max_seg_size)) {
+ /* Can't merge: create a new segment */
+ segstart = s;
+ outcount++;
+ outs = sg_next(outs);
+ } else {
+ outs->dma_length += s->length;
+ }
+ }
+
+ if (segstart == s) {
+ /* This is a new segment, fill entries */
+ outs->dma_address = dma_addr;
+ outs->dma_length = slen;
+ }
+
+ /* Calculate next page pointer for contiguous check */
+ dma_next = dma_addr + slen;
}
- used = nelems - used;
- /* Step 4: Create the mappings. */
- if (strbuf->strbuf_enabled)
- iopte_protection = IOPTE_STREAMING(ctx);
- else
- iopte_protection = IOPTE_CONSISTENT(ctx);
- if (direction != DMA_TO_DEVICE)
- iopte_protection |= IOPTE_WRITE;
+ spin_unlock_irqrestore(&iommu->lock, flags);
- fill_sg(base, sglist, used, nelems, iopte_protection);
+ if (outcount < incount) {
+ outs = sg_next(outs);
+ outs->dma_address = DMA_ERROR_CODE;
+ outs->dma_length = 0;
+ }
-#ifdef VERIFY_SG
- verify_sglist(sglist, nelems, base, npages);
-#endif
+ return outcount;
- return used;
+iommu_map_failed:
+ for_each_sg(sglist, s, nelems, i) {
+ if (s->dma_length != 0) {
+ unsigned long vaddr, npages, entry, i;
+ iopte_t *base;
+
+ vaddr = s->dma_address & IO_PAGE_MASK;
+ npages = iommu_num_pages(s->dma_address, s->dma_length);
+ iommu_range_free(iommu, vaddr, npages);
+
+ entry = (vaddr - iommu->page_table_map_base)
+ >> IO_PAGE_SHIFT;
+ base = iommu->page_table + entry;
+
+ for (i = 0; i < npages; i++)
+ iopte_make_dummy(iommu, base + i);
+
+ s->dma_address = DMA_ERROR_CODE;
+ s->dma_length = 0;
+ }
+ if (s == outs)
+ break;
+ }
+ spin_unlock_irqrestore(&iommu->lock, flags);
-bad:
- iommu_free_ctx(iommu, ctx);
-bad_no_ctx:
- if (printk_ratelimit())
- WARN_ON(1);
return 0;
}
+/* If contexts are being used, they are the same in all of the mappings
+ * we make for a particular SG.
+ */
+static unsigned long fetch_sg_ctx(struct iommu *iommu, struct scatterlist *sg)
+{
+ unsigned long ctx = 0;
+
+ if (iommu->iommu_ctxflush) {
+ iopte_t *base;
+ u32 bus_addr;
+
+ bus_addr = sg->dma_address & IO_PAGE_MASK;
+ base = iommu->page_table +
+ ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
+
+ ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+ }
+ return ctx;
+}
+
static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- struct iommu *iommu;
+ unsigned long flags, ctx;
+ struct scatterlist *sg;
struct strbuf *strbuf;
- iopte_t *base;
- unsigned long flags, ctx, i, npages;
- struct scatterlist *sg, *sgprv;
- u32 bus_addr;
+ struct iommu *iommu;
- if (unlikely(direction == DMA_NONE)) {
- if (printk_ratelimit())
- WARN_ON(1);
- }
+ BUG_ON(direction == DMA_NONE);
iommu = dev->archdata.iommu;
strbuf = dev->archdata.stc;
- bus_addr = sglist->dma_address & IO_PAGE_MASK;
-
- sgprv = NULL;
- for_each_sg(sglist, sg, nelems, i) {
- if (sg->dma_length == 0)
- break;
- sgprv = sg;
- }
+ ctx = fetch_sg_ctx(iommu, sglist);
- npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) -
- bus_addr) >> IO_PAGE_SHIFT;
+ spin_lock_irqsave(&iommu->lock, flags);
- base = iommu->page_table +
- ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
+ sg = sglist;
+ while (nelems--) {
+ dma_addr_t dma_handle = sg->dma_address;
+ unsigned int len = sg->dma_length;
+ unsigned long npages, entry;
+ iopte_t *base;
+ int i;
- spin_lock_irqsave(&iommu->lock, flags);
+ if (!len)
+ break;
+ npages = iommu_num_pages(dma_handle, len);
+ iommu_range_free(iommu, dma_handle, npages);
- /* Record the context, if any. */
- ctx = 0;
- if (iommu->iommu_ctxflush)
- ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+ entry = ((dma_handle - iommu->page_table_map_base)
+ >> IO_PAGE_SHIFT);
+ base = iommu->page_table + entry;
- /* Step 1: Kick data out of streaming buffers if necessary. */
- if (strbuf->strbuf_enabled)
- strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
+ dma_handle &= IO_PAGE_MASK;
+ if (strbuf->strbuf_enabled)
+ strbuf_flush(strbuf, iommu, dma_handle, ctx,
+ npages, direction);
- /* Step 2: Clear out the TSB entries. */
- for (i = 0; i < npages; i++)
- iopte_make_dummy(iommu, base + i);
+ for (i = 0; i < npages; i++)
+ iopte_make_dummy(iommu, base + i);
- free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
+ sg = sg_next(sg);
+ }
iommu_free_ctx(iommu, ctx);
diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c
deleted file mode 100644
index efd5dff85f6..00000000000
--- a/arch/sparc64/kernel/iommu_common.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/* $Id: iommu_common.c,v 1.9 2001/12/17 07:05:09 davem Exp $
- * iommu_common.c: UltraSparc SBUS/PCI common iommu code.
- *
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- */
-
-#include "iommu_common.h"
-
-/* You are _strongly_ advised to enable the following debugging code
- * any time you make changes to the sg code below, run it for a while
- * with filesystems mounted read-only before buying the farm... -DaveM
- */
-
-#ifdef VERIFY_SG
-static int verify_lengths(struct scatterlist *sglist, int nents, int npages)
-{
- int sg_len, dma_len;
- int i, pgcount;
- struct scatterlist *sg;
-
- sg_len = 0;
- for_each_sg(sglist, sg, nents, i)
- sg_len += sg->length;
-
- dma_len = 0;
- for_each_sg(sglist, sg, nents, i) {
- if (!sg->dma_length)
- break;
- dma_len += sg->dma_length;
- }
-
- if (sg_len != dma_len) {
- printk("verify_lengths: Error, different, sg[%d] dma[%d]\n",
- sg_len, dma_len);
- return -1;
- }
-
- pgcount = 0;
- for_each_sg(sglist, sg, nents, i) {
- unsigned long start, end;
-
- if (!sg->dma_length)
- break;
-
- start = sg->dma_address;
- start = start & IO_PAGE_MASK;
-
- end = sg->dma_address + sg->dma_length;
- end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK;
-
- pgcount += ((end - start) >> IO_PAGE_SHIFT);
- }
-
- if (pgcount != npages) {
- printk("verify_lengths: Error, page count wrong, "
- "npages[%d] pgcount[%d]\n",
- npages, pgcount);
- return -1;
- }
-
- /* This test passes... */
- return 0;
-}
-
-static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte)
-{
- struct scatterlist *sg = *__sg;
- iopte_t *iopte = *__iopte;
- u32 dlen = dma_sg->dma_length;
- u32 daddr;
- unsigned int sglen;
- unsigned long sgaddr;
-
- daddr = dma_sg->dma_address;
- sglen = sg->length;
- sgaddr = (unsigned long) sg_virt(sg);
- while (dlen > 0) {
- unsigned long paddr;
-
- /* SG and DMA_SG must begin at the same sub-page boundary. */
- if ((sgaddr & ~IO_PAGE_MASK) != (daddr & ~IO_PAGE_MASK)) {
- printk("verify_one_map: Wrong start offset "
- "sg[%08lx] dma[%08x]\n",
- sgaddr, daddr);
- nents = -1;
- goto out;
- }
-
- /* Verify the IOPTE points to the right page. */
- paddr = iopte_val(*iopte) & IOPTE_PAGE;
- if ((paddr + PAGE_OFFSET) != (sgaddr & IO_PAGE_MASK)) {
- printk("verify_one_map: IOPTE[%08lx] maps the "
- "wrong page, should be [%08lx]\n",
- iopte_val(*iopte), (sgaddr & IO_PAGE_MASK) - PAGE_OFFSET);
- nents = -1;
- goto out;
- }
-
- /* If this SG crosses a page, adjust to that next page
- * boundary and loop.
- */
- if ((sgaddr & IO_PAGE_MASK) ^ ((sgaddr + sglen - 1) & IO_PAGE_MASK)) {
- unsigned long next_page, diff;
-
- next_page = (sgaddr + IO_PAGE_SIZE) & IO_PAGE_MASK;
- diff = next_page - sgaddr;
- sgaddr += diff;
- daddr += diff;
- sglen -= diff;
- dlen -= diff;
- if (dlen > 0)
- iopte++;
- continue;
- }
-
- /* SG wholly consumed within this page. */
- daddr += sglen;
- dlen -= sglen;
-
- if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0))
- iopte++;
-
- sg = sg_next(sg);
- if (--nents <= 0)
- break;
- sgaddr = (unsigned long) sg_virt(sg);
- sglen = sg->length;
- }
- if (dlen < 0) {
- /* Transfer overrun, big problems. */
- printk("verify_one_map: Transfer overrun by %d bytes.\n",
- -dlen);
- nents = -1;
- } else {
- /* Advance to next dma_sg implies that the next iopte will
- * begin it.
- */
- iopte++;
- }
-
-out:
- *__sg = sg;
- *__iopte = iopte;
- return nents;
-}
-
-static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte)
-{
- struct scatterlist *dma_sg = sg;
- struct scatterlist *orig_dma_sg = dma_sg;
- int orig_nents = nents;
-
- for (;;) {
- nents = verify_one_map(dma_sg, &sg, nents, &iopte);
- if (nents <= 0)
- break;
- dma_sg = sg_next(dma_sg);
- if (dma_sg->dma_length == 0)
- break;
- }
-
- if (nents > 0) {
- printk("verify_maps: dma maps consumed by some sgs remain (%d)\n",
- nents);
- return -1;
- }
-
- if (nents < 0) {
- printk("verify_maps: Error, messed up mappings, "
- "at sg %d dma_sg %d\n",
- (int) (orig_nents + nents), (int) (dma_sg - orig_dma_sg));
- return -1;
- }
-
- /* This test passes... */
- return 0;
-}
-
-void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int npages)
-{
- struct scatterlist *sg;
-
- if (verify_lengths(sglist, nents, npages) < 0 ||
- verify_maps(sglist, nents, iopte) < 0) {
- int i;
-
- printk("verify_sglist: Crap, messed up mappings, dumping, iodma at ");
- printk("%016lx.\n", sglist->dma_address & IO_PAGE_MASK);
-
- for_each_sg(sglist, sg, nents, i) {
- printk("sg(%d): page_addr(%p) off(%x) length(%x) "
- "dma_address[%016x] dma_length[%016x]\n",
- i,
- page_address(sg_page(sg)), sg->offset,
- sg->length,
- sg->dma_address, sg->dma_length);
- }
- }
-
- /* Seems to be ok */
-}
-#endif
-
-unsigned long prepare_sg(struct scatterlist *sg, int nents)
-{
- struct scatterlist *dma_sg = sg;
- unsigned long prev;
- u32 dent_addr, dent_len;
-
- prev = (unsigned long) sg_virt(sg);
- prev += (unsigned long) (dent_len = sg->length);
- dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL));
- while (--nents) {
- unsigned long addr;
-
- sg = sg_next(sg);
- addr = (unsigned long) sg_virt(sg);
- if (! VCONTIG(prev, addr)) {
- dma_sg->dma_address = dent_addr;
- dma_sg->dma_length = dent_len;
- dma_sg = sg_next(dma_sg);
-
- dent_addr = ((dent_addr +
- dent_len +
- (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT);
- dent_addr <<= IO_PAGE_SHIFT;
- dent_addr += addr & (IO_PAGE_SIZE - 1UL);
- dent_len = 0;
- }
- dent_len += sg->length;
- prev = addr + sg->length;
- }
- dma_sg->dma_address = dent_addr;
- dma_sg->dma_length = dent_len;
-
- if (dma_sg != sg) {
- dma_sg = sg_next(dma_sg);
- dma_sg->dma_length = 0;
- }
-
- return ((unsigned long) dent_addr +
- (unsigned long) dent_len +
- (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT;
-}
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
index 75b5a581452..0713bd58499 100644
--- a/arch/sparc64/kernel/iommu_common.h
+++ b/arch/sparc64/kernel/iommu_common.h
@@ -1,14 +1,17 @@
-/* $Id: iommu_common.h,v 1.5 2001/12/11 09:41:01 davem Exp $
- * iommu_common.h: UltraSparc SBUS/PCI common iommu declarations.
+/* iommu_common.h: UltraSparc SBUS/PCI common iommu declarations.
*
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999, 2008 David S. Miller (davem@davemloft.net)
*/
+#ifndef _IOMMU_COMMON_H
+#define _IOMMU_COMMON_H
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
+#include <linux/device.h>
#include <asm/iommu.h>
#include <asm/scatterlist.h>
@@ -29,21 +32,38 @@
*/
#define IOMMU_PAGE_SHIFT 13
-/* You are _strongly_ advised to enable the following debugging code
- * any time you make changes to the sg code below, run it for a while
- * with filesystems mounted read-only before buying the farm... -DaveM
- */
-#undef VERIFY_SG
+#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG))))
-#ifdef VERIFY_SG
-extern void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages);
-#endif
+static inline unsigned long iommu_num_pages(unsigned long vaddr,
+ unsigned long slen)
+{
+ unsigned long npages;
-/* Two addresses are "virtually contiguous" if and only if:
- * 1) They are equal, or...
- * 2) They are both on a page boundary
- */
-#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \
- (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL)
+ npages = IO_PAGE_ALIGN(vaddr + slen) - (vaddr & IO_PAGE_MASK);
+ npages >>= IO_PAGE_SHIFT;
+
+ return npages;
+}
+
+static inline unsigned long calc_npages(struct scatterlist *sglist, int nelems)
+{
+ unsigned long i, npages = 0;
+ struct scatterlist *sg;
+
+ for_each_sg(sglist, sg, nelems, i) {
+ unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
+ npages += iommu_num_pages(paddr, sg->length);
+ }
+
+ return npages;
+}
+
+extern unsigned long iommu_range_alloc(struct device *dev,
+ struct iommu *iommu,
+ unsigned long npages,
+ unsigned long *handle);
+extern void iommu_range_free(struct iommu *iommu,
+ dma_addr_t dma_addr,
+ unsigned long npages);
-extern unsigned long prepare_sg(struct scatterlist *sg, int nents);
+#endif /* _IOMMU_COMMON_H */
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 30431bd24e1..5ec06c8c7fe 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -522,7 +522,7 @@ static struct irq_chip sun4v_virq = {
.set_affinity = sun4v_virt_set_affinity,
};
-static void fastcall pre_flow_handler(unsigned int virt_irq,
+static void pre_flow_handler(unsigned int virt_irq,
struct irq_desc *desc)
{
struct irq_handler_data *data = get_irq_chip_data(virt_irq);
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index d94f901d321..34fc3ddd500 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -480,8 +480,117 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
return 0;
}
-/* architecture specific initialization */
-int arch_init_kprobes(void)
+/* Called with kretprobe_lock held. The value stored in the return
+ * address register is actually 2 instructions before where the
+ * callee will return to. Sequences usually look something like this
+ *
+ * call some_function <--- return register points here
+ * nop <--- call delay slot
+ * whatever <--- where callee returns to
+ *
+ * To keep trampoline_probe_handler logic simpler, we normalize the
+ * value kept in ri->ret_addr so we don't need to keep adjusting it
+ * back and forth.
+ */
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
+ struct pt_regs *regs)
+{
+ ri->ret_addr = (kprobe_opcode_t *)(regs->u_regs[UREG_RETPC] + 8);
+
+ /* Replace the return addr with trampoline addr */
+ regs->u_regs[UREG_RETPC] =
+ ((unsigned long)kretprobe_trampoline) - 8;
+}
+
+/*
+ * Called when the probe at kretprobe trampoline is hit
+ */
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct kretprobe_instance *ri = NULL;
+ struct hlist_head *head, empty_rp;
+ struct hlist_node *node, *tmp;
+ unsigned long flags, orig_ret_address = 0;
+ unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
+
+ INIT_HLIST_HEAD(&empty_rp);
+ spin_lock_irqsave(&kretprobe_lock, flags);
+ head = kretprobe_inst_table_head(current);
+
+ /*
+ * It is possible to have multiple instances associated with a given
+ * task either because an multiple functions in the call path
+ * have a return probe installed on them, and/or more then one return
+ * return probe was registered for a target function.
+ *
+ * We can handle this because:
+ * - instances are always inserted at the head of the list
+ * - when multiple return probes are registered for the same
+ * function, the first instance's ret_addr will point to the
+ * real return address, and all the rest will point to
+ * kretprobe_trampoline
+ */
+ hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+ if (ri->task != current)
+ /* another task is sharing our hash bucket */
+ continue;
+
+ if (ri->rp && ri->rp->handler)
+ ri->rp->handler(ri, regs);
+
+ orig_ret_address = (unsigned long)ri->ret_addr;
+ recycle_rp_inst(ri, &empty_rp);
+
+ if (orig_ret_address != trampoline_address)
+ /*
+ * This is the real return address. Any other
+ * instances associated with this task are for
+ * other calls deeper on the call stack
+ */
+ break;
+ }
+
+ kretprobe_assert(ri, orig_ret_address, trampoline_address);
+ regs->tpc = orig_ret_address;
+ regs->tnpc = orig_ret_address + 4;
+
+ reset_current_kprobe();
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
+ preempt_enable_no_resched();
+
+ hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
+ hlist_del(&ri->hlist);
+ kfree(ri);
+ }
+ /*
+ * By returning a non-zero value, we are telling
+ * kprobe_handler() that we don't want the post_handler
+ * to run (and have re-enabled preemption)
+ */
+ return 1;
+}
+
+void kretprobe_trampoline_holder(void)
+{
+ asm volatile(".global kretprobe_trampoline\n"
+ "kretprobe_trampoline:\n"
+ "\tnop\n"
+ "\tnop\n");
+}
+static struct kprobe trampoline_p = {
+ .addr = (kprobe_opcode_t *) &kretprobe_trampoline,
+ .pre_handler = trampoline_probe_handler
+};
+
+int __init arch_init_kprobes(void)
{
+ return register_kprobe(&trampoline_p);
+}
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+ if (p->addr == (kprobe_opcode_t *)&kretprobe_trampoline)
+ return 1;
+
return 0;
}
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index fc5c0cc793b..0fd9db95b89 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -868,29 +868,3 @@ static int __init of_debug(char *str)
}
__setup("of_debug=", of_debug);
-
-struct of_device* of_platform_device_create(struct device_node *np,
- const char *bus_id,
- struct device *parent,
- struct bus_type *bus)
-{
- struct of_device *dev;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return NULL;
-
- dev->dev.parent = parent;
- dev->dev.bus = bus;
- dev->dev.release = of_release_dev;
-
- strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
-
- if (of_device_register(dev) != 0) {
- kfree(dev);
- return NULL;
- }
-
- return dev;
-}
-EXPORT_SYMBOL(of_platform_device_create);
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 1aa8e044b10..ddca6c6c0b4 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -1,6 +1,6 @@
/* pci_sun4v.c: SUN4V specific PCI controller support.
*
- * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2006, 2007, 2008 David S. Miller (davem@davemloft.net)
*/
#include <linux/kernel.h>
@@ -89,6 +89,17 @@ static long iommu_batch_flush(struct iommu_batch *p)
return 0;
}
+static inline void iommu_batch_new_entry(unsigned long entry)
+{
+ struct iommu_batch *p = &__get_cpu_var(iommu_batch);
+
+ if (p->entry + p->npages == entry)
+ return;
+ if (p->entry != ~0UL)
+ iommu_batch_flush(p);
+ p->entry = entry;
+}
+
/* Interrupts must be disabled. */
static inline long iommu_batch_add(u64 phys_page)
{
@@ -113,54 +124,6 @@ static inline long iommu_batch_end(void)
return iommu_batch_flush(p);
}
-static long arena_alloc(struct iommu_arena *arena, unsigned long npages)
-{
- unsigned long n, i, start, end, limit;
- int pass;
-
- limit = arena->limit;
- start = arena->hint;
- pass = 0;
-
-again:
- n = find_next_zero_bit(arena->map, limit, start);
- end = n + npages;
- if (unlikely(end >= limit)) {
- if (likely(pass < 1)) {
- limit = start;
- start = 0;
- pass++;
- goto again;
- } else {
- /* Scanned the whole thing, give up. */
- return -1;
- }
- }
-
- for (i = n; i < end; i++) {
- if (test_bit(i, arena->map)) {
- start = i + 1;
- goto again;
- }
- }
-
- for (i = n; i < end; i++)
- __set_bit(i, arena->map);
-
- arena->hint = end;
-
- return n;
-}
-
-static void arena_free(struct iommu_arena *arena, unsigned long base,
- unsigned long npages)
-{
- unsigned long i;
-
- for (i = base; i < (base + npages); i++)
- __clear_bit(i, arena->map);
-}
-
static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addrp, gfp_t gfp)
{
@@ -185,11 +148,11 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
iommu = dev->archdata.iommu;
spin_lock_irqsave(&iommu->lock, flags);
- entry = arena_alloc(&iommu->arena, npages);
+ entry = iommu_range_alloc(dev, iommu, npages, NULL);
spin_unlock_irqrestore(&iommu->lock, flags);
- if (unlikely(entry < 0L))
- goto arena_alloc_fail;
+ if (unlikely(entry == DMA_ERROR_CODE))
+ goto range_alloc_fail;
*dma_addrp = (iommu->page_table_map_base +
(entry << IO_PAGE_SHIFT));
@@ -219,10 +182,10 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
iommu_map_fail:
/* Interrupts are disabled. */
spin_lock(&iommu->lock);
- arena_free(&iommu->arena, entry, npages);
+ iommu_range_free(iommu, *dma_addrp, npages);
spin_unlock_irqrestore(&iommu->lock, flags);
-arena_alloc_fail:
+range_alloc_fail:
free_pages(first_page, order);
return NULL;
}
@@ -243,7 +206,7 @@ static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
spin_lock_irqsave(&iommu->lock, flags);
- arena_free(&iommu->arena, entry, npages);
+ iommu_range_free(iommu, dvma, npages);
do {
unsigned long num;
@@ -281,10 +244,10 @@ static dma_addr_t dma_4v_map_single(struct device *dev, void *ptr, size_t sz,
npages >>= IO_PAGE_SHIFT;
spin_lock_irqsave(&iommu->lock, flags);
- entry = arena_alloc(&iommu->arena, npages);
+ entry = iommu_range_alloc(dev, iommu, npages, NULL);
spin_unlock_irqrestore(&iommu->lock, flags);
- if (unlikely(entry < 0L))
+ if (unlikely(entry == DMA_ERROR_CODE))
goto bad;
bus_addr = (iommu->page_table_map_base +
@@ -319,7 +282,7 @@ bad:
iommu_map_fail:
/* Interrupts are disabled. */
spin_lock(&iommu->lock);
- arena_free(&iommu->arena, entry, npages);
+ iommu_range_free(iommu, bus_addr, npages);
spin_unlock_irqrestore(&iommu->lock, flags);
return DMA_ERROR_CODE;
@@ -350,9 +313,9 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
spin_lock_irqsave(&iommu->lock, flags);
- entry = (bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
- arena_free(&iommu->arena, entry, npages);
+ iommu_range_free(iommu, bus_addr, npages);
+ entry = (bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
do {
unsigned long num;
@@ -365,174 +328,134 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
spin_unlock_irqrestore(&iommu->lock, flags);
}
-#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG))))
-
-static long fill_sg(long entry, struct device *dev,
- struct scatterlist *sg,
- int nused, int nelems, unsigned long prot)
+static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
+ int nelems, enum dma_data_direction direction)
{
- struct scatterlist *dma_sg = sg;
- unsigned long flags;
- int i;
-
- local_irq_save(flags);
-
- iommu_batch_start(dev, prot, entry);
-
- for (i = 0; i < nused; i++) {
- unsigned long pteval = ~0UL;
- u32 dma_npages;
-
- dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) +
- dma_sg->dma_length +
- ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT;
- do {
- unsigned long offset;
- signed int len;
-
- /* If we are here, we know we have at least one
- * more page to map. So walk forward until we
- * hit a page crossing, and begin creating new
- * mappings from that spot.
- */
- for (;;) {
- unsigned long tmp;
-
- tmp = SG_ENT_PHYS_ADDRESS(sg);
- len = sg->length;
- if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) {
- pteval = tmp & IO_PAGE_MASK;
- offset = tmp & (IO_PAGE_SIZE - 1UL);
- break;
- }
- if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) {
- pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK;
- offset = 0UL;
- len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL)));
- break;
- }
- sg = sg_next(sg);
- nelems--;
- }
-
- pteval = (pteval & IOPTE_PAGE);
- while (len > 0) {
- long err;
+ struct scatterlist *s, *outs, *segstart;
+ unsigned long flags, handle, prot;
+ dma_addr_t dma_next = 0, dma_addr;
+ unsigned int max_seg_size;
+ int outcount, incount, i;
+ struct iommu *iommu;
+ long err;
- err = iommu_batch_add(pteval);
- if (unlikely(err < 0L))
- goto iommu_map_failed;
+ BUG_ON(direction == DMA_NONE);
- pteval += IO_PAGE_SIZE;
- len -= (IO_PAGE_SIZE - offset);
- offset = 0;
- dma_npages--;
- }
+ iommu = dev->archdata.iommu;
+ if (nelems == 0 || !iommu)
+ return 0;
+
+ prot = HV_PCI_MAP_ATTR_READ;
+ if (direction != DMA_TO_DEVICE)
+ prot |= HV_PCI_MAP_ATTR_WRITE;
- pteval = (pteval & IOPTE_PAGE) + len;
- sg = sg_next(sg);
- nelems--;
+ outs = s = segstart = &sglist[0];
+ outcount = 1;
+ incount = nelems;
+ handle = 0;
- /* Skip over any tail mappings we've fully mapped,
- * adjusting pteval along the way. Stop when we
- * detect a page crossing event.
- */
- while (nelems &&
- (pteval << (64 - IO_PAGE_SHIFT)) != 0UL &&
- (pteval == SG_ENT_PHYS_ADDRESS(sg)) &&
- ((pteval ^
- (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) {
- pteval += sg->length;
- sg = sg_next(sg);
- nelems--;
- }
- if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL)
- pteval = ~0UL;
- } while (dma_npages != 0);
- dma_sg = sg_next(dma_sg);
- }
+ /* Init first segment length for backout at failure */
+ outs->dma_length = 0;
- if (unlikely(iommu_batch_end() < 0L))
- goto iommu_map_failed;
+ spin_lock_irqsave(&iommu->lock, flags);
- local_irq_restore(flags);
- return 0;
+ iommu_batch_start(dev, prot, ~0UL);
-iommu_map_failed:
- local_irq_restore(flags);
- return -1L;
-}
+ max_seg_size = dma_get_max_seg_size(dev);
+ for_each_sg(sglist, s, nelems, i) {
+ unsigned long paddr, npages, entry, slen;
-static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
- int nelems, enum dma_data_direction direction)
-{
- struct iommu *iommu;
- unsigned long flags, npages, prot;
- u32 dma_base;
- struct scatterlist *sgtmp;
- long entry, err;
- int used;
-
- /* Fast path single entry scatterlists. */
- if (nelems == 1) {
- sglist->dma_address =
- dma_4v_map_single(dev, sg_virt(sglist),
- sglist->length, direction);
- if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
- return 0;
- sglist->dma_length = sglist->length;
- return 1;
- }
+ slen = s->length;
+ /* Sanity check */
+ if (slen == 0) {
+ dma_next = 0;
+ continue;
+ }
+ /* Allocate iommu entries for that segment */
+ paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
+ npages = iommu_num_pages(paddr, slen);
+ entry = iommu_range_alloc(dev, iommu, npages, &handle);
- iommu = dev->archdata.iommu;
-
- if (unlikely(direction == DMA_NONE))
- goto bad;
+ /* Handle failure */
+ if (unlikely(entry == DMA_ERROR_CODE)) {
+ if (printk_ratelimit())
+ printk(KERN_INFO "iommu_alloc failed, iommu %p paddr %lx"
+ " npages %lx\n", iommu, paddr, npages);
+ goto iommu_map_failed;
+ }
- /* Step 1: Prepare scatter list. */
- npages = prepare_sg(sglist, nelems);
+ iommu_batch_new_entry(entry);
- /* Step 2: Allocate a cluster and context, if necessary. */
- spin_lock_irqsave(&iommu->lock, flags);
- entry = arena_alloc(&iommu->arena, npages);
- spin_unlock_irqrestore(&iommu->lock, flags);
+ /* Convert entry to a dma_addr_t */
+ dma_addr = iommu->page_table_map_base +
+ (entry << IO_PAGE_SHIFT);
+ dma_addr |= (s->offset & ~IO_PAGE_MASK);
- if (unlikely(entry < 0L))
- goto bad;
+ /* Insert into HW table */
+ paddr &= IO_PAGE_MASK;
+ while (npages--) {
+ err = iommu_batch_add(paddr);
+ if (unlikely(err < 0L))
+ goto iommu_map_failed;
+ paddr += IO_PAGE_SIZE;
+ }
- dma_base = iommu->page_table_map_base +
- (entry << IO_PAGE_SHIFT);
+ /* If we are in an open segment, try merging */
+ if (segstart != s) {
+ /* We cannot merge if:
+ * - allocated dma_addr isn't contiguous to previous allocation
+ */
+ if ((dma_addr != dma_next) ||
+ (outs->dma_length + s->length > max_seg_size)) {
+ /* Can't merge: create a new segment */
+ segstart = s;
+ outcount++;
+ outs = sg_next(outs);
+ } else {
+ outs->dma_length += s->length;
+ }
+ }
- /* Step 3: Normalize DMA addresses. */
- used = nelems;
+ if (segstart == s) {
+ /* This is a new segment, fill entries */
+ outs->dma_address = dma_addr;
+ outs->dma_length = slen;
+ }
- sgtmp = sglist;
- while (used && sgtmp->dma_length) {
- sgtmp->dma_address += dma_base;
- sgtmp = sg_next(sgtmp);
- used--;
+ /* Calculate next page pointer for contiguous check */
+ dma_next = dma_addr + slen;
}
- used = nelems - used;
- /* Step 4: Create the mappings. */
- prot = HV_PCI_MAP_ATTR_READ;
- if (direction != DMA_TO_DEVICE)
- prot |= HV_PCI_MAP_ATTR_WRITE;
+ err = iommu_batch_end();
- err = fill_sg(entry, dev, sglist, used, nelems, prot);
if (unlikely(err < 0L))
goto iommu_map_failed;
- return used;
+ spin_unlock_irqrestore(&iommu->lock, flags);
-bad:
- if (printk_ratelimit())
- WARN_ON(1);
- return 0;
+ if (outcount < incount) {
+ outs = sg_next(outs);
+ outs->dma_address = DMA_ERROR_CODE;
+ outs->dma_length = 0;
+ }
+
+ return outcount;
iommu_map_failed:
- spin_lock_irqsave(&iommu->lock, flags);
- arena_free(&iommu->arena, entry, npages);
+ for_each_sg(sglist, s, nelems, i) {
+ if (s->dma_length != 0) {
+ unsigned long vaddr, npages;
+
+ vaddr = s->dma_address & IO_PAGE_MASK;
+ npages = iommu_num_pages(s->dma_address, s->dma_length);
+ iommu_range_free(iommu, vaddr, npages);
+ /* XXX demap? XXX */
+ s->dma_address = DMA_ERROR_CODE;
+ s->dma_length = 0;
+ }
+ if (s == outs)
+ break;
+ }
spin_unlock_irqrestore(&iommu->lock, flags);
return 0;
@@ -542,47 +465,42 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
struct pci_pbm_info *pbm;
+ struct scatterlist *sg;
struct iommu *iommu;
- unsigned long flags, i, npages;
- struct scatterlist *sg, *sgprv;
- long entry;
- u32 devhandle, bus_addr;
+ unsigned long flags;
+ u32 devhandle;
- if (unlikely(direction == DMA_NONE)) {
- if (printk_ratelimit())
- WARN_ON(1);
- }
+ BUG_ON(direction == DMA_NONE);
iommu = dev->archdata.iommu;
pbm = dev->archdata.host_controller;
devhandle = pbm->devhandle;
- bus_addr = sglist->dma_address & IO_PAGE_MASK;
- sgprv = NULL;
- for_each_sg(sglist, sg, nelems, i) {
- if (sg->dma_length == 0)
- break;
-
- sgprv = sg;
- }
-
- npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) -
- bus_addr) >> IO_PAGE_SHIFT;
+ spin_lock_irqsave(&iommu->lock, flags);
- entry = ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
+ sg = sglist;
+ while (nelems--) {
+ dma_addr_t dma_handle = sg->dma_address;
+ unsigned int len = sg->dma_length;
+ unsigned long npages, entry;
- spin_lock_irqsave(&iommu->lock, flags);
+ if (!len)
+ break;
+ npages = iommu_num_pages(dma_handle, len);
+ iommu_range_free(iommu, dma_handle, npages);
- arena_free(&iommu->arena, entry, npages);
+ entry = ((dma_handle - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
+ while (npages) {
+ unsigned long num;
- do {
- unsigned long num;
+ num = pci_sun4v_iommu_demap(devhandle, HV_PCI_TSBID(0, entry),
+ npages);
+ entry += num;
+ npages -= num;
+ }
- num = pci_sun4v_iommu_demap(devhandle, HV_PCI_TSBID(0, entry),
- npages);
- entry += num;
- npages -= num;
- } while (npages != 0);
+ sg = sg_next(sg);
+ }
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -625,8 +543,8 @@ static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
/* XXX register error interrupt handlers XXX */
}
-static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
- struct iommu *iommu)
+static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm,
+ struct iommu *iommu)
{
struct iommu_arena *arena = &iommu->arena;
unsigned long i, cnt = 0;
@@ -653,7 +571,7 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
return cnt;
}
-static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
+static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
{
struct iommu *iommu = pbm->iommu;
struct property *prop;
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index ca7cdfd55f7..1b237917498 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -24,7 +24,6 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/compat.h>
@@ -725,17 +724,6 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
return retval;
}
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
- /* Only should be used for SunOS and ancient a.out
- * SparcLinux binaries... Not worth implementing.
- */
- memset(dump, 0, sizeof(struct user));
-}
-
typedef struct {
union {
unsigned int pr_regs[32];
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 81111a12f0a..9a1ba1fe859 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -1,6 +1,6 @@
/* ptrace.c: Sparc process tracing support.
*
- * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
+ * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*
* Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
@@ -22,6 +22,9 @@
#include <linux/seccomp.h>
#include <linux/audit.h>
#include <linux/signal.h>
+#include <linux/regset.h>
+#include <linux/compat.h>
+#include <linux/elf.h>
#include <asm/asi.h>
#include <asm/pgtable.h>
@@ -33,70 +36,7 @@
#include <asm/page.h>
#include <asm/cpudata.h>
-/* Returning from ptrace is a bit tricky because the syscall return
- * low level code assumes any value returned which is negative and
- * is a valid errno will mean setting the condition codes to indicate
- * an error return. This doesn't work, so we have this hook.
- */
-static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
-{
- regs->u_regs[UREG_I0] = error;
- regs->tstate |= (TSTATE_ICARRY | TSTATE_XCARRY);
- regs->tpc = regs->tnpc;
- regs->tnpc += 4;
-}
-
-static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
-{
- regs->u_regs[UREG_I0] = value;
- regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
- regs->tpc = regs->tnpc;
- regs->tnpc += 4;
-}
-
-static inline void
-pt_succ_return_linux(struct pt_regs *regs, unsigned long value, void __user *addr)
-{
- if (test_thread_flag(TIF_32BIT)) {
- if (put_user(value, (unsigned int __user *) addr)) {
- pt_error_return(regs, EFAULT);
- return;
- }
- } else {
- if (put_user(value, (long __user *) addr)) {
- pt_error_return(regs, EFAULT);
- return;
- }
- }
- regs->u_regs[UREG_I0] = 0;
- regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
- regs->tpc = regs->tnpc;
- regs->tnpc += 4;
-}
-
-static void
-pt_os_succ_return (struct pt_regs *regs, unsigned long val, void __user *addr)
-{
- if (current->personality == PER_SUNOS)
- pt_succ_return (regs, val);
- else
- pt_succ_return_linux (regs, val, addr);
-}
-
/* #define ALLOW_INIT_TRACING */
-/* #define DEBUG_PTRACE */
-
-#ifdef DEBUG_PTRACE
-char *pt_rq [] = {
- /* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR",
- /* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT",
- /* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH",
- /* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS",
- /* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT",
- /* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown",
- /* 24 */ "SYSCALL", ""
-};
-#endif
/*
* Called by kernel/ptrace.c when detaching..
@@ -167,481 +107,784 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
}
}
-asmlinkage void do_ptrace(struct pt_regs *regs)
+enum sparc_regset {
+ REGSET_GENERAL,
+ REGSET_FP,
+};
+
+static int genregs64_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
{
- int request = regs->u_regs[UREG_I0];
- pid_t pid = regs->u_regs[UREG_I1];
- unsigned long addr = regs->u_regs[UREG_I2];
- unsigned long data = regs->u_regs[UREG_I3];
- unsigned long addr2 = regs->u_regs[UREG_I4];
- struct task_struct *child;
+ const struct pt_regs *regs = task_pt_regs(target);
int ret;
- if (test_thread_flag(TIF_32BIT)) {
- addr &= 0xffffffffUL;
- data &= 0xffffffffUL;
- addr2 &= 0xffffffffUL;
+ if (target == current)
+ flushw_user();
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ regs->u_regs,
+ 0, 16 * sizeof(u64));
+ if (!ret) {
+ unsigned long __user *reg_window = (unsigned long __user *)
+ (regs->u_regs[UREG_I6] + STACK_BIAS);
+ unsigned long window[16];
+
+ if (copy_from_user(window, reg_window, sizeof(window)))
+ return -EFAULT;
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ window,
+ 16 * sizeof(u64),
+ 32 * sizeof(u64));
}
- lock_kernel();
-#ifdef DEBUG_PTRACE
- {
- char *s;
- if ((request >= 0) && (request <= 24))
- s = pt_rq [request];
- else
- s = "unknown";
-
- if (request == PTRACE_POKEDATA && data == 0x91d02001){
- printk ("do_ptrace: breakpoint pid=%d, addr=%016lx addr2=%016lx\n",
- pid, addr, addr2);
- } else
- printk("do_ptrace: rq=%s(%d) pid=%d addr=%016lx data=%016lx addr2=%016lx\n",
- s, request, pid, addr, data, addr2);
+ if (!ret) {
+ /* TSTATE, TPC, TNPC */
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &regs->tstate,
+ 32 * sizeof(u64),
+ 35 * sizeof(u64));
}
-#endif
- if (request == PTRACE_TRACEME) {
- ret = ptrace_traceme();
- if (ret < 0)
- pt_error_return(regs, -ret);
- else
- pt_succ_return(regs, 0);
- goto out;
+
+ if (!ret) {
+ unsigned long y = regs->y;
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &y,
+ 35 * sizeof(u64),
+ 36 * sizeof(u64));
}
- child = ptrace_get_task_struct(pid);
- if (IS_ERR(child)) {
- ret = PTR_ERR(child);
- pt_error_return(regs, -ret);
- goto out;
+ if (!ret)
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ 36 * sizeof(u64), -1);
+
+ return ret;
+}
+
+static int genregs64_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ struct pt_regs *regs = task_pt_regs(target);
+ int ret;
+
+ if (target == current)
+ flushw_user();
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ regs->u_regs,
+ 0, 16 * sizeof(u64));
+ if (!ret && count > 0) {
+ unsigned long __user *reg_window = (unsigned long __user *)
+ (regs->u_regs[UREG_I6] + STACK_BIAS);
+ unsigned long window[16];
+
+ if (copy_from_user(window, reg_window, sizeof(window)))
+ return -EFAULT;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ window,
+ 16 * sizeof(u64),
+ 32 * sizeof(u64));
+ if (!ret &&
+ copy_to_user(reg_window, window, sizeof(window)))
+ return -EFAULT;
}
- if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
- || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
- if (ptrace_attach(child)) {
- pt_error_return(regs, EPERM);
- goto out_tsk;
+ if (!ret && count > 0) {
+ unsigned long tstate;
+
+ /* TSTATE */
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &tstate,
+ 32 * sizeof(u64),
+ 33 * sizeof(u64));
+ if (!ret) {
+ /* Only the condition codes can be modified
+ * in the %tstate register.
+ */
+ tstate &= (TSTATE_ICC | TSTATE_XCC);
+ regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
+ regs->tstate |= tstate;
}
- pt_succ_return(regs, 0);
- goto out_tsk;
}
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0) {
- pt_error_return(regs, -ret);
- goto out_tsk;
+ if (!ret) {
+ /* TPC, TNPC */
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &regs->tpc,
+ 33 * sizeof(u64),
+ 35 * sizeof(u64));
}
- if (!(test_thread_flag(TIF_32BIT)) &&
- ((request == PTRACE_READDATA64) ||
- (request == PTRACE_WRITEDATA64) ||
- (request == PTRACE_READTEXT64) ||
- (request == PTRACE_WRITETEXT64) ||
- (request == PTRACE_PEEKTEXT64) ||
- (request == PTRACE_POKETEXT64) ||
- (request == PTRACE_PEEKDATA64) ||
- (request == PTRACE_POKEDATA64))) {
- addr = regs->u_regs[UREG_G2];
- addr2 = regs->u_regs[UREG_G3];
- request -= 30; /* wheee... */
- }
+ if (!ret) {
+ unsigned long y;
- switch(request) {
- case PTRACE_PEEKUSR:
- if (addr != 0)
- pt_error_return(regs, EIO);
- else
- pt_succ_return(regs, 0);
- goto out_tsk;
-
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp64;
- unsigned int tmp32;
- int res, copied;
-
- res = -EIO;
- if (test_thread_flag(TIF_32BIT)) {
- copied = access_process_vm(child, addr,
- &tmp32, sizeof(tmp32), 0);
- tmp64 = (unsigned long) tmp32;
- if (copied == sizeof(tmp32))
- res = 0;
- } else {
- copied = access_process_vm(child, addr,
- &tmp64, sizeof(tmp64), 0);
- if (copied == sizeof(tmp64))
- res = 0;
- }
- if (res < 0)
- pt_error_return(regs, -res);
- else
- pt_os_succ_return(regs, tmp64, (void __user *) data);
- goto out_tsk;
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &y,
+ 35 * sizeof(u64),
+ 36 * sizeof(u64));
+ if (!ret)
+ regs->y = y;
}
- case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA: {
- unsigned long tmp64;
- unsigned int tmp32;
- int copied, res = -EIO;
-
- if (test_thread_flag(TIF_32BIT)) {
- tmp32 = data;
- copied = access_process_vm(child, addr,
- &tmp32, sizeof(tmp32), 1);
- if (copied == sizeof(tmp32))
- res = 0;
- } else {
- tmp64 = data;
- copied = access_process_vm(child, addr,
- &tmp64, sizeof(tmp64), 1);
- if (copied == sizeof(tmp64))
- res = 0;
- }
- if (res < 0)
- pt_error_return(regs, -res);
+ if (!ret)
+ ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 36 * sizeof(u64), -1);
+
+ return ret;
+}
+
+static int fpregs64_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ const unsigned long *fpregs = task_thread_info(target)->fpregs;
+ unsigned long fprs, fsr, gsr;
+ int ret;
+
+ if (target == current)
+ save_and_clear_fpu();
+
+ fprs = task_thread_info(target)->fpsaved[0];
+
+ if (fprs & FPRS_DL)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ fpregs,
+ 0, 16 * sizeof(u64));
+ else
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ 0,
+ 16 * sizeof(u64));
+
+ if (!ret) {
+ if (fprs & FPRS_DU)
+ ret = user_regset_copyout(&pos, &count,
+ &kbuf, &ubuf,
+ fpregs + 16,
+ 16 * sizeof(u64),
+ 32 * sizeof(u64));
else
- pt_succ_return(regs, res);
- goto out_tsk;
+ ret = user_regset_copyout_zero(&pos, &count,
+ &kbuf, &ubuf,
+ 16 * sizeof(u64),
+ 32 * sizeof(u64));
}
- case PTRACE_GETREGS: {
- struct pt_regs32 __user *pregs =
- (struct pt_regs32 __user *) addr;
- struct pt_regs *cregs = task_pt_regs(child);
- int rval;
-
- if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
- __put_user(cregs->tpc, (&pregs->pc)) ||
- __put_user(cregs->tnpc, (&pregs->npc)) ||
- __put_user(cregs->y, (&pregs->y))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
- }
- for (rval = 1; rval < 16; rval++)
- if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
- }
- pt_succ_return(regs, 0);
-#ifdef DEBUG_PTRACE
- printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
-#endif
- goto out_tsk;
+ if (fprs & FPRS_FEF) {
+ fsr = task_thread_info(target)->xfsr[0];
+ gsr = task_thread_info(target)->gsr[0];
+ } else {
+ fsr = gsr = 0;
}
- case PTRACE_GETREGS64: {
- struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
- struct pt_regs *cregs = task_pt_regs(child);
- unsigned long tpc = cregs->tpc;
- int rval;
-
- if ((task_thread_info(child)->flags & _TIF_32BIT) != 0)
- tpc &= 0xffffffff;
- if (__put_user(cregs->tstate, (&pregs->tstate)) ||
- __put_user(tpc, (&pregs->tpc)) ||
- __put_user(cregs->tnpc, (&pregs->tnpc)) ||
- __put_user(cregs->y, (&pregs->y))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
- }
- for (rval = 1; rval < 16; rval++)
- if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
- }
- pt_succ_return(regs, 0);
-#ifdef DEBUG_PTRACE
- printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
-#endif
- goto out_tsk;
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &fsr,
+ 32 * sizeof(u64),
+ 33 * sizeof(u64));
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &gsr,
+ 33 * sizeof(u64),
+ 34 * sizeof(u64));
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &fprs,
+ 34 * sizeof(u64),
+ 35 * sizeof(u64));
+
+ if (!ret)
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ 35 * sizeof(u64), -1);
+
+ return ret;
+}
+
+static int fpregs64_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ unsigned long *fpregs = task_thread_info(target)->fpregs;
+ unsigned long fprs;
+ int ret;
+
+ if (target == current)
+ save_and_clear_fpu();
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ fpregs,
+ 0, 32 * sizeof(u64));
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ task_thread_info(target)->xfsr,
+ 32 * sizeof(u64),
+ 33 * sizeof(u64));
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ task_thread_info(target)->gsr,
+ 33 * sizeof(u64),
+ 34 * sizeof(u64));
+
+ fprs = task_thread_info(target)->fpsaved[0];
+ if (!ret && count > 0) {
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &fprs,
+ 34 * sizeof(u64),
+ 35 * sizeof(u64));
}
- case PTRACE_SETREGS: {
- struct pt_regs32 __user *pregs =
- (struct pt_regs32 __user *) addr;
- struct pt_regs *cregs = task_pt_regs(child);
- unsigned int psr, pc, npc, y;
- int i;
-
- /* Must be careful, tracing process can only set certain
- * bits in the psr.
- */
- if (__get_user(psr, (&pregs->psr)) ||
- __get_user(pc, (&pregs->pc)) ||
- __get_user(npc, (&pregs->npc)) ||
- __get_user(y, (&pregs->y))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
+ fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU);
+ task_thread_info(target)->fpsaved[0] = fprs;
+
+ if (!ret)
+ ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 35 * sizeof(u64), -1);
+ return ret;
+}
+
+static const struct user_regset sparc64_regsets[] = {
+ /* Format is:
+ * G0 --> G7
+ * O0 --> O7
+ * L0 --> L7
+ * I0 --> I7
+ * TSTATE, TPC, TNPC, Y
+ */
+ [REGSET_GENERAL] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = 36 * sizeof(u64),
+ .size = sizeof(u64), .align = sizeof(u64),
+ .get = genregs64_get, .set = genregs64_set
+ },
+ /* Format is:
+ * F0 --> F63
+ * FSR
+ * GSR
+ * FPRS
+ */
+ [REGSET_FP] = {
+ .core_note_type = NT_PRFPREG,
+ .n = 35 * sizeof(u64),
+ .size = sizeof(u64), .align = sizeof(u64),
+ .get = fpregs64_get, .set = fpregs64_set
+ },
+};
+
+static const struct user_regset_view user_sparc64_view = {
+ .name = "sparc64", .e_machine = EM_SPARCV9,
+ .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
+};
+
+static int genregs32_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ const struct pt_regs *regs = task_pt_regs(target);
+ compat_ulong_t __user *reg_window;
+ compat_ulong_t *k = kbuf;
+ compat_ulong_t __user *u = ubuf;
+ compat_ulong_t reg;
+
+ if (target == current)
+ flushw_user();
+
+ pos /= sizeof(reg);
+ count /= sizeof(reg);
+
+ if (kbuf) {
+ for (; count > 0 && pos < 16; count--)
+ *k++ = regs->u_regs[pos++];
+
+ reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
+ for (; count > 0 && pos < 32; count--) {
+ if (get_user(*k++, &reg_window[pos++]))
+ return -EFAULT;
}
- cregs->tstate &= ~(TSTATE_ICC);
- cregs->tstate |= psr_to_tstate_icc(psr);
- if (!((pc | npc) & 3)) {
- cregs->tpc = pc;
- cregs->tnpc = npc;
+ } else {
+ for (; count > 0 && pos < 16; count--) {
+ if (put_user((compat_ulong_t) regs->u_regs[pos++], u++))
+ return -EFAULT;
}
- cregs->y = y;
- for (i = 1; i < 16; i++) {
- if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
- }
+
+ reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
+ for (; count > 0 && pos < 32; count--) {
+ if (get_user(reg, &reg_window[pos++]) ||
+ put_user(reg, u++))
+ return -EFAULT;
+ }
+ }
+ while (count > 0) {
+ switch (pos) {
+ case 32: /* PSR */
+ reg = tstate_to_psr(regs->tstate);
+ break;
+ case 33: /* PC */
+ reg = regs->tpc;
+ break;
+ case 34: /* NPC */
+ reg = regs->tnpc;
+ break;
+ case 35: /* Y */
+ reg = regs->y;
+ break;
+ case 36: /* WIM */
+ case 37: /* TBR */
+ reg = 0;
+ break;
+ default:
+ goto finish;
}
- pt_succ_return(regs, 0);
- goto out_tsk;
+
+ if (kbuf)
+ *k++ = reg;
+ else if (put_user(reg, u++))
+ return -EFAULT;
+ pos++;
+ count--;
}
+finish:
+ pos *= sizeof(reg);
+ count *= sizeof(reg);
+
+ return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ 38 * sizeof(reg), -1);
+}
- case PTRACE_SETREGS64: {
- struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
- struct pt_regs *cregs = task_pt_regs(child);
- unsigned long tstate, tpc, tnpc, y;
- int i;
-
- /* Must be careful, tracing process can only set certain
- * bits in the psr.
- */
- if (__get_user(tstate, (&pregs->tstate)) ||
- __get_user(tpc, (&pregs->tpc)) ||
- __get_user(tnpc, (&pregs->tnpc)) ||
- __get_user(y, (&pregs->y))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
+static int genregs32_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ struct pt_regs *regs = task_pt_regs(target);
+ compat_ulong_t __user *reg_window;
+ const compat_ulong_t *k = kbuf;
+ const compat_ulong_t __user *u = ubuf;
+ compat_ulong_t reg;
+
+ if (target == current)
+ flushw_user();
+
+ pos /= sizeof(reg);
+ count /= sizeof(reg);
+
+ if (kbuf) {
+ for (; count > 0 && pos < 16; count--)
+ regs->u_regs[pos++] = *k++;
+
+ reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
+ for (; count > 0 && pos < 32; count--) {
+ if (put_user(*k++, &reg_window[pos++]))
+ return -EFAULT;
}
- if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) {
- tpc &= 0xffffffff;
- tnpc &= 0xffffffff;
+ } else {
+ for (; count > 0 && pos < 16; count--) {
+ if (get_user(reg, u++))
+ return -EFAULT;
+ regs->u_regs[pos++] = reg;
}
- tstate &= (TSTATE_ICC | TSTATE_XCC);
- cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
- cregs->tstate |= tstate;
- if (!((tpc | tnpc) & 3)) {
- cregs->tpc = tpc;
- cregs->tnpc = tnpc;
+
+ reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
+ for (; count > 0 && pos < 32; count--) {
+ if (get_user(reg, u++) ||
+ put_user(reg, &reg_window[pos++]))
+ return -EFAULT;
}
- cregs->y = y;
- for (i = 1; i < 16; i++) {
- if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
- }
+ }
+ while (count > 0) {
+ unsigned long tstate;
+
+ if (kbuf)
+ reg = *k++;
+ else if (get_user(reg, u++))
+ return -EFAULT;
+
+ switch (pos) {
+ case 32: /* PSR */
+ tstate = regs->tstate;
+ tstate &= ~(TSTATE_ICC | TSTATE_XCC);
+ tstate |= psr_to_tstate_icc(reg);
+ regs->tstate = tstate;
+ break;
+ case 33: /* PC */
+ regs->tpc = reg;
+ break;
+ case 34: /* NPC */
+ regs->tnpc = reg;
+ break;
+ case 35: /* Y */
+ regs->y = reg;
+ break;
+ case 36: /* WIM */
+ case 37: /* TBR */
+ break;
+ default:
+ goto finish;
}
- pt_succ_return(regs, 0);
- goto out_tsk;
+
+ pos++;
+ count--;
}
+finish:
+ pos *= sizeof(reg);
+ count *= sizeof(reg);
- case PTRACE_GETFPREGS: {
- struct fps {
- unsigned int regs[32];
- unsigned int fsr;
- unsigned int flags;
- unsigned int extra;
- unsigned int fpqd;
- struct fq {
- unsigned int insnaddr;
- unsigned int insn;
- } fpq[16];
- };
- struct fps __user *fps = (struct fps __user *) addr;
- unsigned long *fpregs = task_thread_info(child)->fpregs;
-
- if (copy_to_user(&fps->regs[0], fpregs,
- (32 * sizeof(unsigned int))) ||
- __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) ||
- __put_user(0, (&fps->fpqd)) ||
- __put_user(0, (&fps->flags)) ||
- __put_user(0, (&fps->extra)) ||
- clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
- }
- pt_succ_return(regs, 0);
- goto out_tsk;
+ return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 38 * sizeof(reg), -1);
+}
+
+static int fpregs32_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ const unsigned long *fpregs = task_thread_info(target)->fpregs;
+ compat_ulong_t enabled;
+ unsigned long fprs;
+ compat_ulong_t fsr;
+ int ret = 0;
+
+ if (target == current)
+ save_and_clear_fpu();
+
+ fprs = task_thread_info(target)->fpsaved[0];
+ if (fprs & FPRS_FEF) {
+ fsr = task_thread_info(target)->xfsr[0];
+ enabled = 1;
+ } else {
+ fsr = 0;
+ enabled = 0;
}
- case PTRACE_GETFPREGS64: {
- struct fps {
- unsigned int regs[64];
- unsigned long fsr;
- };
- struct fps __user *fps = (struct fps __user *) addr;
- unsigned long *fpregs = task_thread_info(child)->fpregs;
-
- if (copy_to_user(&fps->regs[0], fpregs,
- (64 * sizeof(unsigned int))) ||
- __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
- }
- pt_succ_return(regs, 0);
- goto out_tsk;
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ fpregs,
+ 0, 32 * sizeof(u32));
+
+ if (!ret)
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ 32 * sizeof(u32),
+ 33 * sizeof(u32));
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &fsr,
+ 33 * sizeof(u32),
+ 34 * sizeof(u32));
+
+ if (!ret) {
+ compat_ulong_t val;
+
+ val = (enabled << 8) | (8 << 16);
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &val,
+ 34 * sizeof(u32),
+ 35 * sizeof(u32));
}
- case PTRACE_SETFPREGS: {
- struct fps {
- unsigned int regs[32];
- unsigned int fsr;
- unsigned int flags;
- unsigned int extra;
- unsigned int fpqd;
- struct fq {
- unsigned int insnaddr;
- unsigned int insn;
- } fpq[16];
- };
- struct fps __user *fps = (struct fps __user *) addr;
- unsigned long *fpregs = task_thread_info(child)->fpregs;
- unsigned fsr;
-
- if (copy_from_user(fpregs, &fps->regs[0],
- (32 * sizeof(unsigned int))) ||
- __get_user(fsr, (&fps->fsr))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
+ if (!ret)
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ 35 * sizeof(u32), -1);
+
+ return ret;
+}
+
+static int fpregs32_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ unsigned long *fpregs = task_thread_info(target)->fpregs;
+ unsigned long fprs;
+ int ret;
+
+ if (target == current)
+ save_and_clear_fpu();
+
+ fprs = task_thread_info(target)->fpsaved[0];
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ fpregs,
+ 0, 32 * sizeof(u32));
+ if (!ret)
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 32 * sizeof(u32),
+ 33 * sizeof(u32));
+ if (!ret && count > 0) {
+ compat_ulong_t fsr;
+ unsigned long val;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &fsr,
+ 33 * sizeof(u32),
+ 34 * sizeof(u32));
+ if (!ret) {
+ val = task_thread_info(target)->xfsr[0];
+ val &= 0xffffffff00000000UL;
+ val |= fsr;
+ task_thread_info(target)->xfsr[0] = val;
}
- task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL;
- task_thread_info(child)->xfsr[0] |= fsr;
- if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
- task_thread_info(child)->gsr[0] = 0;
- task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
- pt_succ_return(regs, 0);
- goto out_tsk;
}
- case PTRACE_SETFPREGS64: {
- struct fps {
- unsigned int regs[64];
- unsigned long fsr;
- };
- struct fps __user *fps = (struct fps __user *) addr;
- unsigned long *fpregs = task_thread_info(child)->fpregs;
-
- if (copy_from_user(fpregs, &fps->regs[0],
- (64 * sizeof(unsigned int))) ||
- __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) {
- pt_error_return(regs, EFAULT);
- goto out_tsk;
+ fprs |= (FPRS_FEF | FPRS_DL);
+ task_thread_info(target)->fpsaved[0] = fprs;
+
+ if (!ret)
+ ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 34 * sizeof(u32), -1);
+ return ret;
+}
+
+static const struct user_regset sparc32_regsets[] = {
+ /* Format is:
+ * G0 --> G7
+ * O0 --> O7
+ * L0 --> L7
+ * I0 --> I7
+ * PSR, PC, nPC, Y, WIM, TBR
+ */
+ [REGSET_GENERAL] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = 38 * sizeof(u32),
+ .size = sizeof(u32), .align = sizeof(u32),
+ .get = genregs32_get, .set = genregs32_set
+ },
+ /* Format is:
+ * F0 --> F31
+ * empty 32-bit word
+ * FSR (32--bit word)
+ * FPU QUEUE COUNT (8-bit char)
+ * FPU QUEUE ENTRYSIZE (8-bit char)
+ * FPU ENABLED (8-bit char)
+ * empty 8-bit char
+ * FPU QUEUE (64 32-bit ints)
+ */
+ [REGSET_FP] = {
+ .core_note_type = NT_PRFPREG,
+ .n = 99 * sizeof(u32),
+ .size = sizeof(u32), .align = sizeof(u32),
+ .get = fpregs32_get, .set = fpregs32_set
+ },
+};
+
+static const struct user_regset_view user_sparc32_view = {
+ .name = "sparc", .e_machine = EM_SPARC,
+ .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+ if (test_tsk_thread_flag(task, TIF_32BIT))
+ return &user_sparc32_view;
+ return &user_sparc64_view;
+}
+
+struct compat_fps {
+ unsigned int regs[32];
+ unsigned int fsr;
+ unsigned int flags;
+ unsigned int extra;
+ unsigned int fpqd;
+ struct compat_fq {
+ unsigned int insnaddr;
+ unsigned int insn;
+ } fpq[16];
+};
+
+long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+ compat_ulong_t caddr, compat_ulong_t cdata)
+{
+ const struct user_regset_view *view = task_user_regset_view(child);
+ compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4];
+ struct pt_regs32 __user *pregs;
+ struct compat_fps __user *fps;
+ unsigned long addr2 = caddr2;
+ unsigned long addr = caddr;
+ unsigned long data = cdata;
+ int ret;
+
+ pregs = (struct pt_regs32 __user *) addr;
+ fps = (struct compat_fps __user *) addr;
+
+ switch (request) {
+ case PTRACE_PEEKUSR:
+ ret = (addr != 0) ? -EIO : 0;
+ break;
+
+ case PTRACE_GETREGS:
+ ret = copy_regset_to_user(child, view, REGSET_GENERAL,
+ 32 * sizeof(u32),
+ 4 * sizeof(u32),
+ &pregs->psr);
+ if (!ret)
+ ret = copy_regset_to_user(child, view, REGSET_GENERAL,
+ 1 * sizeof(u32),
+ 15 * sizeof(u32),
+ &pregs->u_regs[0]);
+ break;
+
+ case PTRACE_SETREGS:
+ ret = copy_regset_from_user(child, view, REGSET_GENERAL,
+ 32 * sizeof(u32),
+ 4 * sizeof(u32),
+ &pregs->psr);
+ if (!ret)
+ ret = copy_regset_from_user(child, view, REGSET_GENERAL,
+ 1 * sizeof(u32),
+ 15 * sizeof(u32),
+ &pregs->u_regs[0]);
+ break;
+
+ case PTRACE_GETFPREGS:
+ ret = copy_regset_to_user(child, view, REGSET_FP,
+ 0 * sizeof(u32),
+ 32 * sizeof(u32),
+ &fps->regs[0]);
+ if (!ret)
+ ret = copy_regset_to_user(child, view, REGSET_FP,
+ 33 * sizeof(u32),
+ 1 * sizeof(u32),
+ &fps->fsr);
+ if (!ret) {
+ if (__put_user(0, &fps->flags) ||
+ __put_user(0, &fps->extra) ||
+ __put_user(0, &fps->fpqd) ||
+ clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
+ ret = -EFAULT;
}
- if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
- task_thread_info(child)->gsr[0] = 0;
- task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
+ break;
+
+ case PTRACE_SETFPREGS:
+ ret = copy_regset_from_user(child, view, REGSET_FP,
+ 0 * sizeof(u32),
+ 32 * sizeof(u32),
+ &fps->regs[0]);
+ if (!ret)
+ ret = copy_regset_from_user(child, view, REGSET_FP,
+ 33 * sizeof(u32),
+ 1 * sizeof(u32),
+ &fps->fsr);
+ break;
case PTRACE_READTEXT:
- case PTRACE_READDATA: {
- int res = ptrace_readdata(child, addr,
- (char __user *)addr2, data);
- if (res == data) {
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
- if (res >= 0)
- res = -EIO;
- pt_error_return(regs, -res);
- goto out_tsk;
- }
+ case PTRACE_READDATA:
+ ret = ptrace_readdata(child, addr,
+ (char __user *)addr2, data);
+ if (ret == data)
+ ret = 0;
+ else if (ret >= 0)
+ ret = -EIO;
+ break;
case PTRACE_WRITETEXT:
- case PTRACE_WRITEDATA: {
- int res = ptrace_writedata(child, (char __user *) addr2,
- addr, data);
- if (res == data) {
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
- if (res >= 0)
- res = -EIO;
- pt_error_return(regs, -res);
- goto out_tsk;
+ case PTRACE_WRITEDATA:
+ ret = ptrace_writedata(child, (char __user *) addr2,
+ addr, data);
+ if (ret == data)
+ ret = 0;
+ else if (ret >= 0)
+ ret = -EIO;
+ break;
+
+ default:
+ ret = compat_ptrace_request(child, request, addr, data);
+ break;
}
- case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
- addr = 1;
- case PTRACE_CONT: { /* restart after signal. */
- if (!valid_signal(data)) {
- pt_error_return(regs, EIO);
- goto out_tsk;
- }
+ return ret;
+}
- if (request == PTRACE_SYSCALL) {
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- } else {
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
+struct fps {
+ unsigned int regs[64];
+ unsigned long fsr;
+};
- child->exit_code = data;
-#ifdef DEBUG_PTRACE
- printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm,
- child->pid, child->exit_code,
- task_pt_regs(child)->tpc,
- task_pt_regs(child)->tnpc);
-
-#endif
- wake_up_process(child);
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+{
+ const struct user_regset_view *view = task_user_regset_view(child);
+ struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
+ unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
+ struct fps __user *fps = (struct fps __user *) addr;
+ int ret;
-/*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL: {
- if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
- pt_succ_return(regs, 0);
- goto out_tsk;
+ switch (request) {
+ case PTRACE_PEEKUSR:
+ ret = (addr != 0) ? -EIO : 0;
+ break;
+
+ case PTRACE_GETREGS64:
+ ret = copy_regset_to_user(child, view, REGSET_GENERAL,
+ 1 * sizeof(u64),
+ 15 * sizeof(u64),
+ &pregs->u_regs[0]);
+ if (!ret) {
+ /* XXX doesn't handle 'y' register correctly XXX */
+ ret = copy_regset_to_user(child, view, REGSET_GENERAL,
+ 32 * sizeof(u64),
+ 4 * sizeof(u64),
+ &pregs->tstate);
}
- child->exit_code = SIGKILL;
- wake_up_process(child);
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
+ break;
- case PTRACE_SUNDETACH: { /* detach a process that was attached. */
- int error = ptrace_detach(child, data);
- if (error) {
- pt_error_return(regs, EIO);
- goto out_tsk;
+ case PTRACE_SETREGS64:
+ ret = copy_regset_from_user(child, view, REGSET_GENERAL,
+ 1 * sizeof(u64),
+ 15 * sizeof(u64),
+ &pregs->u_regs[0]);
+ if (!ret) {
+ /* XXX doesn't handle 'y' register correctly XXX */
+ ret = copy_regset_from_user(child, view, REGSET_GENERAL,
+ 32 * sizeof(u64),
+ 4 * sizeof(u64),
+ &pregs->tstate);
}
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
+ break;
- /* PTRACE_DUMPCORE unsupported... */
+ case PTRACE_GETFPREGS64:
+ ret = copy_regset_to_user(child, view, REGSET_FP,
+ 0 * sizeof(u64),
+ 33 * sizeof(u64),
+ fps);
+ break;
- case PTRACE_GETEVENTMSG: {
- int err;
+ case PTRACE_SETFPREGS64:
+ ret = copy_regset_to_user(child, view, REGSET_FP,
+ 0 * sizeof(u64),
+ 33 * sizeof(u64),
+ fps);
+ break;
- if (test_thread_flag(TIF_32BIT))
- err = put_user(child->ptrace_message,
- (unsigned int __user *) data);
- else
- err = put_user(child->ptrace_message,
- (unsigned long __user *) data);
- if (err)
- pt_error_return(regs, -err);
- else
- pt_succ_return(regs, 0);
+ case PTRACE_READTEXT:
+ case PTRACE_READDATA:
+ ret = ptrace_readdata(child, addr,
+ (char __user *)addr2, data);
+ if (ret == data)
+ ret = 0;
+ else if (ret >= 0)
+ ret = -EIO;
break;
- }
- default: {
- int err = ptrace_request(child, request, addr, data);
- if (err)
- pt_error_return(regs, -err);
- else
- pt_succ_return(regs, 0);
- goto out_tsk;
- }
+ case PTRACE_WRITETEXT:
+ case PTRACE_WRITEDATA:
+ ret = ptrace_writedata(child, (char __user *) addr2,
+ addr, data);
+ if (ret == data)
+ ret = 0;
+ else if (ret >= 0)
+ ret = -EIO;
+ break;
+
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
}
-out_tsk:
- if (child)
- put_task_struct(child);
-out:
- unlock_kernel();
+
+ return ret;
}
asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index a813441b358..5964d8653ad 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -15,7 +15,6 @@
#include <linux/slab.h>
#include <asm/smp.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/screen_info.h>
#include <linux/delay.h>
#include <linux/fs.h>
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index c39944927f1..a8052b76df4 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -46,8 +46,6 @@
#include <asm/ldc.h>
#include <asm/hypervisor.h>
-extern void calibrate_delay(void);
-
int sparc64_multi_core __read_mostly;
cpumask_t cpu_possible_map __read_mostly = CPU_MASK_NONE;
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 60765e314bd..68db0893039 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -53,7 +53,6 @@
#include <asm/ebus.h>
#include <asm/isa.h>
#endif
-#include <asm/a.out.h>
#include <asm/ns87303.h>
#include <asm/timer.h>
#include <asm/cpudata.h>
@@ -277,6 +276,7 @@ EXPORT_SYMBOL(sys_getpid);
EXPORT_SYMBOL(sys_geteuid);
EXPORT_SYMBOL(sys_getuid);
EXPORT_SYMBOL(sys_getegid);
+EXPORT_SYMBOL(sysctl_nr_open);
EXPORT_SYMBOL(sys_getgid);
EXPORT_SYMBOL(svr4_getcontext);
EXPORT_SYMBOL(svr4_setcontext);
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index c56573a10ee..134d801579f 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -28,7 +28,6 @@
#include <asm/uaccess.h>
#include <asm/utrap.h>
#include <asm/perfctr.h>
-#include <asm/a.out.h>
#include <asm/unistd.h>
/* #define DEBUG_UNIMP_SYSCALL */
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 98c468803ce..deaba2bd053 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -57,7 +57,6 @@
#include <asm/fpumacro.h>
#include <asm/semaphore.h>
#include <asm/mmu_context.h>
-#include <asm/a.out.h>
#include <asm/compat_signal.h>
asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group)
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 06d10907d8c..6b9b718e24a 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -23,7 +23,7 @@ sys_call_table32:
/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod
/*15*/ .word sys_chmod, sys32_lchown16, sparc_brk, sys32_perfctr, sys32_lseek
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16
-/*25*/ .word sys32_vmsplice, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
+/*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
/*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
.word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile
/*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid
@@ -80,7 +80,8 @@ sys_call_table32:
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
-/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, compat_sys_timerfd, sys_eventfd, compat_sys_fallocate
+/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate
+ .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime
#endif /* CONFIG_COMPAT */
@@ -152,7 +153,8 @@ sys_call_table:
.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
/*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate
+/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
+ .word sys_timerfd_settime, sys_timerfd_gettime
#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
defined(CONFIG_SOLARIS_EMUL_MODULE)
@@ -271,6 +273,7 @@ sunos_sys_table:
.word sunos_nosys, sunos_nosys, sunos_nosys
.word sunos_nosys
/*310*/ .word sunos_nosys, sunos_nosys, sunos_nosys
- .word sunos_nosys, sunos_nosys
+ .word sunos_nosys, sunos_nosys, sunos_nosys
+ .word sunos_nosys
#endif
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 4352ee4d8da..d204f1ab1d4 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -1707,6 +1707,11 @@ static void __exit rtc_mini_exit(void)
misc_deregister(&rtc_mini_dev);
}
+int __devinit read_current_timer(unsigned long *timer_val)
+{
+ *timer_val = tick_ops->get_tick();
+ return 0;
+}
module_init(rtc_mini_init);
module_exit(rtc_mini_exit);
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 523e993ee90..e726c45645f 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -997,7 +997,7 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
prom_printf("reserve_bootmem(initrd): base[%llx] size[%lx]\n",
initrd_start, initrd_end);
#endif
- reserve_bootmem(initrd_start, size);
+ reserve_bootmem(initrd_start, size, BOOTMEM_DEFAULT);
initrd_start += PAGE_OFFSET;
initrd_end += PAGE_OFFSET;
@@ -1007,7 +1007,7 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
#ifdef CONFIG_DEBUG_BOOTMEM
prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", kern_base, kern_size);
#endif
- reserve_bootmem(kern_base, kern_size);
+ reserve_bootmem(kern_base, kern_size, BOOTMEM_DEFAULT);
*pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT;
/* Add back in the initmem pages. */
@@ -1024,7 +1024,7 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
prom_printf("reserve_bootmem(bootmap): base[%lx] size[%lx]\n",
(bootmap_pfn << PAGE_SHIFT), size);
#endif
- reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size);
+ reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size, BOOTMEM_DEFAULT);
for (i = 0; i < pavail_ents; i++) {
unsigned long start_pfn, end_pfn;
@@ -1489,7 +1489,7 @@ static void __init taint_real_pages(void)
goto do_next_page;
}
}
- reserve_bootmem(old_start, PAGE_SIZE);
+ reserve_bootmem(old_start, PAGE_SIZE, BOOTMEM_DEFAULT);
do_next_page:
old_start += PAGE_SIZE;
diff --git a/arch/sparc64/prom/init.c b/arch/sparc64/prom/init.c
index 1c0db842a6f..87e7c7ea0ee 100644
--- a/arch/sparc64/prom/init.c
+++ b/arch/sparc64/prom/init.c
@@ -48,7 +48,10 @@ void __init prom_init(void *cif_handler, void *cif_stack)
prom_getstring(node, "version", prom_version, sizeof(prom_version));
prom_printf("\n");
+}
+void __init prom_init_report(void)
+{
printk("PROMLIB: Sun IEEE Boot Prom '%s'\n", prom_version);
printk("PROMLIB: Root node compatible: %s\n", prom_root_compatible);
}
diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
index 61be597bf43..7d035f0d3ae 100644
--- a/arch/sparc64/solaris/fs.c
+++ b/arch/sparc64/solaris/fs.c
@@ -434,9 +434,9 @@ asmlinkage int solaris_statvfs(u32 path, u32 buf)
error = user_path_walk(A(path),&nd);
if (!error) {
- struct inode * inode = nd.dentry->d_inode;
- error = report_statvfs(nd.mnt, inode, buf);
- path_release(&nd);
+ struct inode *inode = nd.path.dentry->d_inode;
+ error = report_statvfs(nd.path.mnt, inode, buf);
+ path_put(&nd.path);
}
return error;
}
@@ -464,9 +464,9 @@ asmlinkage int solaris_statvfs64(u32 path, u32 buf)
lock_kernel();
error = user_path_walk(A(path), &nd);
if (!error) {
- struct inode * inode = nd.dentry->d_inode;
- error = report_statvfs64(nd.mnt, inode, buf);
- path_release(&nd);
+ struct inode *inode = nd.path.dentry->d_inode;
+ error = report_statvfs64(nd.path.mnt, inode, buf);
+ path_put(&nd.path);
}
unlock_kernel();
return error;
@@ -624,7 +624,7 @@ asmlinkage int solaris_ulimit(int cmd, int val)
case 3: /* UL_GMEMLIM */
return current->signal->rlim[RLIMIT_DATA].rlim_cur;
case 4: /* UL_GDESLIM */
- return NR_OPEN;
+ return sysctl_nr_open;
}
return -EINVAL;
}
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index c86cb3091a8..d3e48e9701b 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -415,7 +415,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
switch (cmd) {
case 0: /* getpgrp */
- return task_pgrp_nr(current);
+ return task_pgrp_vnr(current);
case 1: /* setpgrp */
{
int (*sys_setpgid)(pid_t,pid_t) =
@@ -426,7 +426,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
ret = sys_setpgid(0, 0);
if (ret) return ret;
proc_clear_tty(current);
- return task_pgrp_nr(current);
+ return task_pgrp_vnr(current);
}
case 2: /* getsid */
{
diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
index a9d32ceabf2..f53123c02c2 100644
--- a/arch/sparc64/solaris/timod.c
+++ b/arch/sparc64/solaris/timod.c
@@ -859,7 +859,8 @@ asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
SOLD("entry");
lock_kernel();
- if(fd >= NR_OPEN) goto out;
+ if (fd >= sysctl_nr_open)
+ goto out;
fdt = files_fdtable(current->files);
filp = fdt->fd[fd];
@@ -927,7 +928,8 @@ asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
SOLD("entry");
lock_kernel();
- if(fd >= NR_OPEN) goto out;
+ if (fd >= sysctl_nr_open)
+ goto out;
fdt = files_fdtable(current->files);
filp = fdt->fd[fd];
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 55945db1313..dba8e05f028 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -68,6 +68,10 @@ config IRQ_RELEASE_METHOD
bool
default y
+config HZ
+ int
+ default 100
+
menu "UML-specific options"
config STATIC_LINK
@@ -95,23 +99,6 @@ config LD_SCRIPT_DYN
default y
depends on !LD_SCRIPT_STATIC
-config NET
- bool "Networking support"
- help
- Unless you really know what you are doing, you should say Y here.
- The reason is that some programs need kernel networking support even
- when running on a stand-alone machine that isn't connected to any
- other computer. If you are upgrading from an older kernel, you
- should consider updating your networking tools too because changes
- in the kernel and the tools often go hand in hand. The tools are
- contained in the package net-tools, the location and version number
- of which are given in <file:Documentation/Changes>.
-
- For a general introduction to Linux networking, it is highly
- recommended to read the NET-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
-
source "fs/Kconfig.binfmt"
config HOSTFS
@@ -145,7 +132,7 @@ config HPPFS
by removing or changing anything in /proc which gives away the
identity of a UML.
- See <http://user-mode-linux.sf.net/hppfs.html> for more information.
+ See <http://user-mode-linux.sf.net/old/hppfs.html> for more information.
You only need this if you are setting up a UML honeypot. Otherwise,
it is safe to say 'N' here.
@@ -189,8 +176,7 @@ config MAGIC_SYSRQ
config SMP
bool "Symmetric multi-processing support (EXPERIMENTAL)"
default n
- #SMP_BROKEN is for x86_64.
- depends on EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN))
+ depends on BROKEN
help
This option enables UML SMP support.
It is NOT related to having a real SMP box. Not directly, at least.
@@ -217,17 +203,6 @@ config NR_CPUS
depends on SMP
default "32"
-config NEST_LEVEL
- int "Nesting level"
- default "0"
- help
- This is set to the number of layers of UMLs that this UML will be run
- in. Normally, this is zero, meaning that it will run directly on the
- host. Setting it to one will build a UML that can run inside a UML
- that is running on the host. Generally, if you intend this UML to run
- inside another UML, set CONFIG_NEST_LEVEL to one more than the host
- UML.
-
config HIGHMEM
bool "Highmem support (EXPERIMENTAL)"
depends on !64BIT && EXPERIMENTAL
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
index 9a78d354f0b..3a4b396d797 100644
--- a/arch/um/Kconfig.char
+++ b/arch/um/Kconfig.char
@@ -18,7 +18,7 @@ config SSL
lines on the UML that are usually made to show up on the host as
ttys or ptys.
- See <http://user-mode-linux.sourceforge.net/input.html> for more
+ See <http://user-mode-linux.sourceforge.net/old/input.html> for more
information and command line examples of how to use this facility.
Unless you have a specific reason for disabling this, say Y.
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index 1f6462ffd3e..8fce5e536b0 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -4,12 +4,12 @@ source "lib/Kconfig.debug"
config GPROF
bool "Enable gprof support"
- depends on DEBUG_INFO
+ depends on DEBUG_INFO && FRAME_POINTER
help
This allows profiling of a User-Mode Linux kernel with the gprof
utility.
- See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+ See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more
details.
If you're involved in UML kernel development and want to use gprof,
@@ -22,7 +22,7 @@ config GCOV
This option allows developers to retrieve coverage data from a UML
session.
- See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+ See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more
details.
If you're involved in UML kernel development and want to use gcov,
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index 717f5d3440e..3cd8a04d66d 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -23,43 +23,6 @@ config SEMAPHORE_SLEEPERS
bool
default y
-choice
- prompt "Host memory split"
- default HOST_VMSPLIT_3G
- help
- This is needed when the host kernel on which you run has a non-default
- (like 2G/2G) memory split, instead of the customary 3G/1G. If you did
- not recompile your own kernel but use the default distro's one, you can
- safely accept the "Default split" option.
-
- It can be enabled on recent (>=2.6.16-rc2) vanilla kernels via
- CONFIG_VM_SPLIT_*, or on previous kernels with special patches (-ck
- patchset by Con Kolivas, or other ones) - option names match closely the
- host CONFIG_VM_SPLIT_* ones.
-
- A lower setting (where 1G/3G is lowest and 3G/1G is higher) will
- tolerate even more "normal" host kernels, but an higher setting will be
- stricter.
-
- So, if you do not know what to do here, say 'Default split'.
-
-config HOST_VMSPLIT_3G
- bool "Default split (3G/1G user/kernel host split)"
-config HOST_VMSPLIT_3G_OPT
- bool "3G/1G user/kernel host split (for full 1G low memory)"
-config HOST_VMSPLIT_2G
- bool "2G/2G user/kernel host split"
-config HOST_VMSPLIT_1G
- bool "1G/3G user/kernel host split"
-endchoice
-
-config TOP_ADDR
- hex
- default 0xB0000000 if HOST_VMSPLIT_3G_OPT
- default 0x78000000 if HOST_VMSPLIT_2G
- default 0x40000000 if HOST_VMSPLIT_1G
- default 0xC0000000
-
config 3_LEVEL_PGTABLES
bool "Three-level pagetables (EXPERIMENTAL)"
default n
@@ -84,3 +47,5 @@ config GENERIC_HWEIGHT
bool
default y
+config ARCH_SUPPORTS_AOUT
+ def_bool y
diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net
index 66e50026ade..9e9a4aaa703 100644
--- a/arch/um/Kconfig.net
+++ b/arch/um/Kconfig.net
@@ -14,7 +14,7 @@ config UML_NET
For more information, including explanations of the networking and
sample configurations, see
- <http://user-mode-linux.sourceforge.net/networking.html>.
+ <http://user-mode-linux.sourceforge.net/old/networking.html>.
If you'd like to be able to enable networking in the User-Mode
linux environment, say Y; otherwise say N. Note that you must
@@ -38,7 +38,7 @@ config UML_NET_ETHERTAP
CONFIG_NETLINK_DEV configured as Y or M.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable Ethertap
networking.
@@ -72,7 +72,7 @@ config UML_NET_SLIP
To use this, your host must support slip devices.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html>. That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html>.
has examples of the UML command line to use to enable slip
networking, and details of a few quirks with it.
@@ -96,7 +96,7 @@ config UML_NET_DAEMON
networking daemon on the host.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable Daemon
networking.
@@ -144,7 +144,7 @@ config UML_NET_MCAST
To use this, your host kernel(s) must support IP Multicasting.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable Multicast
networking, and notes about the security of this approach.
@@ -165,7 +165,7 @@ config UML_NET_PCAP
installed in order to build the pcap transport into UML.
For more information, see
- <http://user-mode-linux.sourceforge.net/networking.html> That site
+ <http://user-mode-linux.sourceforge.net/old/networking.html> That site
has examples of the UML command line to use to enable this option.
If you intend to use UML as a network monitor for the host, say
diff --git a/arch/um/Kconfig.x86_64 b/arch/um/Kconfig.x86_64
index d632e9a89cc..6533b349f06 100644
--- a/arch/um/Kconfig.x86_64
+++ b/arch/um/Kconfig.x86_64
@@ -15,10 +15,6 @@ config SEMAPHORE_SLEEPERS
bool
default y
-config TOP_ADDR
- hex
- default 0x7fc0000000
-
config 3_LEVEL_PGTABLES
bool
default y
@@ -39,3 +35,5 @@ config GENERIC_HWEIGHT
bool
default y
+config ARCH_SUPPORTS_AOUT
+ def_bool y
diff --git a/arch/um/Makefile b/arch/um/Makefile
index ba6813a4aa3..dbeab15e7bb 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -49,7 +49,7 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
#
# These apply to USER_CFLAGS to.
-KBUILD_CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
+KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
-Din6addr_loopback=kernel_in6addr_loopback \
-Din6addr_any=kernel_in6addr_any
@@ -58,7 +58,7 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
$(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
- -D_FILE_OFFSET_BITS=64
+ $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64
include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
@@ -79,13 +79,6 @@ KERNEL_DEFINES = $(strip -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
KBUILD_CFLAGS += $(KERNEL_DEFINES)
KBUILD_CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
-# These are needed for clean and mrproper, since in that case .config is not
-# included; the values here are meaningless
-
-CONFIG_NEST_LEVEL ?= 0
-
-SIZE = ($(CONFIG_NEST_LEVEL) * 0x20000000)
-
PHONY += linux
all: linux
@@ -120,17 +113,15 @@ CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,)
CONFIG_KERNEL_STACK_ORDER ?= 2
STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
-ifndef START
- START = $(shell echo $$[ $(TOP_ADDR) - $(SIZE) ] )
-endif
-
CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
-DELF_FORMAT="$(ELF_FORMAT)" -DKERNEL_STACK_SIZE=$(STACK_SIZE)
# The wrappers will select whether using "malloc" or the kernel allocator.
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
-CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS)
+LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt))
+
+CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
define cmd_vmlinux__
$(CC) $(CFLAGS_vmlinux) -o $@ \
-Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
@@ -158,7 +149,7 @@ ifneq ($(KBUILD_SRC),)
$(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
else
- $(Q)cd $(TOPDIR)/$(dir $@) ; \
+ $(Q)cd $(srctree)/$(dir $@) ; \
ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
endif
@@ -168,7 +159,7 @@ ifneq ($(KBUILD_SRC),)
$(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-$(HEADER_ARCH) include/asm-um/arch
else
- $(Q)cd $(TOPDIR)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch
+ $(Q)cd $(srctree)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch
endif
$(objtree)/$(ARCH_DIR)/include:
diff --git a/arch/um/Makefile-tt b/arch/um/Makefile-tt
deleted file mode 100644
index 03f7b10cfd0..00000000000
--- a/arch/um/Makefile-tt
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-# Licensed under the GPL
-#
-
diff --git a/arch/um/defconfig b/arch/um/defconfig
index f609edede06..59215bc264e 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -56,8 +56,6 @@ CONFIG_X86_TSC=y
CONFIG_UML_X86=y
# CONFIG_64BIT is not set
CONFIG_SEMAPHORE_SLEEPERS=y
-# CONFIG_HOST_2G_2G is not set
-CONFIG_TOP_ADDR=0xc0000000
# CONFIG_3_LEVEL_PGTABLES is not set
CONFIG_ARCH_HAS_SC_SIGNALS=y
CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
@@ -77,11 +75,10 @@ CONFIG_LD_SCRIPT_DYN=y
CONFIG_NET=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
-# CONFIG_HOSTFS is not set
+CONFIG_HOSTFS=y
# CONFIG_HPPFS is not set
CONFIG_MCONSOLE=y
CONFIG_MAGIC_SYSRQ=y
-CONFIG_NEST_LEVEL=0
# CONFIG_HIGHMEM is not set
CONFIG_KERNEL_STACK_ORDER=0
@@ -188,7 +185,7 @@ CONFIG_CON_CHAN="xterm"
CONFIG_SSL_CHAN="pts"
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_LEGACY_PTY_COUNT=32
# CONFIG_WATCHDOG is not set
CONFIG_UML_SOUND=m
CONFIG_SOUND=m
@@ -508,7 +505,7 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
-CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SLAB_LEAK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 83bf15a3dda..2c898c4d6b6 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -8,6 +8,7 @@
#include "chan_kern.h"
#include "irq_kern.h"
#include "irq_user.h"
+#include "kern_util.h"
#include "os.h"
#define LINE_BUFSIZE 4096
@@ -48,7 +49,7 @@ static int write_room(struct line *line)
n = line->head - line->tail;
if (n <= 0)
- n = LINE_BUFSIZE + n; /* The other case */
+ n += LINE_BUFSIZE; /* The other case */
return n - 1;
}
@@ -58,17 +59,10 @@ int line_write_room(struct tty_struct *tty)
unsigned long flags;
int room;
- if (tty->stopped)
- return 0;
-
spin_lock_irqsave(&line->lock, flags);
room = write_room(line);
spin_unlock_irqrestore(&line->lock, flags);
- /*XXX: Warning to remove */
- if (0 == room)
- printk(KERN_DEBUG "%s: %s: no room left in buffer\n",
- __FUNCTION__,tty->name);
return room;
}
@@ -79,8 +73,7 @@ int line_chars_in_buffer(struct tty_struct *tty)
int ret;
spin_lock_irqsave(&line->lock, flags);
-
- /*write_room subtracts 1 for the needed NULL, so we readd it.*/
+ /* write_room subtracts 1 for the needed NULL, so we readd it.*/
ret = LINE_BUFSIZE - (write_room(line) + 1);
spin_unlock_irqrestore(&line->lock, flags);
@@ -184,10 +177,6 @@ void line_flush_buffer(struct tty_struct *tty)
unsigned long flags;
int err;
- /*XXX: copied from line_write, verify if it is correct!*/
- if (tty->stopped)
- return;
-
spin_lock_irqsave(&line->lock, flags);
err = flush_buffer(line);
spin_unlock_irqrestore(&line->lock, flags);
@@ -213,9 +202,6 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
unsigned long flags;
int n, ret = 0;
- if (tty->stopped)
- return 0;
-
spin_lock_irqsave(&line->lock, flags);
if (line->head != line->tail)
ret = buffer_data(line, buf, len);
@@ -788,9 +774,11 @@ static irqreturn_t winch_interrupt(int irq, void *data)
tty = winch->tty;
if (tty != NULL) {
line = tty->driver_data;
- chan_window_size(&line->chan_list, &tty->winsize.ws_row,
- &tty->winsize.ws_col);
- kill_pgrp(tty->pgrp, SIGWINCH, 1);
+ if (line != NULL) {
+ chan_window_size(&line->chan_list, &tty->winsize.ws_row,
+ &tty->winsize.ws_col);
+ kill_pgrp(tty->pgrp, SIGWINCH, 1);
+ }
}
out:
if (winch->fd != -1)
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 0f3c7d14a6e..19d579d74d2 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -1,23 +1,25 @@
/*
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Copyright (C) 2001 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/console.h"
-#include "linux/ctype.h"
-#include "linux/interrupt.h"
-#include "linux/list.h"
-#include "linux/mm.h"
-#include "linux/module.h"
-#include "linux/notifier.h"
-#include "linux/reboot.h"
-#include "linux/proc_fs.h"
-#include "linux/slab.h"
-#include "linux/syscalls.h"
-#include "linux/utsname.h"
-#include "linux/workqueue.h"
-#include "asm/uaccess.h"
+#include <linux/console.h>
+#include <linux/ctype.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/utsname.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+
#include "init.h"
#include "irq_kern.h"
#include "irq_user.h"
@@ -143,8 +145,8 @@ void mconsole_proc(struct mc_request *req)
}
up_write(&super->s_umount);
- nd.dentry = super->s_root;
- nd.mnt = NULL;
+ nd.path.dentry = super->s_root;
+ nd.path.mnt = NULL;
nd.flags = O_RDONLY + 1;
nd.last_type = LAST_ROOT;
@@ -157,7 +159,7 @@ void mconsole_proc(struct mc_request *req)
goto out_kill;
}
- file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+ file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY);
if (IS_ERR(file)) {
mconsole_reply(req, "Failed to open file", 1, 0);
goto out_kill;
@@ -305,7 +307,9 @@ void mconsole_stop(struct mc_request *req)
deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
os_set_fd_block(req->originating_fd, 1);
mconsole_reply(req, "stopped", 0, 0);
- while (mconsole_get_request(req->originating_fd, req)) {
+ for (;;) {
+ if (!mconsole_get_request(req->originating_fd, req))
+ continue;
if (req->cmd->handler == mconsole_go)
break;
if (req->cmd->handler == mconsole_stop) {
@@ -358,7 +362,7 @@ struct unplugged_pages {
void *pages[UNPLUGGED_PER_PAGE];
};
-static DECLARE_MUTEX(plug_mem_mutex);
+static DEFINE_MUTEX(plug_mem_mutex);
static unsigned long long unplugged_pages_count = 0;
static LIST_HEAD(unplugged_pages);
static int unplug_index = UNPLUGGED_PER_PAGE;
@@ -394,7 +398,7 @@ static int mem_config(char *str, char **error_out)
diff /= PAGE_SIZE;
- down(&plug_mem_mutex);
+ mutex_lock(&plug_mem_mutex);
for (i = 0; i < diff; i++) {
struct unplugged_pages *unplugged;
void *addr;
@@ -451,7 +455,7 @@ static int mem_config(char *str, char **error_out)
err = 0;
out_unlock:
- up(&plug_mem_mutex);
+ mutex_unlock(&plug_mem_mutex);
out:
return err;
}
@@ -741,7 +745,6 @@ void mconsole_stack(struct mc_request *req)
{
char *ptr = req->request.data;
int pid_requested= -1;
- struct task_struct *from = NULL;
struct task_struct *to = NULL;
/*
@@ -763,9 +766,7 @@ void mconsole_stack(struct mc_request *req)
return;
}
- from = current;
-
- to = find_task_by_pid(pid_requested);
+ to = find_task_by_pid_ns(pid_requested, &init_pid_ns);
if ((to == NULL) || (pid_requested == 0)) {
mconsole_reply(req, "Couldn't find that pid", 1, 0);
return;
@@ -795,6 +796,8 @@ static int __init mconsole_init(void)
printk(KERN_ERR "Failed to initialize management console\n");
return 1;
}
+ if (os_set_fd_block(sock, 0))
+ goto out;
register_reboot_notifier(&reboot_notifier);
@@ -803,7 +806,7 @@ static int __init mconsole_init(void)
"mconsole", (void *)sock);
if (err) {
printk(KERN_ERR "Failed to get IRQ for management console\n");
- return 1;
+ goto out;
}
if (notify_socket != NULL) {
@@ -819,6 +822,10 @@ static int __init mconsole_init(void)
printk(KERN_INFO "mconsole (version %d) initialized on %s\n",
MCONSOLE_VERSION, mconsole_socket_name);
return 0;
+
+ out:
+ os_close_file(sock);
+ return 1;
}
__initcall(mconsole_init);
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 430c024a19b..13af2f03ed8 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -83,9 +83,8 @@ int mconsole_get_request(int fd, struct mc_request *req)
int len;
req->originlen = sizeof(req->origin);
- req->len = recvfrom(fd, &req->request, sizeof(req->request),
- MSG_DONTWAIT, (struct sockaddr *) req->origin,
- &req->originlen);
+ req->len = recvfrom(fd, &req->request, sizeof(req->request), 0,
+ (struct sockaddr *) req->origin, &req->originlen);
if (req->len < 0)
return 0;
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 3c6c44ca1ff..1e8f41a9951 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -318,7 +318,7 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name)
if (str == NULL)
goto random;
- for (i = 0;i < 6; i++) {
+ for (i = 0; i < 6; i++) {
addr[i] = simple_strtoul(str, &end, 16);
if ((end == str) ||
((*end != ':') && (*end != ',') && (*end != '\0'))) {
@@ -343,14 +343,13 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name)
}
if (!is_local_ether_addr(addr)) {
printk(KERN_WARNING
- "Warning: attempt to assign a globally valid ethernet "
+ "Warning: Assigning a globally valid ethernet "
"address to a device\n");
- printk(KERN_WARNING "You should better enable the 2nd "
- "rightmost bit in the first byte of the MAC,\n");
+ printk(KERN_WARNING "You should set the 2nd rightmost bit in "
+ "the first byte of the MAC,\n");
printk(KERN_WARNING "i.e. %02x:%02x:%02x:%02x:%02x:%02x\n",
addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
addr[5]);
- goto random;
}
return;
@@ -368,7 +367,6 @@ static struct platform_driver uml_net_driver = {
.name = DRIVER_NAME,
},
};
-static int driver_registered;
static void net_device_release(struct device *dev)
{
@@ -383,6 +381,12 @@ static void net_device_release(struct device *dev)
free_netdev(netdev);
}
+/*
+ * Ensures that platform_driver_register is called only once by
+ * eth_configure. Will be set in an initcall.
+ */
+static int driver_registered;
+
static void eth_configure(int n, void *init, char *mac,
struct transport *transport)
{
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 29185cad9ff..abf2653f551 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -201,7 +201,7 @@ static int change_tramp(char **argv, char *output, int output_len)
close(fds[1]);
if (pid > 0)
- helper_wait(pid, 0, "change_tramp");
+ helper_wait(pid);
return pid;
}
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 330543b3129..19930081d3d 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -6,6 +6,7 @@
#include "linux/completion.h"
#include "linux/interrupt.h"
#include "linux/list.h"
+#include "linux/mutex.h"
#include "asm/atomic.h"
#include "init.h"
#include "irq_kern.h"
@@ -120,7 +121,7 @@ static int port_accept(struct port_list *port)
return 0;
}
-static DECLARE_MUTEX(ports_sem);
+static DEFINE_MUTEX(ports_mutex);
static LIST_HEAD(ports);
static void port_work_proc(struct work_struct *unused)
@@ -161,7 +162,7 @@ void *port_data(int port_num)
struct port_dev *dev = NULL;
int fd;
- down(&ports_sem);
+ mutex_lock(&ports_mutex);
list_for_each(ele, &ports) {
port = list_entry(ele, struct port_list, list);
if (port->port == port_num)
@@ -216,7 +217,7 @@ void *port_data(int port_num)
out_free:
kfree(port);
out:
- up(&ports_sem);
+ mutex_unlock(&ports_mutex);
return dev;
}
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index e942e836f99..71f0959c153 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -5,6 +5,7 @@
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*/
+#include <linux/sched.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index b8711e50da8..8b80505a3fb 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -109,7 +109,7 @@ static int slip_tramp(char **argv, int fd)
read_output(fds[0], output, output_len);
printk("%s", output);
- err = helper_wait(pid, 0, argv[0]);
+ err = helper_wait(pid);
close(fds[0]);
out_free:
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 89c1be225fd..a0ada8fec72 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -98,7 +98,7 @@ static void slirp_close(int fd, void *data)
"(%d)\n", pri->pid, errno);
}
#endif
- err = helper_wait(pri->pid, 1, "slirp_close");
+ err = helper_wait(pri->pid);
if (err < 0)
return;
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 875d60d0c6a..f1786e64607 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -15,7 +15,6 @@
#include "line.h"
#include "ssl.h"
#include "chan_kern.h"
-#include "kern_util.h"
#include "kern.h"
#include "init.h"
#include "irq_user.h"
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 656036e90b1..cec0c33cdd3 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -22,7 +22,6 @@
#include "stdio_console.h"
#include "line.h"
#include "chan_kern.h"
-#include "kern_util.h"
#include "irq_user.h"
#include "mconsole_kern.h"
#include "init.h"
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 99f9f9605e9..be3a2797dac 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -49,6 +49,7 @@
#include "irq_user.h"
#include "irq_kern.h"
#include "ubd_user.h"
+#include "kern_util.h"
#include "os.h"
#include "mem.h"
#include "mem_kern.h"
@@ -229,7 +230,7 @@ static int proc_ide_read_media(char *page, char **start, off_t off, int count,
return len;
}
-static void make_ide_entries(char *dev_name)
+static void make_ide_entries(const char *dev_name)
{
struct proc_dir_entry *dir, *ent;
char name[64];
@@ -244,7 +245,7 @@ static void make_ide_entries(char *dev_name)
ent->data = NULL;
ent->read_proc = proc_ide_read_media;
ent->write_proc = NULL;
- sprintf(name,"ide0/%s", dev_name);
+ snprintf(name, sizeof(name), "ide0/%s", dev_name);
proc_symlink(dev_name, proc_ide_root, name);
}
@@ -437,7 +438,10 @@ __uml_help(ubd_setup,
" machine by running 'dd' on the device. <n> must be in the range\n"
" 0 to 7. Appending an 'r' to the number will cause that device\n"
" to be mounted read-only. For example ubd1r=./ext_fs. Appending\n"
-" an 's' will cause data to be written to disk on the host immediately.\n\n"
+" an 's' will cause data to be written to disk on the host immediately.\n"
+" 'c' will cause the device to be treated as being shared between multiple\n"
+" UMLs and file locking will be turned off - this is appropriate for a\n"
+" cluster filesystem and inappropriate at almost all other times.\n\n"
);
static int udb_setup(char *str)
@@ -456,20 +460,6 @@ __uml_help(udb_setup,
" in the boot output.\n\n"
);
-static int fakehd_set = 0;
-static int fakehd(char *str)
-{
- printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
- fakehd_set = 1;
- return 1;
-}
-
-__setup("fakehd", fakehd);
-__uml_help(fakehd,
-"fakehd\n"
-" Change the ubd device name to \"hd\".\n\n"
-);
-
static void do_ubd_request(struct request_queue * q);
/* Only changed by ubd_init, which is an initcall. */
@@ -718,8 +708,10 @@ static int ubd_add(int n, char **error_out)
ubd_disk_register(fake_major, ubd_dev->size, n,
&fake_gendisk[n]);
- /* perhaps this should also be under the "if (fake_major)" above */
- /* using the fake_disk->disk_name and also the fakehd_set name */
+ /*
+ * Perhaps this should also be under the "if (fake_major)" above
+ * using the fake_disk->disk_name
+ */
if (fake_ide)
make_ide_entries(ubd_gendisk[n]->disk_name);
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 48fc7452bc1..b591bb9c41d 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -16,7 +16,6 @@
#include <sys/mman.h>
#include <sys/param.h>
#include "asm/types.h"
-#include "kern_util.h"
#include "user.h"
#include "ubd_user.h"
#include "os.h"
diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c
index d9941fe5f93..56533db2534 100644
--- a/arch/um/drivers/vde_user.c
+++ b/arch/um/drivers/vde_user.c
@@ -80,7 +80,7 @@ void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
if (vpri->args == NULL) {
- printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args"
+ printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args "
"allocation failed");
return;
}
diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h
index 49c601ff2ba..2de92a08a76 100644
--- a/arch/um/include/arch.h
+++ b/arch/um/include/arch.h
@@ -10,6 +10,6 @@
extern void arch_check_bugs(void);
extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs);
-extern int arch_handle_signal(int sig, struct uml_pt_regs *regs);
+extern void arch_examine_signal(int sig, struct uml_pt_regs *regs);
#endif
diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h
index a5cdf953e04..cac542d8ff7 100644
--- a/arch/um/include/as-layout.h
+++ b/arch/um/include/as-layout.h
@@ -10,23 +10,31 @@
#include "kern_constants.h"
/*
- * Assembly doesn't want any casting, but C does, so define these
- * without casts here, and define new symbols with casts inside the C
- * section.
+ * Stolen from linux/const.h, which can't be directly included since
+ * this is used in userspace code, which has no access to the kernel
+ * headers. Changed to be suitable for adding casts to the start,
+ * rather than "UL" to the end.
*/
-#define ASM_STUB_CODE (UML_CONFIG_TOP_ADDR - 2 * UM_KERN_PAGE_SIZE)
-#define ASM_STUB_DATA (UML_CONFIG_TOP_ADDR - UM_KERN_PAGE_SIZE)
-#define ASM_STUB_START ASM_STUB_CODE
-/*
- * This file is included by the assembly stubs, which just want the
- * definitions above.
+/* Some constant macros are used in both assembler and
+ * C code. Therefore we cannot annotate them always with
+ * 'UL' and other type specifiers unilaterally. We
+ * use the following macros to deal with this.
*/
-#ifndef __ASSEMBLY__
-#define STUB_CODE ((unsigned long) ASM_STUB_CODE)
-#define STUB_DATA ((unsigned long) ASM_STUB_DATA)
-#define STUB_START ((unsigned long) ASM_STUB_START)
+#ifdef __ASSEMBLY__
+#define _AC(X, Y) (Y)
+#else
+#define __AC(X, Y) (X (Y))
+#define _AC(X, Y) __AC(X, Y)
+#endif
+
+#define STUB_START _AC(, 0x100000)
+#define STUB_CODE _AC((unsigned long), STUB_START)
+#define STUB_DATA _AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE)
+#define STUB_END _AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE)
+
+#ifndef __ASSEMBLY__
#include "sysdep/ptrace.h"
@@ -49,6 +57,8 @@ extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
extern unsigned long _unprotected_end;
extern unsigned long brk_start;
+extern unsigned long host_task_size;
+
extern int linux_main(int argc, char **argv);
extern void (*sig_info[])(int, struct uml_pt_regs *);
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 5a2263e05bb..9b9ced85b70 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -48,7 +48,7 @@ extern void register_winch_irq(int fd, int tty_fd, int pid,
#define __channel_help(fn, prefix) \
__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
" Attach a console or serial line to a host channel. See\n" \
-" http://user-mode-linux.sourceforge.net/input.html for a complete\n" \
+" http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \
" description of this switch.\n\n" \
);
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 0edab695ed4..b54bd35585c 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -18,6 +18,7 @@ DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
DEFINE_STR(UM_KERN_INFO, KERN_INFO);
DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
+DEFINE_STR(UM_KERN_CONT, KERN_CONT);
DEFINE(UM_ELF_CLASS, ELF_CLASS);
DEFINE(UM_ELFCLASS32, ELFCLASS32);
diff --git a/arch/um/include/init.h b/arch/um/include/init.h
index cebc6cae919..b00a95741d4 100644
--- a/arch/um/include/init.h
+++ b/arch/um/include/init.h
@@ -40,6 +40,20 @@
typedef int (*initcall_t)(void);
typedef void (*exitcall_t)(void);
+#ifndef __KERNEL__
+#ifndef __section
+# define __section(S) __attribute__ ((__section__(#S)))
+#endif
+
+#if __GNUC_MINOR__ >= 3
+# define __used __attribute__((__used__))
+#else
+# define __used __attribute__((__unused__))
+#endif
+
+#else
+#include <linux/compiler.h>
+#endif
/* These are for everybody (although not all archs will actually
discard it in modules) */
#define __init __section(.init.text)
@@ -127,14 +141,3 @@ extern struct uml_param __uml_setup_start, __uml_setup_end;
#endif
#endif /* _LINUX_UML_INIT_H */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index 884a9c17eea..e60b31873de 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -14,7 +14,6 @@ struct irq_fd {
int fd;
int type;
int irq;
- int pid;
int events;
int current_events;
};
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 74ce8e5370a..3c341222d25 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -9,107 +9,61 @@
#include "sysdep/ptrace.h"
#include "sysdep/faultinfo.h"
-typedef void (*kern_hndl)(int, struct uml_pt_regs *);
-
-struct kern_handlers {
- kern_hndl relay_signal;
- kern_hndl winch;
- kern_hndl bus_handler;
- kern_hndl page_fault;
- kern_hndl sigio_handler;
- kern_hndl timer_handler;
-};
-
-extern const struct kern_handlers handlinfo_kern;
+extern int uml_exitcode;
extern int ncpus;
-extern char *gdb_init;
extern int kmalloc_ok;
-extern int jail;
-extern int nsyscalls;
-#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
#define UML_ROUND_UP(addr) \
- UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
+ ((((unsigned long) addr) + PAGE_SIZE - 1) & PAGE_MASK)
-extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
-extern int kernel_thread_proc(void *data);
-extern void syscall_segv(int sig);
-extern int current_pid(void);
extern unsigned long alloc_stack(int order, int atomic);
+extern void free_stack(unsigned long stack, int order);
+
extern int do_signal(void);
-extern int is_stack_fault(unsigned long sp);
+extern void copy_sc(struct uml_pt_regs *regs, void *from);
+extern void interrupt_end(void);
+extern void relay_signal(int sig, struct uml_pt_regs *regs);
+
extern unsigned long segv(struct faultinfo fi, unsigned long ip,
int is_user, struct uml_pt_regs *regs);
extern int handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user, int *code_out);
-extern void syscall_ready(void);
-extern void set_tracing(void *t, int tracing);
-extern int is_tracing(void *task);
-extern int segv_syscall(void);
-extern void kern_finish_exec(void *task, int new_pid, unsigned long stack);
-extern unsigned long page_mask(void);
-extern int need_finish_fork(void);
-extern void free_stack(unsigned long stack, int order);
-extern void add_input_request(int op, void (*proc)(int), void *arg);
-extern char *current_cmd(void);
-extern void timer_handler(int sig, struct uml_pt_regs *regs);
-extern int set_signals(int enable);
-extern int pid_to_processor_id(int pid);
-extern void deliver_signals(void *t);
-extern int next_trap_index(int max);
-extern void default_idle(void);
-extern void finish_fork(void);
-extern void paging_init(void);
-extern void init_flush_vm(void);
-extern void *syscall_sp(void *t);
-extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
+
extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs);
-extern void interrupt_end(void);
-extern void initial_thread_cb(void (*proc)(void *), void *arg);
-extern int debugger_signal(int status, int pid);
-extern void debugger_parent_signal(int status, int pid);
-extern void child_signal(int pid, int status);
-extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
-extern int init_parent_proxy(int pid);
-extern int singlestepping(void *t);
-extern void check_stack_overflow(void *ptr);
-extern void relay_signal(int sig, struct uml_pt_regs *regs);
-extern int user_context(unsigned long sp);
-extern void timer_irq(struct uml_pt_regs *regs);
-extern void do_uml_exitcalls(void);
-extern int attach_debugger(int idle_pid, int pid, int stop);
-extern int config_gdb(char *str);
-extern int remove_gdb(void);
-extern char *uml_strdup(char *string);
-extern void unprotect_kernel_mem(void);
-extern void protect_kernel_mem(void);
-extern void uml_cleanup(void);
-extern void lock_signalled_task(void *t);
-extern void IPI_handler(int cpu);
-extern int jail_setup(char *line, int *add);
-extern void *get_init_task(void);
-extern int clear_user_proc(void *buf, int size);
-extern int copy_to_user_proc(void *to, void *from, int size);
-extern int copy_from_user_proc(void *to, void *from, int size);
-extern int strlen_user_proc(char *str);
-extern long execute_syscall(void *r);
extern int smp_sigio_handler(void);
-extern void *get_current(void);
-extern struct task_struct *get_task(int pid, int require);
-extern void machine_halt(void);
+extern void initial_thread_cb(void (*proc)(void *), void *arg);
extern int is_syscall(unsigned long addr);
+extern void timer_handler(int sig, struct uml_pt_regs *regs);
-extern void free_irq(unsigned int, void *);
-extern int cpu(void);
+extern void timer_handler(int sig, struct uml_pt_regs *regs);
-extern void time_init_kern(void);
+extern int start_uml(void);
+extern void paging_init(void);
-/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
+extern void uml_cleanup(void);
+extern void do_uml_exitcalls(void);
+
+/*
+ * Are we disallowed to sleep? Used to choose between GFP_KERNEL and
+ * GFP_ATOMIC.
+ */
extern int __cant_sleep(void);
-extern void sigio_handler(int sig, struct uml_pt_regs *regs);
-extern void copy_sc(struct uml_pt_regs *regs, void *from);
+extern void *get_current(void);
+extern int copy_from_user_proc(void *to, void *from, int size);
+extern int cpu(void);
+extern char *uml_strdup(const char *string);
+
extern unsigned long to_irq_stack(unsigned long *mask_out);
-unsigned long from_irq_stack(int nested);
-extern int start_uml(void);
+extern unsigned long from_irq_stack(int nested);
+
+extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
+extern int singlestepping(void *t);
+
+extern void segv_handler(int sig, struct uml_pt_regs *regs);
+extern void bus_handler(int sig, struct uml_pt_regs *regs);
+extern void winch(int sig, struct uml_pt_regs *regs);
+extern void fatal_sigsegv(void) __attribute__ ((noreturn));
+
+
#endif
diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
index a54514d2cc3..46384acd547 100644
--- a/arch/um/include/mem_user.h
+++ b/arch/um/include/mem_user.h
@@ -46,9 +46,6 @@ extern int iomem_size;
#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
-extern unsigned long host_task_size;
-extern unsigned long task_size;
-
extern int init_mem_user(void);
extern void setup_memory(void *entry);
extern unsigned long find_iomem(char *driver, unsigned long *len_out);
@@ -59,9 +56,7 @@ extern void setup_physmem(unsigned long start, unsigned long usable,
unsigned long len, unsigned long long highmem);
extern void add_iomem(char *name, int fd, unsigned long size);
extern unsigned long phys_offset(unsigned long phys);
-extern void unmap_physmem(void);
extern void map_memory(unsigned long virt, unsigned long phys,
unsigned long len, int r, int w, int x);
-extern unsigned long get_kmem_end(void);
#endif
diff --git a/arch/um/include/misc_constants.h b/arch/um/include/misc_constants.h
deleted file mode 100644
index 989bc08de36..00000000000
--- a/arch/um/include/misc_constants.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __MISC_CONSTANT_H_
-#define __MISC_CONSTANT_H_
-
-#include <user_constants.h>
-
-#endif
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 6f0d1c741bc..32c799e3a49 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -8,7 +8,6 @@
#include <stdarg.h>
#include "irq_user.h"
-#include "kern_util.h"
#include "longjmp.h"
#include "mm_id.h"
#include "sysdep/tls.h"
@@ -128,33 +127,31 @@ static inline struct openflags of_cloexec(struct openflags flags)
extern int os_stat_file(const char *file_name, struct uml_stat *buf);
extern int os_stat_fd(const int fd, struct uml_stat *buf);
extern int os_access(const char *file, int mode);
-extern int os_get_exec_close(int fd, int *close_on_exec);
extern int os_set_exec_close(int fd);
extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
extern int os_get_ifname(int fd, char *namebuf);
extern int os_set_slip(int fd);
-extern int os_set_owner(int fd, int pid);
extern int os_mode_fd(int fd, int mode);
extern int os_seek_file(int fd, unsigned long long offset);
-extern int os_open_file(char *file, struct openflags flags, int mode);
+extern int os_open_file(const char *file, struct openflags flags, int mode);
extern int os_read_file(int fd, void *buf, int len);
extern int os_write_file(int fd, const void *buf, int count);
-extern int os_file_size(char *file, unsigned long long *size_out);
-extern int os_file_modtime(char *file, unsigned long *modtime);
+extern int os_file_size(const char *file, unsigned long long *size_out);
+extern int os_file_modtime(const char *file, unsigned long *modtime);
extern int os_pipe(int *fd, int stream, int close_on_exec);
-extern int os_set_fd_async(int fd, int owner);
+extern int os_set_fd_async(int fd);
extern int os_clear_fd_async(int fd);
extern int os_set_fd_block(int fd, int blocking);
extern int os_accept_connection(int fd);
-extern int os_create_unix_socket(char *file, int len, int close_on_exec);
+extern int os_create_unix_socket(const char *file, int len, int close_on_exec);
extern int os_shutdown_socket(int fd, int r, int w);
extern void os_close_file(int fd);
extern int os_rcv_fd(int fd, int *helper_pid_out);
extern int create_unix_socket(char *file, int len, int close_on_exec);
-extern int os_connect_socket(char *name);
+extern int os_connect_socket(const char *name);
extern int os_file_type(char *file);
-extern int os_file_mode(char *file, struct openflags *mode_out);
+extern int os_file_mode(const char *file, struct openflags *mode_out);
extern int os_lock_file(int fd, int excl);
extern void os_flush_stdout(void);
extern int os_stat_filesystem(char *path, long *bsize_out,
@@ -168,14 +165,10 @@ extern int os_fchange_dir(int fd);
/* start_up.c */
extern void os_early_checks(void);
-extern int can_do_skas(void);
+extern void can_do_skas(void);
extern void os_check_bugs(void);
extern void check_host_supports_tls(int *supports_tls, int *tls_min);
-/* Make sure they are clear when running in TT mode. Required by
- * SEGV_MAYBE_FIXABLE */
-#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
-
/* mem.c */
extern int create_mem_file(unsigned long long len);
@@ -214,7 +207,7 @@ extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv);
extern int run_helper_thread(int (*proc)(void *), void *arg,
unsigned int flags, unsigned long *stack_out);
-extern int helper_wait(int pid, int nohang, char *pname);
+extern int helper_wait(int pid);
/* tls.c */
@@ -237,16 +230,12 @@ extern void unblock_signals(void);
extern int get_signals(void);
extern int set_signals(int enable);
-/* trap.c */
-extern void os_fill_handlinfo(struct kern_handlers h);
-
/* util.c */
extern void stack_protections(unsigned long address);
extern int raw(int fd);
extern void setup_machinename(char *machine_out);
extern void setup_hostinfo(char *buf, int len);
-extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
-extern void os_dump_core(void);
+extern void os_dump_core(void) __attribute__ ((noreturn));
/* time.c */
extern void idle_sleep(unsigned long long nsecs);
@@ -275,11 +264,9 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr,
extern int is_skas_winch(int pid, int fd, void *data);
extern int start_userspace(unsigned long stub_stack);
extern int copy_context_skas0(unsigned long stack, int pid);
-extern void save_registers(int pid, struct uml_pt_regs *regs);
-extern void restore_registers(int pid, struct uml_pt_regs *regs);
extern void userspace(struct uml_pt_regs *regs);
-extern void map_stub_pages(int fd, unsigned long code,
- unsigned long data, unsigned long stack);
+extern int map_stub_pages(int fd, unsigned long code, unsigned long data,
+ unsigned long stack);
extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
extern void switch_threads(jmp_buf *me, jmp_buf *you);
extern int start_idle_thread(void *stack, jmp_buf *switch_buf);
@@ -298,20 +285,19 @@ extern void os_free_irq_later(struct irq_fd *active_fds,
extern int os_get_pollfd(int i);
extern void os_set_pollfd(int i, int fd);
extern void os_set_ioignore(void);
-extern void init_irq_signals(int on_sigstack);
/* sigio.c */
extern int add_sigio_fd(int fd);
extern int ignore_sigio_fd(int fd);
extern void maybe_sigio_broken(int fd, int read);
-/* skas/trap */
-extern void sig_handler_common_skas(int sig, void *sc_ptr);
-
/* sys-x86_64/prctl.c */
extern int os_arch_prctl(int pid, int code, unsigned long *addr);
/* tty.c */
-int get_pty(void);
+extern int get_pty(void);
+
+/* sys-$ARCH/task_size.c */
+extern unsigned long os_get_task_size(void);
#endif
diff --git a/arch/um/include/ptrace_user.h b/arch/um/include/ptrace_user.h
index f3450e6bc18..4bce6e01288 100644
--- a/arch/um/include/ptrace_user.h
+++ b/arch/um/include/ptrace_user.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -10,12 +10,6 @@
extern int ptrace_getregs(long pid, unsigned long *regs_out);
extern int ptrace_setregs(long pid, unsigned long *regs_in);
-extern int ptrace_getfpregs(long pid, unsigned long *regs_out);
-extern int ptrace_setfpregs(long pid, unsigned long *regs);
-extern void arch_enter_kernel(void *task, int pid);
-extern void arch_leave_kernel(void *task, int pid);
-extern void ptrace_pokeuser(unsigned long addr, unsigned long data);
-
/* syscall emulation path in ptrace */
@@ -54,7 +48,8 @@ extern int sysemu_supported;
(((int[3][3] ) { \
{ PTRACE_SYSCALL, PTRACE_SYSCALL, PTRACE_SINGLESTEP }, \
{ PTRACE_SYSEMU, PTRACE_SYSEMU, PTRACE_SINGLESTEP }, \
- { PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, PTRACE_SYSEMU_SINGLESTEP }}) \
+ { PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, \
+ PTRACE_SYSEMU_SINGLESTEP } }) \
[sysemu_mode][singlestep_mode])
#endif
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index 0e27406a43a..9ea1ae3c8f4 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -9,14 +9,13 @@
#include "sysdep/ptrace.h"
#include "sysdep/archsetjmp.h"
-extern void init_thread_registers(struct uml_pt_regs *to);
extern int save_fp_registers(int pid, unsigned long *fp_regs);
extern int restore_fp_registers(int pid, unsigned long *fp_regs);
extern int save_fpx_registers(int pid, unsigned long *fp_regs);
extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
-extern void save_registers(int pid, struct uml_pt_regs *regs);
-extern void restore_registers(int pid, struct uml_pt_regs *regs);
-extern void init_registers(int pid);
+extern int save_registers(int pid, struct uml_pt_regs *regs);
+extern int restore_registers(int pid, struct uml_pt_regs *regs);
+extern int init_registers(int pid);
extern void get_safe_registers(unsigned long *regs);
extern unsigned long get_thread_reg(int reg, jmp_buf *buf);
diff --git a/arch/um/include/signal_kern.h b/arch/um/include/signal_kern.h
deleted file mode 100644
index aeb5d5ab1df..00000000000
--- a/arch/um/include/signal_kern.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SIGNAL_KERN_H__
-#define __SIGNAL_KERN_H__
-
-extern int have_signals(void *t);
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
deleted file mode 100644
index e065feb000d..00000000000
--- a/arch/um/include/skas/mode-skas.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
- */
-
-#ifndef __MODE_SKAS_H__
-#define __MODE_SKAS_H__
-
-extern void kill_off_processes_skas(void);
-
-#endif
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index 57bd79efbee..905698197e3 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -18,7 +18,8 @@ extern syscall_handler_t old_mmap_i386;
extern syscall_handler_t *sys_call_table[];
#define EXECUTE_SYSCALL(syscall, regs) \
- ((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
+ ((long (*)(struct syscall_args)) \
+ (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
extern long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index c978b589df4..a307237b796 100644
--- a/arch/um/include/sysdep-x86_64/kernel-offsets.h
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -17,16 +17,7 @@
#define OFFSET(sym, str, mem) \
DEFINE(sym, offsetof(struct str, mem));
-#define __NO_STUBS 1
-#undef __SYSCALL
-#undef _ASM_X86_64_UNISTD_H_
-#define __SYSCALL(nr, sym) [nr] = 1,
-static char syscalls[] = {
-#include <asm/arch/unistd.h>
-};
-
void foo(void)
{
#include <common-offsets.h>
-DEFINE(UM_NR_syscall_max, sizeof(syscalls) - 1);
}
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
index cf72256609e..7cfb0b08565 100644
--- a/arch/um/include/sysdep-x86_64/syscalls.h
+++ b/arch/um/include/sysdep-x86_64/syscalls.h
@@ -30,6 +30,4 @@ extern long old_mmap(unsigned long addr, unsigned long len,
extern syscall_handler_t sys_modify_ldt;
extern syscall_handler_t sys_arch_prctl;
-#define NR_syscalls (UM_NR_syscall_max + 1)
-
#endif
diff --git a/arch/um/include/tempfile.h b/arch/um/include/tempfile.h
deleted file mode 100644
index d441eac936b..00000000000
--- a/arch/um/include/tempfile.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TEMPFILE_H__
-#define __TEMPFILE_H__
-
-extern int make_tempfile(const char *template, char **tempname, int do_unlink);
-
-#endif
diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h
index 8855d8df512..f575ff91f2a 100644
--- a/arch/um/include/um_mmu.h
+++ b/arch/um/include/um_mmu.h
@@ -12,11 +12,8 @@
typedef struct mm_context {
struct mm_id id;
- unsigned long last_page_table;
-#ifdef CONFIG_3_LEVEL_PGTABLES
- unsigned long last_pmd;
-#endif
struct uml_ldt ldt;
+ struct page **stub_pages;
} mm_context_t;
extern void __switch_mm(struct mm_id * mm_idp);
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
index fdfc06b8560..2b6fc8e0f07 100644
--- a/arch/um/include/um_uaccess.h
+++ b/arch/um/include/um_uaccess.h
@@ -6,7 +6,9 @@
#ifndef __ARCH_UM_UACCESS_H
#define __ARCH_UM_UACCESS_H
-#include "asm/fixmap.h"
+#include <asm/elf.h>
+#include <asm/fixmap.h>
+#include "sysdep/archsetjmp.h"
#define __under_task_size(addr, size) \
(((unsigned long) (addr) < TASK_SIZE) && \
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 8196450451c..f5d7f4569ba 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -19,12 +19,13 @@
void flush_thread(void)
{
void *data = NULL;
- unsigned long end = proc_mm ? task_size : STUB_START;
int ret;
arch_flush_thread(&current->thread.arch);
- ret = unmap(&current->mm->context.id, 0, end, 1, &data);
+ ret = unmap(&current->mm->context.id, 0, STUB_START, 0, &data);
+ ret = ret || unmap(&current->mm->context.id, STUB_END,
+ host_task_size - STUB_END, 1, &data);
if (ret) {
printk(KERN_ERR "flush_thread - clearing address space failed, "
"err = %d\n", ret);
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index c716b5a6db1..984f80e668c 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -1,15 +1,17 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/init.h"
-#include "linux/ctype.h"
-#include "linux/proc_fs.h"
-#include "asm/uaccess.h"
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
-/* If read and write race, the read will still atomically read a valid
+/*
+ * If read and write race, the read will still atomically read a valid
* value.
*/
int uml_exitcode = 0;
@@ -19,18 +21,19 @@ static int read_proc_exitcode(char *page, char **start, off_t off,
{
int len, val;
- /* Save uml_exitcode in a local so that we don't need to guarantee
+ /*
+ * Save uml_exitcode in a local so that we don't need to guarantee
* that sprintf accesses it atomically.
*/
val = uml_exitcode;
len = sprintf(page, "%d\n", val);
len -= off;
- if(len <= off+count)
+ if (len <= off+count)
*eof = 1;
*start = page + off;
- if(len > count)
+ if (len > count)
len = count;
- if(len < 0)
+ if (len < 0)
len = 0;
return len;
}
@@ -41,11 +44,11 @@ static int write_proc_exitcode(struct file *file, const char __user *buffer,
char *end, buf[sizeof("nnnnn\0")];
int tmp;
- if(copy_from_user(buf, buffer, count))
+ if (copy_from_user(buf, buffer, count))
return -EFAULT;
tmp = simple_strtol(buf, &end, 0);
- if((*end != '\0') && !isspace(*end))
+ if ((*end != '\0') && !isspace(*end))
return -EINVAL;
uml_exitcode = tmp;
@@ -57,7 +60,7 @@ static int make_proc_exitcode(void)
struct proc_dir_entry *ent;
ent = create_proc_entry("exitcode", 0600, &proc_root);
- if(ent == NULL){
+ if (ent == NULL) {
printk(KERN_WARNING "make_proc_exitcode : Failed to register "
"/proc/exitcode\n");
return 0;
diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
index 734f873cab1..72eccd2a411 100644
--- a/arch/um/kernel/gmon_syms.c
+++ b/arch/um/kernel/gmon_syms.c
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -8,12 +8,13 @@
extern void __bb_init_func(void *) __attribute__((weak));
EXPORT_SYMBOL(__bb_init_func);
-/* This is defined (and referred to in profiling stub code) only by some GCC
+/*
+ * This is defined (and referred to in profiling stub code) only by some GCC
* versions in libgcov.
*
* Since SuSE backported the fix, we cannot handle it depending on GCC version.
- * So, unconditionally export it. But also give it a weak declaration, which will
- * be overridden by any other one.
+ * So, unconditionally export it. But also give it a weak declaration, which
+ * will be overridden by any other one.
*/
extern void __gcov_init(void *) __attribute__((weak));
diff --git a/arch/um/kernel/gprof_syms.c b/arch/um/kernel/gprof_syms.c
index 9244f018d44..e2f043d0de6 100644
--- a/arch/um/kernel/gprof_syms.c
+++ b/arch/um/kernel/gprof_syms.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -7,14 +7,3 @@
extern void mcount(void);
EXPORT_SYMBOL(mcount);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
index 16dc43e9d94..fa015565001 100644
--- a/arch/um/kernel/initrd.c
+++ b/arch/um/kernel/initrd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -7,7 +7,6 @@
#include "linux/bootmem.h"
#include "linux/initrd.h"
#include "asm/types.h"
-#include "kern_util.h"
#include "initrd.h"
#include "init.h"
#include "os.h"
@@ -21,18 +20,27 @@ static int __init read_initrd(void)
long long size;
int err;
- if(initrd == NULL)
+ if (initrd == NULL)
return 0;
err = os_file_size(initrd, &size);
- if(err)
+ if (err)
return 0;
+ /*
+ * This is necessary because alloc_bootmem craps out if you
+ * ask for no memory.
+ */
+ if (size == 0) {
+ printk(KERN_ERR "\"%\" is a zero-size initrd\n");
+ return 0;
+ }
+
area = alloc_bootmem(size);
- if(area == NULL)
+ if (area == NULL)
return 0;
- if(load_initrd(initrd, area, size) == -1)
+ if (load_initrd(initrd, area, size) == -1)
return 0;
initrd_start = (unsigned long) area;
@@ -59,13 +67,15 @@ int load_initrd(char *filename, void *buf, int size)
int fd, n;
fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
- if(fd < 0){
- printk("Opening '%s' failed - err = %d\n", filename, -fd);
+ if (fd < 0) {
+ printk(KERN_ERR "Opening '%s' failed - err = %d\n", filename,
+ -fd);
return -1;
}
n = os_read_file(fd, buf, size);
- if(n != size){
- printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+ if (n != size) {
+ printk(KERN_ERR "Read of %d bytes from '%s' failed, "
+ "err = %d\n", size,
filename, -n);
return -1;
}
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index ba11ccd6a8a..91587f8db34 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -107,10 +107,9 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
struct pollfd *tmp_pfd;
struct irq_fd *new_fd, *irq_fd;
unsigned long flags;
- int pid, events, err, n;
+ int events, err, n;
- pid = os_getpid();
- err = os_set_fd_async(fd, pid);
+ err = os_set_fd_async(fd);
if (err < 0)
goto out;
@@ -127,7 +126,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
.fd = fd,
.type = type,
.irq = irq,
- .pid = pid,
.events = events,
.current_events = 0 } );
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 7c7142ba3bd..66e2a305a8d 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -5,7 +5,6 @@
#include "linux/module.h"
#include "linux/syscalls.h"
-#include "asm/a.out.h"
#include "asm/tlbflush.h"
#include "asm/uaccess.h"
#include "as-layout.h"
@@ -18,15 +17,11 @@ EXPORT_SYMBOL(set_signals);
EXPORT_SYMBOL(get_signals);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(sys_waitpid);
-EXPORT_SYMBOL(task_size);
EXPORT_SYMBOL(flush_tlb_range);
-EXPORT_SYMBOL(host_task_size);
EXPORT_SYMBOL(arch_validate);
-EXPORT_SYMBOL(get_kmem_end);
EXPORT_SYMBOL(high_physmem);
EXPORT_SYMBOL(empty_zero_page);
-EXPORT_SYMBOL(um_virt_to_phys);
EXPORT_SYMBOL(handle_page_fault);
EXPORT_SYMBOL(find_iomem);
@@ -40,7 +35,6 @@ EXPORT_SYMBOL(uml_strdup);
EXPORT_SYMBOL(os_stat_fd);
EXPORT_SYMBOL(os_stat_file);
EXPORT_SYMBOL(os_access);
-EXPORT_SYMBOL(os_get_exec_close);
EXPORT_SYMBOL(os_set_exec_close);
EXPORT_SYMBOL(os_getpid);
EXPORT_SYMBOL(os_open_file);
@@ -65,7 +59,6 @@ EXPORT_SYMBOL(os_accept_connection);
EXPORT_SYMBOL(os_rcv_fd);
EXPORT_SYMBOL(run_helper);
EXPORT_SYMBOL(start_thread);
-EXPORT_SYMBOL(dump_thread);
#ifdef CONFIG_SMP
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 59822dee438..2627ce82e91 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -1,49 +1,41 @@
/*
- * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/stddef.h"
-#include "linux/kernel.h"
-#include "linux/mm.h"
-#include "linux/bootmem.h"
-#include "linux/swap.h"
-#include "linux/highmem.h"
-#include "linux/gfp.h"
-#include "asm/page.h"
-#include "asm/fixmap.h"
-#include "asm/pgalloc.h"
-#include "kern_util.h"
+#include <linux/stddef.h>
+#include <linux/bootmem.h>
+#include <linux/gfp.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <asm/fixmap.h>
+#include <asm/page.h>
#include "as-layout.h"
+#include "init.h"
#include "kern.h"
+#include "kern_util.h"
#include "mem_user.h"
-#include "um_uaccess.h"
#include "os.h"
-#include "linux/types.h"
-#include "linux/string.h"
-#include "init.h"
-#include "kern_constants.h"
/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
unsigned long *empty_zero_page = NULL;
/* allocated in paging_init and unchanged thereafter */
unsigned long *empty_bad_page = NULL;
+
+/*
+ * Initialized during boot, and readonly for initializing page tables
+ * afterwards
+ */
pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/* Initialized at boot time, and readonly after that */
unsigned long long highmem;
int kmalloc_ok = 0;
+/* Used during early boot */
static unsigned long brk_end;
-void unmap_physmem(void)
-{
- os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
-}
-
-static void map_cb(void *unused)
-{
- map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
-}
-
#ifdef CONFIG_HIGHMEM
static void setup_highmem(unsigned long highmem_start,
unsigned long highmem_len)
@@ -53,7 +45,7 @@ static void setup_highmem(unsigned long highmem_start,
int i;
highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
- for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
+ for (i = 0; i < highmem_len >> PAGE_SHIFT; i++) {
page = &mem_map[highmem_pfn + i];
ClearPageReserved(page);
init_page_count(page);
@@ -65,14 +57,13 @@ static void setup_highmem(unsigned long highmem_start,
void __init mem_init(void)
{
/* clear the zero-page */
- memset((void *) empty_zero_page, 0, PAGE_SIZE);
+ memset(empty_zero_page, 0, PAGE_SIZE);
/* Map in the area just after the brk now that kmalloc is about
* to be turned on.
*/
brk_end = (unsigned long) UML_ROUND_UP(sbrk(0));
- map_cb(NULL);
- initial_thread_cb(map_cb, NULL);
+ map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
free_bootmem(__pa(brk_end), uml_reserved - brk_end);
uml_reserved = brk_end;
@@ -85,7 +76,7 @@ void __init mem_init(void)
#endif
num_physpages = totalram_pages;
max_pfn = totalram_pages;
- printk(KERN_INFO "Memory: %luk available\n",
+ printk(KERN_INFO "Memory: %luk available\n",
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
kmalloc_ok = 1;
@@ -119,7 +110,7 @@ static void __init one_md_table_init(pud_t *pud)
#endif
}
-static void __init fixrange_init(unsigned long start, unsigned long end,
+static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
pgd_t *pgd;
@@ -138,7 +129,7 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
if (pud_none(*pud))
one_md_table_init(pud);
pmd = pmd_offset(pud, vaddr);
- for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
+ for (; (j < PTRS_PER_PMD) && (vaddr < end); pmd++, j++) {
one_page_table_init(pmd);
vaddr += PMD_SIZE;
}
@@ -152,7 +143,7 @@ pgprot_t kmap_prot;
#define kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\
- (vaddr)), (vaddr))
+ (vaddr)), (vaddr))
static void __init kmap_init(void)
{
@@ -197,21 +188,23 @@ static void __init fixaddr_user_init( void)
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
- unsigned long paddr, vaddr = FIXADDR_USER_START;
+ phys_t p;
+ unsigned long v, vaddr = FIXADDR_USER_START;
- if ( ! size )
+ if (!size)
return;
fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
- paddr = (unsigned long)alloc_bootmem_low_pages( size);
- memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size);
- paddr = __pa(paddr);
- for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE){
+ v = (unsigned long) alloc_bootmem_low_pages(size);
+ memcpy((void *) v , (void *) FIXADDR_USER_START, size);
+ p = __pa(v);
+ for ( ; size > 0; size -= PAGE_SIZE, vaddr += PAGE_SIZE,
+ p += PAGE_SIZE) {
pgd = swapper_pg_dir + pgd_index(vaddr);
pud = pud_offset(pgd, vaddr);
pmd = pmd_offset(pud, vaddr);
pte = pte_offset_kernel(pmd, vaddr);
- pte_set_val( (*pte), paddr, PAGE_READONLY);
+ pte_set_val(*pte, p, PAGE_READONLY);
}
#endif
}
@@ -223,7 +216,7 @@ void __init paging_init(void)
empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
- for(i = 0; i < ARRAY_SIZE(zones_size); i++)
+ for (i = 0; i < ARRAY_SIZE(zones_size); i++)
zones_size[i] = 0;
zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
@@ -253,32 +246,33 @@ struct page *arch_validate(struct page *page, gfp_t mask, int order)
int i;
again:
- if(page == NULL)
+ if (page == NULL)
return page;
- if(PageHighMem(page))
+ if (PageHighMem(page))
return page;
addr = (unsigned long) page_address(page);
- for(i = 0; i < (1 << order); i++){
+ for (i = 0; i < (1 << order); i++) {
current->thread.fault_addr = (void *) addr;
- if(__do_copy_to_user((void __user *) addr, &zero,
+ if (__do_copy_to_user((void __user *) addr, &zero,
sizeof(zero),
&current->thread.fault_addr,
- &current->thread.fault_catcher)){
- if(!(mask & __GFP_WAIT))
+ &current->thread.fault_catcher)) {
+ if (!(mask & __GFP_WAIT))
return NULL;
else break;
}
addr += PAGE_SIZE;
}
- if(i == (1 << order))
+ if (i == (1 << order))
return page;
page = alloc_pages(mask, order);
goto again;
}
-/* This can't do anything because nothing in the kernel image can be freed
+/*
+ * This can't do anything because nothing in the kernel image can be freed
* since it's not in kernel physical memory.
*/
@@ -290,8 +284,8 @@ void free_initmem(void)
void free_initrd_mem(unsigned long start, unsigned long end)
{
if (start < end)
- printk ("Freeing initrd memory: %ldk freed\n",
- (end - start) >> 10);
+ printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
+ (end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
@@ -308,32 +302,31 @@ void show_mem(void)
int highmem = 0;
struct page *page;
- printk("Mem-info:\n");
+ printk(KERN_INFO "Mem-info:\n");
show_free_areas();
- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ printk(KERN_INFO "Free swap: %6ldkB\n",
+ nr_swap_pages<<(PAGE_SHIFT-10));
pfn = max_mapnr;
- while(pfn-- > 0) {
+ while (pfn-- > 0) {
page = pfn_to_page(pfn);
total++;
- if(PageHighMem(page))
+ if (PageHighMem(page))
highmem++;
- if(PageReserved(page))
+ if (PageReserved(page))
reserved++;
- else if(PageSwapCache(page))
+ else if (PageSwapCache(page))
cached++;
- else if(page_count(page))
+ else if (page_count(page))
shared += page_count(page) - 1;
}
- printk("%d pages of RAM\n", total);
- printk("%d pages of HIGHMEM\n", highmem);
- printk("%d reserved pages\n", reserved);
- printk("%d pages shared\n", shared);
- printk("%d pages swap cached\n", cached);
+ printk(KERN_INFO "%d pages of RAM\n", total);
+ printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
+ printk(KERN_INFO "%d reserved pages\n", reserved);
+ printk(KERN_INFO "%d pages shared\n", shared);
+ printk(KERN_INFO "%d pages swap cached\n", cached);
}
-/*
- * Allocate and free page tables.
- */
+/* Allocate and free page tables. */
pgd_t *pgd_alloc(struct mm_struct *mm)
{
@@ -341,14 +334,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
if (pgd) {
memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
- memcpy(pgd + USER_PTRS_PER_PGD,
- swapper_pg_dir + USER_PTRS_PER_PGD,
+ memcpy(pgd + USER_PTRS_PER_PGD,
+ swapper_pg_dir + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
}
return pgd;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_page((unsigned long) pgd);
}
@@ -361,10 +354,24 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
return pte;
}
-struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *pte;
pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+ if (pte)
+ pgtable_page_ctor(pte);
return pte;
}
+
+#ifdef CONFIG_3_LEVEL_PGTABLES
+pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
+
+ if (pmd)
+ memset(pmd, 0, PAGE_SIZE);
+
+ return pmd;
+}
+#endif
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index e66432f4248..9757085a022 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -55,16 +55,6 @@ int __init init_maps(unsigned long physmem, unsigned long iomem,
return 0;
}
-/* Changed during early boot */
-static unsigned long kmem_top = 0;
-
-unsigned long get_kmem_end(void)
-{
- if (kmem_top == 0)
- kmem_top = host_task_size - 1024 * 1024;
- return kmem_top;
-}
-
void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
int r, int w, int x)
{
@@ -174,10 +164,10 @@ __uml_setup("iomem=", parse_iomem,
* setup_iomem, both of which run during early boot. Afterwards, it's
* unchanged.
*/
-struct iomem_region *iomem_regions = NULL;
+struct iomem_region *iomem_regions;
-/* Initialized in parse_iomem */
-int iomem_size = 0;
+/* Initialized in parse_iomem and unchanged thereafter */
+int iomem_size;
unsigned long find_iomem(char *driver, unsigned long *len_out)
{
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 0eae00b3e58..fc50d2f959d 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -4,19 +4,21 @@
* Licensed under the GPL
*/
-#include "linux/stddef.h"
-#include "linux/err.h"
-#include "linux/hardirq.h"
-#include "linux/mm.h"
-#include "linux/personality.h"
-#include "linux/proc_fs.h"
-#include "linux/ptrace.h"
-#include "linux/random.h"
-#include "linux/sched.h"
-#include "linux/tick.h"
-#include "linux/threads.h"
-#include "asm/pgtable.h"
-#include "asm/uaccess.h"
+#include <linux/stddef.h>
+#include <linux/err.h>
+#include <linux/hardirq.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/personality.h>
+#include <linux/proc_fs.h>
+#include <linux/ptrace.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+#include <linux/threads.h>
+#include <asm/current.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
#include "as-layout.h"
#include "kern_util.h"
#include "os.h"
@@ -30,7 +32,7 @@
*/
struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
-static inline int external_pid(struct task_struct *task)
+static inline int external_pid(void)
{
/* FIXME: Need to look up userspace_pid by cpu */
return userspace_pid[0];
@@ -40,7 +42,7 @@ int pid_to_processor_id(int pid)
{
int i;
- for(i = 0; i < ncpus; i++) {
+ for (i = 0; i < ncpus; i++) {
if (cpu_tasks[i].pid == pid)
return i;
}
@@ -60,8 +62,6 @@ unsigned long alloc_stack(int order, int atomic)
if (atomic)
flags = GFP_ATOMIC;
page = __get_free_pages(flags, order);
- if (page == 0)
- return 0;
return page;
}
@@ -80,15 +80,15 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
static inline void set_current(struct task_struct *task)
{
cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
- { external_pid(task), task });
+ { external_pid(), task });
}
-extern void arch_switch_to(struct task_struct *from, struct task_struct *to);
+extern void arch_switch_to(struct task_struct *to);
void *_switch_to(void *prev, void *next, void *last)
{
struct task_struct *from = prev;
- struct task_struct *to= next;
+ struct task_struct *to = next;
to->thread.prev_sched = from;
set_current(to);
@@ -99,13 +99,13 @@ void *_switch_to(void *prev, void *next, void *last)
switch_threads(&from->thread.switch_buf,
&to->thread.switch_buf);
- arch_switch_to(current->thread.prev_sched, current);
+ arch_switch_to(current);
if (current->thread.saved_task)
show_regs(&(current->thread.regs));
- next= current->thread.saved_task;
- prev= current;
- } while(current->thread.saved_task);
+ to = current->thread.saved_task;
+ from = current;
+ } while (current->thread.saved_task);
return current->thread.prev_sched;
@@ -163,8 +163,6 @@ void new_thread_handler(void)
void fork_handler(void)
{
force_flush_all();
- if (current->thread.prev_sched == NULL)
- panic("blech");
schedule_tail(current->thread.prev_sched);
@@ -173,7 +171,7 @@ void fork_handler(void)
* arch_switch_to isn't needed. We could want to apply this to
* improve performance. -bb
*/
- arch_switch_to(current->thread.prev_sched, current);
+ arch_switch_to(current);
current->thread.prev_sched = NULL;
@@ -204,7 +202,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
arch_copy_thread(&current->thread.arch, &p->thread.arch);
}
else {
- init_thread_registers(&p->thread.regs.regs);
+ get_safe_registers(p->thread.regs.regs.gp);
p->thread.request.u.thread = current->thread.request.u.thread;
handler = new_thread_handler;
}
@@ -237,7 +235,7 @@ void default_idle(void)
{
unsigned long long nsecs;
- while(1) {
+ while (1) {
/* endless idle loop with no priority at all */
/*
@@ -256,57 +254,10 @@ void default_idle(void)
void cpu_idle(void)
{
- cpu_tasks[current_thread->cpu].pid = os_getpid();
+ cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
default_idle();
}
-void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
- pte_t *pte_out)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- pte_t ptent;
-
- if (task->mm == NULL)
- return ERR_PTR(-EINVAL);
- pgd = pgd_offset(task->mm, addr);
- if (!pgd_present(*pgd))
- return ERR_PTR(-EINVAL);
-
- pud = pud_offset(pgd, addr);
- if (!pud_present(*pud))
- return ERR_PTR(-EINVAL);
-
- pmd = pmd_offset(pud, addr);
- if (!pmd_present(*pmd))
- return ERR_PTR(-EINVAL);
-
- pte = pte_offset_kernel(pmd, addr);
- ptent = *pte;
- if (!pte_present(ptent))
- return ERR_PTR(-EINVAL);
-
- if (pte_out != NULL)
- *pte_out = ptent;
- return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);
-}
-
-char *current_cmd(void)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
- return "(Unknown)";
-#else
- void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
- return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
-#endif
-}
-
-void dump_thread(struct pt_regs *regs, struct user *u)
-{
-}
-
int __cant_sleep(void) {
return in_atomic() || irqs_disabled() || in_interrupt();
/* Is in_interrupt() really needed? */
@@ -317,7 +268,7 @@ int user_context(unsigned long sp)
unsigned long stack;
stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
- return stack != (unsigned long) current_thread;
+ return stack != (unsigned long) current_thread_info();
}
extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
@@ -331,7 +282,7 @@ void do_uml_exitcalls(void)
(*call)();
}
-char *uml_strdup(char *string)
+char *uml_strdup(const char *string)
{
return kstrdup(string, GFP_KERNEL);
}
@@ -359,7 +310,7 @@ int strlen_user_proc(char __user *str)
int smp_sigio_handler(void)
{
#ifdef CONFIG_SMP
- int cpu = current_thread->cpu;
+ int cpu = current_thread_info()->cpu;
IPI_handler(cpu);
if (cpu != 0)
return 1;
@@ -369,7 +320,7 @@ int smp_sigio_handler(void)
int cpu(void)
{
- return current_thread->cpu;
+ return current_thread_info()->cpu;
}
static atomic_t using_sysemu = ATOMIC_INIT(0);
@@ -435,7 +386,7 @@ int singlestepping(void * t)
{
struct task_struct *task = t ? t : current;
- if ( ! (task->ptrace & PT_DTRACE) )
+ if (!(task->ptrace & PT_DTRACE))
return 0;
if (task->thread.singlestep_syscall)
@@ -459,3 +410,46 @@ unsigned long arch_align_stack(unsigned long sp)
return sp & ~0xf;
}
#endif
+
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long stack_page, sp, ip;
+ bool seen_sched = 0;
+
+ if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING))
+ return 0;
+
+ stack_page = (unsigned long) task_stack_page(p);
+ /* Bail if the process has no kernel stack for some reason */
+ if (stack_page == 0)
+ return 0;
+
+ sp = p->thread.switch_buf->JB_SP;
+ /*
+ * Bail if the stack pointer is below the bottom of the kernel
+ * stack for some reason
+ */
+ if (sp < stack_page)
+ return 0;
+
+ while (sp < stack_page + THREAD_SIZE) {
+ ip = *((unsigned long *) sp);
+ if (in_sched_functions(ip))
+ /* Ignore everything until we're above the scheduler */
+ seen_sched = 1;
+ else if (kernel_text_address(ip) && seen_sched)
+ return ip;
+
+ sp += sizeof(unsigned long);
+ }
+
+ return 0;
+}
+
+int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
+{
+ int cpu = current_thread_info()->cpu;
+
+ return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
+}
+
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 04cebcf0679..00197d3d21e 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -4,6 +4,7 @@
*/
#include "linux/sched.h"
+#include "kern_util.h"
#include "os.h"
#include "skas.h"
@@ -11,7 +12,7 @@ void (*pm_power_off)(void);
static void kill_off_processes(void)
{
- if(proc_mm)
+ if (proc_mm)
/*
* FIXME: need to loop over userspace_pids
*/
@@ -21,8 +22,8 @@ static void kill_off_processes(void)
int pid, me;
me = os_getpid();
- for_each_process(p){
- if(p->mm == NULL)
+ for_each_process(p) {
+ if (p->mm == NULL)
continue;
pid = p->mm->context.id.u.pid;
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
index 89f9866a135..2b272b63b51 100644
--- a/arch/um/kernel/sigio.c
+++ b/arch/um/kernel/sigio.c
@@ -1,18 +1,12 @@
/*
- * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/list.h"
-#include "linux/slab.h"
-#include "linux/signal.h"
-#include "linux/interrupt.h"
-#include "init.h"
-#include "sigio.h"
-#include "irq_user.h"
+#include <linux/interrupt.h>
#include "irq_kern.h"
#include "os.h"
+#include "sigio.h"
/* Protected by sigio_lock() called from write_sigio_workaround */
static int sigio_irq_fd = -1;
@@ -33,9 +27,9 @@ int write_sigio_irq(int fd)
err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio",
NULL);
- if(err){
- printk("write_sigio_irq : um_request_irq failed, err = %d\n",
- err);
+ if (err) {
+ printk(KERN_ERR "write_sigio_irq : um_request_irq failed, "
+ "err = %d\n", err);
return -1;
}
sigio_irq_fd = fd;
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 19cb9773393..b0fce720c4d 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -3,12 +3,12 @@
* Licensed under the GPL
*/
-#include "linux/module.h"
-#include "linux/ptrace.h"
-#include "linux/sched.h"
-#include "asm/siginfo.h"
-#include "asm/signal.h"
-#include "asm/unistd.h"
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <asm/siginfo.h>
+#include <asm/signal.h>
+#include <asm/unistd.h>
#include "frame_kern.h"
#include "kern_util.h"
#include "sigcontext.h"
@@ -36,7 +36,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
/* Did we come from a system call? */
if (PT_REGS_SYSCALL_NR(regs) >= 0) {
/* If so, check system call restarting.. */
- switch(PT_REGS_SYSCALL_RET(regs)) {
+ switch (PT_REGS_SYSCALL_RET(regs)) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
PT_REGS_SYSCALL_RET(regs) = -EINTR;
@@ -116,7 +116,7 @@ static int kern_do_signal(struct pt_regs *regs)
/* Did we come from a system call? */
if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) {
/* Restart the system call - no handlers present */
- switch(PT_REGS_SYSCALL_RET(regs)) {
+ switch (PT_REGS_SYSCALL_RET(regs)) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index 8d07a7acb90..2c8583c1a34 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -1,17 +1,20 @@
-#include <sched.h>
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
#include <signal.h>
-#include <sys/mman.h>
-#include <sys/time.h>
+#include <sched.h>
#include <asm/unistd.h>
+#include <sys/time.h>
#include "as-layout.h"
+#include "kern_constants.h"
#include "ptrace_user.h"
-#include "skas.h"
#include "stub-data.h"
-#include "uml-config.h"
#include "sysdep/stub.h"
-#include "kern_constants.h"
-/* This is in a separate file because it needs to be compiled with any
+/*
+ * This is in a separate file because it needs to be compiled with any
* extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
*
* Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize
@@ -26,25 +29,26 @@ stub_clone_handler(void)
err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *));
- if(err != 0)
+ if (err != 0)
goto out;
err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
- if(err)
+ if (err)
goto out;
- err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
+ err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
(long) &data->timer, 0);
- if(err)
+ if (err)
goto out;
remap_stack(data->fd, data->offset);
goto done;
out:
- /* save current result.
- * Parent: pid;
- * child: retcode of mmap already saved and it jumps around this
+ /*
+ * save current result.
+ * Parent: pid;
+ * child: retcode of mmap already saved and it jumps around this
* assignment
*/
data->err = err;
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index f859ec306cd..0cd9a7a05e7 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -34,33 +34,14 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
if (!pte)
goto out_pte;
- /*
- * There's an interaction between the skas0 stub pages, stack
- * randomization, and the BUG at the end of exit_mmap. exit_mmap
- * checks that the number of page tables freed is the same as had
- * been allocated. If the stack is on the last page table page,
- * then the stack pte page will be freed, and if not, it won't. To
- * avoid having to know where the stack is, or if the process mapped
- * something at the top of its address space for some other reason,
- * we set TASK_SIZE to end at the start of the last page table.
- * This keeps exit_mmap off the last page, but introduces a leak
- * of that page. So, we hang onto it here and free it in
- * destroy_context_skas.
- */
-
- mm->context.last_page_table = pmd_page_vaddr(*pmd);
-#ifdef CONFIG_3_LEVEL_PGTABLES
- mm->context.last_pmd = (unsigned long) __va(pud_val(*pud));
-#endif
-
*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
*pte = pte_mkread(*pte);
return 0;
out_pmd:
- pud_free(pud);
+ pud_free(mm, pud);
out_pte:
- pmd_free(pmd);
+ pmd_free(mm, pmd);
out:
return -ENOMEM;
}
@@ -76,24 +57,6 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
stack = get_zeroed_page(GFP_KERNEL);
if (stack == 0)
goto out;
-
- /*
- * This zeros the entry that pgd_alloc didn't, needed since
- * we are about to reinitialize it, and want mm.nr_ptes to
- * be accurate.
- */
- mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);
-
- ret = init_stub_pte(mm, STUB_CODE,
- (unsigned long) &__syscall_stub_start);
- if (ret)
- goto out_free;
-
- ret = init_stub_pte(mm, STUB_DATA, stack);
- if (ret)
- goto out_free;
-
- mm->nr_ptes--;
}
to_mm->id.stack = stack;
@@ -114,6 +77,11 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
to_mm->id.u.pid = copy_context_skas0(stack,
from_mm->id.u.pid);
else to_mm->id.u.pid = start_userspace(stack);
+
+ if (to_mm->id.u.pid < 0) {
+ ret = to_mm->id.u.pid;
+ goto out_free;
+ }
}
ret = init_new_ldt(to_mm, from_mm);
@@ -123,6 +91,8 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
goto out_free;
}
+ to_mm->stub_pages = NULL;
+
return 0;
out_free:
@@ -132,24 +102,90 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
return ret;
}
+void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+{
+ struct page **pages;
+ int err, ret;
+
+ if (!skas_needs_stub)
+ return;
+
+ ret = init_stub_pte(mm, STUB_CODE,
+ (unsigned long) &__syscall_stub_start);
+ if (ret)
+ goto out;
+
+ ret = init_stub_pte(mm, STUB_DATA, mm->context.id.stack);
+ if (ret)
+ goto out;
+
+ pages = kmalloc(2 * sizeof(struct page *), GFP_KERNEL);
+ if (pages == NULL) {
+ printk(KERN_ERR "arch_dup_mmap failed to allocate 2 page "
+ "pointers\n");
+ goto out;
+ }
+
+ pages[0] = virt_to_page(&__syscall_stub_start);
+ pages[1] = virt_to_page(mm->context.id.stack);
+ mm->context.stub_pages = pages;
+
+ /* dup_mmap already holds mmap_sem */
+ err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START,
+ VM_READ | VM_MAYREAD | VM_EXEC |
+ VM_MAYEXEC | VM_DONTCOPY, pages);
+ if (err) {
+ printk(KERN_ERR "install_special_mapping returned %d\n", err);
+ goto out_free;
+ }
+ return;
+
+out_free:
+ kfree(pages);
+out:
+ force_sigsegv(SIGSEGV, current);
+}
+
+void arch_exit_mmap(struct mm_struct *mm)
+{
+ pte_t *pte;
+
+ if (mm->context.stub_pages != NULL)
+ kfree(mm->context.stub_pages);
+ pte = virt_to_pte(mm, STUB_CODE);
+ if (pte != NULL)
+ pte_clear(mm, STUB_CODE, pte);
+
+ pte = virt_to_pte(mm, STUB_DATA);
+ if (pte == NULL)
+ return;
+
+ pte_clear(mm, STUB_DATA, pte);
+}
+
void destroy_context(struct mm_struct *mm)
{
struct mm_context *mmu = &mm->context;
if (proc_mm)
os_close_file(mmu->id.u.mm_fd);
- else
+ else {
+ /*
+ * If init_new_context wasn't called, this will be
+ * zero, resulting in a kill(0), which will result in the
+ * whole UML suddenly dying. Also, cover negative and
+ * 1 cases, since they shouldn't happen either.
+ */
+ if (mmu->id.u.pid < 2) {
+ printk(KERN_ERR "corrupt mm_context - pid = %d\n",
+ mmu->id.u.pid);
+ return;
+ }
os_kill_ptraced_process(mmu->id.u.pid, 1);
+ }
- if (!proc_mm || !ptrace_faultinfo) {
+ if (skas_needs_stub)
free_page(mmu->id.stack);
- pte_lock_deinit(virt_to_page(mmu->last_page_table));
- pte_free_kernel((pte_t *) mmu->last_page_table);
- dec_zone_page_state(virt_to_page(mmu->last_page_table), NR_PAGETABLE);
-#ifdef CONFIG_3_LEVEL_PGTABLES
- pmd_free((pmd_t *) mmu->last_pmd);
-#endif
- }
free_ldt(mmu);
}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index fce389c2342..2e9852c0d48 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -6,19 +6,25 @@
#include "linux/init.h"
#include "linux/sched.h"
#include "as-layout.h"
+#include "kern.h"
#include "os.h"
#include "skas.h"
int new_mm(unsigned long stack)
{
- int fd;
+ int fd, err;
fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
if (fd < 0)
return fd;
- if (skas_needs_stub)
- map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
+ if (skas_needs_stub) {
+ err = map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
+ if (err) {
+ os_close_file(fd);
+ return err;
+ }
+ }
return fd;
}
@@ -49,8 +55,14 @@ int __init start_uml(void)
{
stack_protections((unsigned long) &cpu0_irqstack);
set_sigstack(cpu0_irqstack, THREAD_SIZE);
- if (proc_mm)
+ if (proc_mm) {
userspace_pid[0] = start_userspace(0);
+ if (userspace_pid[0] < 0) {
+ printf("start_uml - start_userspace returned %d\n",
+ userspace_pid[0]);
+ exit(1);
+ }
+ }
init_new_thread_signals();
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
index 50b476f2b38..4e3b820bd2b 100644
--- a/arch/um/kernel/skas/syscall.c
+++ b/arch/um/kernel/skas/syscall.c
@@ -9,6 +9,9 @@
#include "sysdep/ptrace.h"
#include "sysdep/syscalls.h"
+extern int syscall_table_size;
+#define NR_syscalls (syscall_table_size / sizeof(void *))
+
void handle_syscall(struct uml_pt_regs *r)
{
struct pt_regs *regs = container_of(r, struct pt_regs, regs);
@@ -17,9 +20,6 @@ void handle_syscall(struct uml_pt_regs *r)
syscall_trace(r, 0);
- current->thread.nsyscalls++;
- nsyscalls++;
-
/*
* This should go in the declaration of syscall, but when I do that,
* strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 1d8b119f2d0..e22c96993db 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -3,128 +3,130 @@
* Licensed under the GPL
*/
-#include "linux/err.h"
-#include "linux/highmem.h"
-#include "linux/mm.h"
-#include "asm/current.h"
-#include "asm/page.h"
-#include "asm/pgtable.h"
+#include <linux/err.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
#include "kern_util.h"
#include "os.h"
-extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
- pte_t *pte_out);
-
-static unsigned long maybe_map(unsigned long virt, int is_write)
+pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr)
{
- pte_t pte;
- int err;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ if (mm == NULL)
+ return NULL;
+
+ pgd = pgd_offset(mm, addr);
+ if (!pgd_present(*pgd))
+ return NULL;
+
+ pud = pud_offset(pgd, addr);
+ if (!pud_present(*pud))
+ return NULL;
- void *phys = um_virt_to_phys(current, virt, &pte);
- int dummy_code;
+ pmd = pmd_offset(pud, addr);
+ if (!pmd_present(*pmd))
+ return NULL;
+
+ return pte_offset_kernel(pmd, addr);
+}
+
+static pte_t *maybe_map(unsigned long virt, int is_write)
+{
+ pte_t *pte = virt_to_pte(current->mm, virt);
+ int err, dummy_code;
- if (IS_ERR(phys) || (is_write && !pte_write(pte))) {
+ if ((pte == NULL) || !pte_present(*pte) ||
+ (is_write && !pte_write(*pte))) {
err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
if (err)
- return -1UL;
- phys = um_virt_to_phys(current, virt, NULL);
+ return NULL;
+ pte = virt_to_pte(current->mm, virt);
}
- if (IS_ERR(phys))
- phys = (void *) -1;
+ if (!pte_present(*pte))
+ pte = NULL;
- return (unsigned long) phys;
+ return pte;
}
static int do_op_one_page(unsigned long addr, int len, int is_write,
int (*op)(unsigned long addr, int len, void *arg), void *arg)
{
+ jmp_buf buf;
struct page *page;
- int n;
+ pte_t *pte;
+ int n, faulted;
- addr = maybe_map(addr, is_write);
- if (addr == -1UL)
+ pte = maybe_map(addr, is_write);
+ if (pte == NULL)
return -1;
- page = phys_to_page(addr);
+ page = pte_page(*pte);
addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) +
(addr & ~PAGE_MASK);
- n = (*op)(addr, len, arg);
+ current->thread.fault_catcher = &buf;
+
+ faulted = UML_SETJMP(&buf);
+ if (faulted == 0)
+ n = (*op)(addr, len, arg);
+ else
+ n = -1;
+
+ current->thread.fault_catcher = NULL;
kunmap_atomic(page, KM_UML_USERCOPY);
return n;
}
-static void do_buffer_op(void *jmpbuf, void *arg_ptr)
+static int buffer_op(unsigned long addr, int len, int is_write,
+ int (*op)(unsigned long, int, void *), void *arg)
{
- va_list args;
- unsigned long addr;
- int len, is_write, size, remain, n;
- int (*op)(unsigned long, int, void *);
- void *arg;
- int *res;
-
- va_copy(args, *(va_list *)arg_ptr);
- addr = va_arg(args, unsigned long);
- len = va_arg(args, int);
- is_write = va_arg(args, int);
- op = va_arg(args, void *);
- arg = va_arg(args, void *);
- res = va_arg(args, int *);
- va_end(args);
+ int size, remain, n;
+
size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
remain = len;
- current->thread.fault_catcher = jmpbuf;
n = do_op_one_page(addr, size, is_write, op, arg);
if (n != 0) {
- *res = (n < 0 ? remain : 0);
+ remain = (n < 0 ? remain : 0);
goto out;
}
addr += size;
remain -= size;
- if (remain == 0) {
- *res = 0;
+ if (remain == 0)
goto out;
- }
- while(addr < ((addr + remain) & PAGE_MASK)) {
+ while (addr < ((addr + remain) & PAGE_MASK)) {
n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg);
if (n != 0) {
- *res = (n < 0 ? remain : 0);
+ remain = (n < 0 ? remain : 0);
goto out;
}
addr += PAGE_SIZE;
remain -= PAGE_SIZE;
}
- if (remain == 0) {
- *res = 0;
+ if (remain == 0)
goto out;
- }
n = do_op_one_page(addr, remain, is_write, op, arg);
- if (n != 0)
- *res = (n < 0 ? remain : 0);
- else *res = 0;
- out:
- current->thread.fault_catcher = NULL;
-}
-
-static int buffer_op(unsigned long addr, int len, int is_write,
- int (*op)(unsigned long addr, int len, void *arg),
- void *arg)
-{
- int faulted, res;
-
- faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
- &res);
- if (!faulted)
- return res;
+ if (n != 0) {
+ remain = (n < 0 ? remain : 0);
+ goto out;
+ }
- return addr + len - (unsigned long) current->thread.fault_addr;
+ return 0;
+ out:
+ return remain;
}
static int copy_chunk_from_user(unsigned long from, int len, void *arg)
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index 36d89cf8d20..e1062ec36d4 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -21,7 +21,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
#include "asm/smp.h"
#include "asm/processor.h"
#include "asm/spinlock.h"
-#include "kern_util.h"
#include "kern.h"
#include "irq_user.h"
#include "os.h"
@@ -61,7 +60,7 @@ void smp_send_stop(void)
continue;
os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
}
- printk(KERN_INFO "done\n");
+ printk(KERN_CONT "done\n");
}
static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
@@ -75,8 +74,7 @@ static int idle_proc(void *cpup)
if (err < 0)
panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
- os_set_fd_async(cpu_data[cpu].ipi_pipe[0],
- current->thread.mode.tt.extern_pid);
+ os_set_fd_async(cpu_data[cpu].ipi_pipe[0]);
wmb();
if (cpu_test_and_set(cpu, cpu_callin_map)) {
@@ -129,8 +127,7 @@ void smp_prepare_cpus(unsigned int maxcpus)
if (err < 0)
panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
- os_set_fd_async(cpu_data[me].ipi_pipe[0],
- current->thread.mode.tt.extern_pid);
+ os_set_fd_async(cpu_data[me].ipi_pipe[0]);
for (cpu = 1; cpu < ncpus; cpu++) {
printk(KERN_INFO "Booting processor %d...\n", cpu);
@@ -143,9 +140,8 @@ void smp_prepare_cpus(unsigned int maxcpus)
while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
cpu_relax();
- if (cpu_isset(cpu, cpu_callin_map))
- printk(KERN_INFO "done\n");
- else printk(KERN_INFO "failed\n");
+ printk(KERN_INFO "%s\n",
+ cpu_isset(cpu, cpu_calling_map) ? "done" : "failed");
}
}
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index b9d92b2089a..9cffc628a37 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -13,9 +13,6 @@
#include "asm/uaccess.h"
#include "asm/unistd.h"
-/* Unlocked, I don't care if this is a bit off */
-int nsyscalls = 0;
-
long sys_fork(void)
{
long ret;
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 93263571d81..56d43d0a396 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -1,38 +1,37 @@
-/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/kernel.h"
-#include "linux/module.h"
-#include "linux/kallsyms.h"
-#include "asm/page.h"
-#include "asm/processor.h"
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
#include "sysrq.h"
/* Catch non-i386 SUBARCH's. */
#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
void show_trace(struct task_struct *task, unsigned long * stack)
{
- unsigned long addr;
+ unsigned long addr;
- if (!stack) {
+ if (!stack) {
stack = (unsigned long*) &stack;
WARN_ON(1);
}
- printk("Call Trace: \n");
- while (((long) stack & (THREAD_SIZE-1)) != 0) {
- addr = *stack;
+ printk(KERN_INFO "Call Trace: \n");
+ while (((long) stack & (THREAD_SIZE-1)) != 0) {
+ addr = *stack;
if (__kernel_text_address(addr)) {
- printk("%08lx: [<%08lx>]", (unsigned long) stack, addr);
- print_symbol(" %s", addr);
- printk("\n");
- }
- stack++;
- }
- printk("\n");
+ printk(KERN_INFO "%08lx: [<%08lx>]",
+ (unsigned long) stack, addr);
+ print_symbol(KERN_CONT " %s", addr);
+ printk(KERN_CONT "\n");
+ }
+ stack++;
+ }
+ printk(KERN_INFO "\n");
}
#endif
@@ -67,14 +66,13 @@ void show_stack(struct task_struct *task, unsigned long *esp)
}
stack = esp;
- for(i = 0; i < kstack_depth_to_print; i++) {
+ for (i = 0; i < kstack_depth_to_print; i++) {
if (kstack_end(stack))
break;
if (i && ((i % 8) == 0))
- printk("\n ");
+ printk("\n" KERN_INFO " ");
printk("%08lx ", *stack++);
}
- printk("Call Trace: \n");
show_trace(task, esp);
}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 1ac746a9eae..e066e84493b 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -3,12 +3,12 @@
* Licensed under the GPL
*/
-#include "linux/clockchips.h"
-#include "linux/interrupt.h"
-#include "linux/jiffies.h"
-#include "linux/threads.h"
-#include "asm/irq.h"
-#include "asm/param.h"
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/threads.h>
+#include <asm/irq.h>
+#include <asm/param.h>
#include "kern_util.h"
#include "os.h"
@@ -32,7 +32,7 @@ void timer_handler(int sig, struct uml_pt_regs *regs)
static void itimer_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- switch(mode) {
+ switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
set_interval();
break;
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index f4a0e407eee..d175d0566af 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -3,9 +3,10 @@
* Licensed under the GPL
*/
-#include "linux/mm.h"
-#include "asm/pgtable.h"
-#include "asm/tlbflush.h"
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
#include "as-layout.h"
#include "mem_user.h"
#include "os.h"
@@ -56,7 +57,7 @@ static int do_ops(struct host_vm_change *hvc, int end,
for (i = 0; i < end && !ret; i++) {
op = &hvc->ops[i];
- switch(op->type) {
+ switch (op->type) {
case MMAP:
ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len,
op->u.mmap.prot, op->u.mmap.fd,
@@ -183,27 +184,30 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
pte = pte_offset_kernel(pmd, addr);
do {
+ if ((addr >= STUB_START) && (addr < STUB_END))
+ continue;
+
r = pte_read(*pte);
w = pte_write(*pte);
x = pte_exec(*pte);
if (!pte_young(*pte)) {
r = 0;
w = 0;
- } else if (!pte_dirty(*pte)) {
+ } else if (!pte_dirty(*pte))
w = 0;
- }
+
prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
(x ? UM_PROT_EXEC : 0));
if (hvc->force || pte_newpage(*pte)) {
if (pte_present(*pte))
ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
PAGE_SIZE, prot, hvc);
- else ret = add_munmap(addr, PAGE_SIZE, hvc);
- }
- else if (pte_newprot(*pte))
+ else
+ ret = add_munmap(addr, PAGE_SIZE, hvc);
+ } else if (pte_newprot(*pte))
ret = add_mprotect(addr, PAGE_SIZE, prot, hvc);
*pte = pte_mkuptodate(*pte);
- } while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret));
+ } while (pte++, addr += PAGE_SIZE, ((addr < end) && !ret));
return ret;
}
@@ -225,7 +229,7 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr,
}
}
else ret = update_pte_range(pmd, addr, next, hvc);
- } while (pmd++, addr = next, ((addr != end) && !ret));
+ } while (pmd++, addr = next, ((addr < end) && !ret));
return ret;
}
@@ -247,7 +251,7 @@ static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
}
}
else ret = update_pmd_range(pud, addr, next, hvc);
- } while (pud++, addr = next, ((addr != end) && !ret));
+ } while (pud++, addr = next, ((addr < end) && !ret));
return ret;
}
@@ -270,7 +274,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
}
}
else ret = update_pud_range(pgd, addr, next, &hvc);
- } while (pgd++, addr = next, ((addr != end_addr) && !ret));
+ } while (pgd++, addr = next, ((addr < end_addr) && !ret));
if (!ret)
ret = do_ops(&hvc, hvc.index, 1);
@@ -485,9 +489,6 @@ void __flush_tlb_one(unsigned long addr)
static void fix_range(struct mm_struct *mm, unsigned long start_addr,
unsigned long end_addr, int force)
{
- if (!proc_mm && (end_addr > STUB_START))
- end_addr = STUB_START;
-
fix_range_common(mm, start_addr, end_addr, force);
}
@@ -499,10 +500,9 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
else fix_range(vma->vm_mm, start, end, 0);
}
-void flush_tlb_mm(struct mm_struct *mm)
+void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
{
- unsigned long end;
-
/*
* Don't bother flushing if this address space is about to be
* destroyed.
@@ -510,8 +510,17 @@ void flush_tlb_mm(struct mm_struct *mm)
if (atomic_read(&mm->mm_users) == 0)
return;
- end = proc_mm ? task_size : STUB_START;
- fix_range(mm, 0, end, 0);
+ fix_range(mm, start, end, 0);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+ struct vm_area_struct *vma = mm->mmap;
+
+ while (vma != NULL) {
+ fix_range(mm, vma->vm_start, vma->vm_end, 0);
+ vma = vma->vm_next;
+ }
}
void force_flush_all(void)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index cb3321f8e0a..44e49041949 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -13,6 +13,7 @@
#include "as-layout.h"
#include "kern_util.h"
#include "os.h"
+#include "skas.h"
#include "sysdep/sigcontext.h"
/*
@@ -128,7 +129,19 @@ static void bad_segv(struct faultinfo fi, unsigned long ip)
force_sig_info(SIGSEGV, &si, current);
}
-static void segv_handler(int sig, struct uml_pt_regs *regs)
+void fatal_sigsegv(void)
+{
+ force_sigsegv(SIGSEGV, current);
+ do_signal();
+ /*
+ * This is to tell gcc that we're not returning - do_signal
+ * can, in general, return, but in this case, it's not, since
+ * we just got a fatal SIGSEGV queued.
+ */
+ os_dump_core();
+}
+
+void segv_handler(int sig, struct uml_pt_regs *regs)
{
struct faultinfo * fi = UPT_FAULTINFO(regs);
@@ -216,9 +229,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
void relay_signal(int sig, struct uml_pt_regs *regs)
{
- if (arch_handle_signal(sig, regs))
- return;
-
if (!UPT_IS_USER(regs)) {
if (sig == SIGBUS)
printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "
@@ -226,31 +236,24 @@ void relay_signal(int sig, struct uml_pt_regs *regs)
panic("Kernel mode signal %d", sig);
}
+ arch_examine_signal(sig, regs);
+
current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
force_sig(sig, current);
}
-static void bus_handler(int sig, struct uml_pt_regs *regs)
+void bus_handler(int sig, struct uml_pt_regs *regs)
{
if (current->thread.fault_catcher != NULL)
UML_LONGJMP(current->thread.fault_catcher, 1);
else relay_signal(sig, regs);
}
-static void winch(int sig, struct uml_pt_regs *regs)
+void winch(int sig, struct uml_pt_regs *regs)
{
do_IRQ(WINCH_IRQ, regs);
}
-const struct kern_handlers handlinfo_kern = {
- .relay_signal = relay_signal,
- .winch = winch,
- .bus_handler = bus_handler,
- .page_fault = segv_handler,
- .sigio_handler = sigio_handler,
- .timer_handler = timer_handler
-};
-
void trap_init(void)
{
}
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
index d7436aacd26..f0f4b040d7c 100644
--- a/arch/um/kernel/uaccess.c
+++ b/arch/um/kernel/uaccess.c
@@ -1,10 +1,11 @@
/*
* Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-/* These are here rather than tt/uaccess.c because skas mode needs them in
+/*
+ * These are here rather than tt/uaccess.c because skas mode needs them in
* order to do SIGBUS recovery when a tmpfs mount runs out of room.
*/
@@ -25,6 +26,8 @@ int __do_copy_to_user(void *to, const void *from, int n,
fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
__do_copy, &faulted);
- if(!faulted) return(0);
- else return(n - (fault - (unsigned long) to));
+ if (!faulted)
+ return 0;
+ else
+ return n - (fault - (unsigned long) to);
}
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index f1c71393f57..a6c1dd1cf5a 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -3,22 +3,23 @@
* Licensed under the GPL
*/
-#include "linux/delay.h"
-#include "linux/mm.h"
-#include "linux/module.h"
-#include "linux/seq_file.h"
-#include "linux/string.h"
-#include "linux/utsname.h"
-#include "asm/pgtable.h"
-#include "asm/processor.h"
-#include "asm/setup.h"
-#include "arch.h"
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <linux/utsname.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/setup.h>
#include "as-layout.h"
+#include "arch.h"
#include "init.h"
#include "kern.h"
+#include "kern_util.h"
#include "mem_user.h"
#include "os.h"
-#include "skas.h"
#define DEFAULT_COMMAND_LINE "root=98:0"
@@ -100,8 +101,6 @@ const struct seq_operations cpuinfo_op = {
};
/* Set in linux_main */
-unsigned long host_task_size;
-unsigned long task_size;
unsigned long uml_physmem;
unsigned long uml_reserved; /* Also modified in mem_init */
unsigned long start_vm;
@@ -197,20 +196,19 @@ __uml_setup("--help", Usage,
" Prints this message.\n\n"
);
-static int __init uml_checksetup(char *line, int *add)
+static void __init uml_checksetup(char *line, int *add)
{
struct uml_param *p;
p = &__uml_setup_start;
- while(p < &__uml_setup_end) {
+ while (p < &__uml_setup_end) {
int n;
n = strlen(p->str);
if (!strncmp(line, p->str, n) && p->setup_func(line + n, add))
- return 1;
+ return;
p++;
}
- return 0;
}
static void __init uml_postsetup(void)
@@ -218,14 +216,36 @@ static void __init uml_postsetup(void)
initcall_t *p;
p = &__uml_postsetup_start;
- while(p < &__uml_postsetup_end) {
+ while (p < &__uml_postsetup_end) {
(*p)();
p++;
}
return;
}
+static int panic_exit(struct notifier_block *self, unsigned long unused1,
+ void *unused2)
+{
+ bust_spinlocks(1);
+ show_regs(&(current->thread.regs));
+ bust_spinlocks(0);
+ uml_exitcode = 1;
+ os_dump_core();
+ return 0;
+}
+
+static struct notifier_block panic_exit_notifier = {
+ .notifier_call = panic_exit,
+ .next = NULL,
+ .priority = 0
+};
+
/* Set during early boot */
+unsigned long task_size;
+EXPORT_SYMBOL(task_size);
+
+unsigned long host_task_size;
+
unsigned long brk_start;
unsigned long end_iomem;
EXPORT_SYMBOL(end_iomem);
@@ -234,20 +254,6 @@ EXPORT_SYMBOL(end_iomem);
extern char __binary_start;
-static unsigned long set_task_sizes_skas(unsigned long *task_size_out)
-{
- /* Round up to the nearest 4M */
- unsigned long host_task_size = ROUND_4M((unsigned long)
- &host_task_size);
-
- if (!skas_needs_stub)
- *task_size_out = host_task_size;
- else
- *task_size_out = STUB_START & PGDIR_MASK;
-
- return host_task_size;
-}
-
int __init linux_main(int argc, char **argv)
{
unsigned long avail, diff;
@@ -266,6 +272,13 @@ int __init linux_main(int argc, char **argv)
if (have_root == 0)
add_arg(DEFAULT_COMMAND_LINE);
+ host_task_size = os_get_task_size();
+ /*
+ * TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps
+ * out
+ */
+ task_size = host_task_size & PGDIR_MASK;
+
/* OS sanity checks that need to happen before the kernel runs */
os_early_checks();
@@ -278,13 +291,6 @@ int __init linux_main(int argc, char **argv)
printf("UML running in %s mode\n", mode);
- host_task_size = set_task_sizes_skas(&task_size);
-
- /*
- * Setting up handlers to 'sig_info' struct
- */
- os_fill_handlinfo(handlinfo_kern);
-
brk_start = (unsigned long) sbrk(0);
/*
@@ -309,7 +315,7 @@ int __init linux_main(int argc, char **argv)
highmem = 0;
iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
- max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
+ max_physmem = TASK_SIZE - uml_physmem - iomem_size - MIN_VMALLOC;
/*
* Zones have to begin on a 1 << MAX_ORDER page boundary,
@@ -341,7 +347,7 @@ int __init linux_main(int argc, char **argv)
}
virtmem_size = physmem_size;
- avail = get_kmem_end() - start_vm;
+ avail = TASK_SIZE - start_vm;
if (physmem_size > avail)
virtmem_size = avail;
end_vm = start_vm + virtmem_size;
@@ -350,6 +356,9 @@ int __init linux_main(int argc, char **argv)
printf("Kernel virtual memory size shrunk to %lu bytes\n",
virtmem_size);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &panic_exit_notifier);
+
uml_postsetup();
stack_protections((unsigned long) &init_thread_info);
@@ -358,29 +367,8 @@ int __init linux_main(int argc, char **argv)
return start_uml();
}
-extern int uml_exitcode;
-
-static int panic_exit(struct notifier_block *self, unsigned long unused1,
- void *unused2)
-{
- bust_spinlocks(1);
- show_regs(&(current->thread.regs));
- bust_spinlocks(0);
- uml_exitcode = 1;
- os_dump_core();
- return 0;
-}
-
-static struct notifier_block panic_exit_notifier = {
- .notifier_call = panic_exit,
- .next = NULL,
- .priority = 0
-};
-
void __init setup_arch(char **cmdline_p)
{
- atomic_notifier_chain_register(&panic_notifier_list,
- &panic_exit_notifier);
paging_init();
strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 039e16efcd5..81e07e2be3a 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -1,13 +1,12 @@
-/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include "asm/errno.h"
+#include <asm/errno.h>
#include "init.h"
-#include "os.h"
#include "kern.h"
-#include "linux/kernel.h"
+#include "os.h"
/* Changed by set_umid_arg */
static int umid_inited = 0;
@@ -16,16 +15,16 @@ static int __init set_umid_arg(char *name, int *add)
{
int err;
- if(umid_inited){
+ if (umid_inited) {
printf("umid already set\n");
return 0;
}
*add = 0;
err = set_umid(name);
- if(err == -EEXIST)
+ if (err == -EEXIST)
printf("umid '%s' already in use\n", name);
- else if(!err)
+ else if (!err)
umid_inited = 1;
return 0;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 8e129af8170..8a48d6a3006 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,7 +4,7 @@
#
obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
- registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \
+ registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
obj-$(CONFIG_TTY_LOG) += tty_log.o
@@ -12,7 +12,7 @@ user-objs-$(CONFIG_TTY_LOG) += tty_log.o
USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
- trap.o tty.o tls.o uaccess.o umid.o util.o
+ tty.o tls.o uaccess.o umid.o util.o
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 93dc0c80eba..57e3d46c989 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -12,6 +12,7 @@
#include "aio.h"
#include "init.h"
#include "kern_constants.h"
+#include "kern_util.h"
#include "os.h"
#include "user.h"
@@ -141,7 +142,7 @@ static int do_not_aio(struct aio_thread_req *req)
if (actual != req->offset)
return -errno;
- switch(req->type) {
+ switch (req->type) {
case AIO_READ:
n = read(req->io_fd, req->buf, req->len);
break;
diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c
index 04f11b9f1ac..046a131f610 100644
--- a/arch/um/os-Linux/drivers/ethertap_kern.c
+++ b/arch/um/os-Linux/drivers/ethertap_kern.c
@@ -6,7 +6,7 @@
* Licensed under the GPL.
*/
-#include "linux/init.h"
+#include <linux/init.h>
#include <linux/netdevice.h>
#include "etap.h"
#include "net_kern.h"
@@ -30,10 +30,10 @@ static void etap_init(struct net_device *dev, void *data)
epri->control_fd = -1;
epri->dev = dev;
- printk("ethertap backend - %s", epri->dev_name);
+ printk(KERN_INFO "ethertap backend - %s", epri->dev_name);
if (epri->gate_addr != NULL)
- printk(", IP = %s", epri->gate_addr);
- printk("\n");
+ printk(KERN_CONT ", IP = %s", epri->gate_addr);
+ printk(KERN_CONT "\n");
}
static int etap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 07ca0cb472a..6fb0b174f53 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -131,7 +131,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
}
if (c != 1) {
printk(UM_KERN_ERR "etap_tramp : uml_net failed\n");
- err = helper_wait(pid, 0, "uml_net");
+ err = helper_wait(pid);
}
return err;
}
diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c
index 9d384807b07..6b9e33d5de2 100644
--- a/arch/um/os-Linux/drivers/tuntap_kern.c
+++ b/arch/um/os-Linux/drivers/tuntap_kern.c
@@ -29,10 +29,10 @@ static void tuntap_init(struct net_device *dev, void *data)
tpri->fd = -1;
tpri->dev = dev;
- printk("TUN/TAP backend - ");
+ printk(KERN_INFO "TUN/TAP backend - ");
if (tpri->gate_addr != NULL)
- printk("IP = %s", tpri->gate_addr);
- printk("\n");
+ printk(KERN_CONT "IP = %s", tpri->gate_addr);
+ printk(KERN_CONT "\n");
}
static int tuntap_read(int fd, struct sk_buff *skb, struct uml_net_private *lp)
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 1037a3b6386..2448be03fd7 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -14,6 +14,7 @@
#include <sys/wait.h>
#include <sys/uio.h>
#include "kern_constants.h"
+#include "kern_util.h"
#include "os.h"
#include "tuntap.h"
#include "user.h"
@@ -107,7 +108,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
"errno = %d\n", errno);
return err;
}
- helper_wait(pid, 0, "tuntap_open_tramp");
+ helper_wait(pid);
cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg == NULL) {
@@ -148,7 +149,7 @@ static int tuntap_open(void *data)
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
- if (ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0) {
+ if (ioctl(pri->fd, TUNSETIFF, &ifr) < 0) {
err = -errno;
printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n",
errno);
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index f8346275862..b5afcfd0f86 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -8,18 +8,16 @@
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
-#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include "kern_constants.h"
#include "os.h"
#include "user.h"
-#include "kern_util.h"
-static void copy_stat(struct uml_stat *dst, struct stat64 *src)
+static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
{
*dst = ((struct uml_stat) {
.ust_dev = src->st_dev, /* device */
@@ -43,10 +41,10 @@ int os_stat_fd(const int fd, struct uml_stat *ubuf)
int err;
CATCH_EINTR(err = fstat64(fd, &sbuf));
- if(err < 0)
+ if (err < 0)
return -errno;
- if(ubuf != NULL)
+ if (ubuf != NULL)
copy_stat(ubuf, &sbuf);
return err;
}
@@ -56,27 +54,26 @@ int os_stat_file(const char *file_name, struct uml_stat *ubuf)
struct stat64 sbuf;
int err;
- do {
- err = stat64(file_name, &sbuf);
- } while((err < 0) && (errno == EINTR)) ;
-
- if(err < 0)
+ CATCH_EINTR(err = stat64(file_name, &sbuf));
+ if (err < 0)
return -errno;
- if(ubuf != NULL)
+ if (ubuf != NULL)
copy_stat(ubuf, &sbuf);
return err;
}
-int os_access(const char* file, int mode)
+int os_access(const char *file, int mode)
{
int amode, err;
- amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
- (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
+ amode = (mode & OS_ACC_R_OK ? R_OK : 0) |
+ (mode & OS_ACC_W_OK ? W_OK : 0) |
+ (mode & OS_ACC_X_OK ? X_OK : 0) |
+ (mode & OS_ACC_F_OK ? F_OK : 0);
err = access(file, amode);
- if(err < 0)
+ if (err < 0)
return -errno;
return 0;
@@ -88,7 +85,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
int err;
err = ioctl(fd, cmd, arg);
- if(err < 0)
+ if (err < 0)
return -errno;
return err;
@@ -97,7 +94,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
/* FIXME: ensure namebuf in os_get_if_name is big enough */
int os_get_ifname(int fd, char* namebuf)
{
- if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
+ if (ioctl(fd, SIOCGIFNAME, namebuf) < 0)
return -errno;
return 0;
@@ -108,37 +105,22 @@ int os_set_slip(int fd)
int disc, sencap;
disc = N_SLIP;
- if(ioctl(fd, TIOCSETD, &disc) < 0)
+ if (ioctl(fd, TIOCSETD, &disc) < 0)
return -errno;
sencap = 0;
- if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
+ if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
return -errno;
return 0;
}
-int os_set_owner(int fd, int pid)
-{
- if(fcntl(fd, F_SETOWN, pid) < 0){
- int save_errno = errno;
-
- if(fcntl(fd, F_GETOWN, 0) != pid)
- return -save_errno;
- }
-
- return 0;
-}
-
int os_mode_fd(int fd, int mode)
{
int err;
- do {
- err = fchmod(fd, mode);
- } while((err < 0) && (errno==EINTR)) ;
-
- if(err < 0)
+ CATCH_EINTR(err = fchmod(fd, mode));
+ if (err < 0)
return -errno;
return 0;
@@ -150,64 +132,73 @@ int os_file_type(char *file)
int err;
err = os_stat_file(file, &buf);
- if(err < 0)
+ if (err < 0)
return err;
- if(S_ISDIR(buf.ust_mode))
+ if (S_ISDIR(buf.ust_mode))
return OS_TYPE_DIR;
- else if(S_ISLNK(buf.ust_mode))
+ else if (S_ISLNK(buf.ust_mode))
return OS_TYPE_SYMLINK;
- else if(S_ISCHR(buf.ust_mode))
+ else if (S_ISCHR(buf.ust_mode))
return OS_TYPE_CHARDEV;
- else if(S_ISBLK(buf.ust_mode))
+ else if (S_ISBLK(buf.ust_mode))
return OS_TYPE_BLOCKDEV;
- else if(S_ISFIFO(buf.ust_mode))
+ else if (S_ISFIFO(buf.ust_mode))
return OS_TYPE_FIFO;
- else if(S_ISSOCK(buf.ust_mode))
+ else if (S_ISSOCK(buf.ust_mode))
return OS_TYPE_SOCK;
else return OS_TYPE_FILE;
}
-int os_file_mode(char *file, struct openflags *mode_out)
+int os_file_mode(const char *file, struct openflags *mode_out)
{
int err;
*mode_out = OPENFLAGS();
err = access(file, W_OK);
- if(err && (errno != EACCES))
+ if (err && (errno != EACCES))
return -errno;
- else if(!err)
+ else if (!err)
*mode_out = of_write(*mode_out);
err = access(file, R_OK);
- if(err && (errno != EACCES))
+ if (err && (errno != EACCES))
return -errno;
- else if(!err)
+ else if (!err)
*mode_out = of_read(*mode_out);
return err;
}
-int os_open_file(char *file, struct openflags flags, int mode)
+int os_open_file(const char *file, struct openflags flags, int mode)
{
int fd, err, f = 0;
- if(flags.r && flags.w) f = O_RDWR;
- else if(flags.r) f = O_RDONLY;
- else if(flags.w) f = O_WRONLY;
+ if (flags.r && flags.w)
+ f = O_RDWR;
+ else if (flags.r)
+ f = O_RDONLY;
+ else if (flags.w)
+ f = O_WRONLY;
else f = 0;
- if(flags.s) f |= O_SYNC;
- if(flags.c) f |= O_CREAT;
- if(flags.t) f |= O_TRUNC;
- if(flags.e) f |= O_EXCL;
+ if (flags.s)
+ f |= O_SYNC;
+ if (flags.c)
+ f |= O_CREAT;
+ if (flags.t)
+ f |= O_TRUNC;
+ if (flags.e)
+ f |= O_EXCL;
+ if (flags.a)
+ f |= O_APPEND;
fd = open64(file, f, mode);
- if(fd < 0)
+ if (fd < 0)
return -errno;
- if(flags.cl && fcntl(fd, F_SETFD, 1)){
+ if (flags.cl && fcntl(fd, F_SETFD, 1)) {
err = -errno;
close(fd);
return err;
@@ -216,7 +207,7 @@ int os_open_file(char *file, struct openflags flags, int mode)
return fd;
}
-int os_connect_socket(char *name)
+int os_connect_socket(const char *name)
{
struct sockaddr_un sock;
int fd, err;
@@ -225,13 +216,13 @@ int os_connect_socket(char *name)
snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if(fd < 0) {
+ if (fd < 0) {
err = -errno;
goto out;
}
err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
- if(err) {
+ if (err) {
err = -errno;
goto out_close;
}
@@ -254,7 +245,7 @@ int os_seek_file(int fd, unsigned long long offset)
unsigned long long actual;
actual = lseek64(fd, offset, SEEK_SET);
- if(actual != offset)
+ if (actual != offset)
return -errno;
return 0;
}
@@ -263,7 +254,7 @@ int os_read_file(int fd, void *buf, int len)
{
int n = read(fd, buf, len);
- if(n < 0)
+ if (n < 0)
return -errno;
return n;
}
@@ -272,37 +263,38 @@ int os_write_file(int fd, const void *buf, int len)
{
int n = write(fd, (void *) buf, len);
- if(n < 0)
+ if (n < 0)
return -errno;
return n;
}
-int os_file_size(char *file, unsigned long long *size_out)
+int os_file_size(const char *file, unsigned long long *size_out)
{
struct uml_stat buf;
int err;
err = os_stat_file(file, &buf);
- if(err < 0){
- printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
+ -err);
return err;
}
- if(S_ISBLK(buf.ust_mode)){
+ if (S_ISBLK(buf.ust_mode)) {
int fd;
long blocks;
fd = open(file, O_RDONLY, 0);
- if(fd < 0) {
+ if (fd < 0) {
err = -errno;
- printk("Couldn't open \"%s\", errno = %d\n", file,
- errno);
+ printk(UM_KERN_ERR "Couldn't open \"%s\", "
+ "errno = %d\n", file, errno);
return err;
}
- if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
+ if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
err = -errno;
- printk("Couldn't get the block size of \"%s\", "
- "errno = %d\n", file, errno);
+ printk(UM_KERN_ERR "Couldn't get the block size of "
+ "\"%s\", errno = %d\n", file, errno);
close(fd);
return err;
}
@@ -314,14 +306,15 @@ int os_file_size(char *file, unsigned long long *size_out)
return 0;
}
-int os_file_modtime(char *file, unsigned long *modtime)
+int os_file_modtime(const char *file, unsigned long *modtime)
{
struct uml_stat buf;
int err;
err = os_stat_file(file, &buf);
- if(err < 0){
- printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
+ -err);
return err;
}
@@ -329,26 +322,13 @@ int os_file_modtime(char *file, unsigned long *modtime)
return 0;
}
-int os_get_exec_close(int fd, int *close_on_exec)
-{
- int ret;
-
- CATCH_EINTR(ret = fcntl(fd, F_GETFD));
-
- if(ret < 0)
- return -errno;
-
- *close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0;
- return ret;
-}
-
int os_set_exec_close(int fd)
{
int err;
CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
- if(err < 0)
+ if (err < 0)
return -errno;
return err;
}
@@ -358,53 +338,51 @@ int os_pipe(int *fds, int stream, int close_on_exec)
int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
err = socketpair(AF_UNIX, type, 0, fds);
- if(err < 0)
+ if (err < 0)
return -errno;
- if(!close_on_exec)
+ if (!close_on_exec)
return 0;
err = os_set_exec_close(fds[0]);
- if(err < 0)
+ if (err < 0)
goto error;
err = os_set_exec_close(fds[1]);
- if(err < 0)
+ if (err < 0)
goto error;
return 0;
error:
- printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
+ printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
+ -err);
close(fds[1]);
close(fds[0]);
return err;
}
-int os_set_fd_async(int fd, int owner)
+int os_set_fd_async(int fd)
{
- int err;
+ int err, flags;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -errno;
- /* XXX This should do F_GETFL first */
- if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
+ flags |= O_ASYNC | O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, flags) < 0) {
err = -errno;
- printk("os_set_fd_async : failed to set O_ASYNC and "
- "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
+ printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
+ "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
return err;
}
-#ifdef notdef
- if(fcntl(fd, F_SETFD, 1) < 0){
- printk("os_set_fd_async : Setting FD_CLOEXEC failed, "
- "errno = %d\n", errno);
- }
-#endif
- if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
- (fcntl(fd, F_SETOWN, owner) < 0)){
+ if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
+ (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
err = -errno;
- printk("os_set_fd_async : Failed to fcntl F_SETOWN "
- "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
- owner, errno);
+ printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
+ "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
return err;
}
@@ -413,10 +391,14 @@ int os_set_fd_async(int fd, int owner)
int os_clear_fd_async(int fd)
{
- int flags = fcntl(fd, F_GETFL);
+ int flags;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -errno;
flags &= ~(O_ASYNC | O_NONBLOCK);
- if(fcntl(fd, F_SETFL, flags) < 0)
+ if (fcntl(fd, F_SETFL, flags) < 0)
return -errno;
return 0;
}
@@ -426,11 +408,15 @@ int os_set_fd_block(int fd, int blocking)
int flags;
flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -errno;
- if(blocking) flags &= ~O_NONBLOCK;
- else flags |= O_NONBLOCK;
+ if (blocking)
+ flags &= ~O_NONBLOCK;
+ else
+ flags |= O_NONBLOCK;
- if(fcntl(fd, F_SETFL, flags) < 0)
+ if (fcntl(fd, F_SETFL, flags) < 0)
return -errno;
return 0;
@@ -441,7 +427,7 @@ int os_accept_connection(int fd)
int new;
new = accept(fd, NULL, 0);
- if(new < 0)
+ if (new < 0)
return -errno;
return new;
}
@@ -462,15 +448,17 @@ int os_shutdown_socket(int fd, int r, int w)
{
int what, err;
- if(r && w) what = SHUT_RDWR;
- else if(r) what = SHUT_RD;
- else if(w) what = SHUT_WR;
- else {
- printk("os_shutdown_socket : neither r or w was set\n");
+ if (r && w)
+ what = SHUT_RDWR;
+ else if (r)
+ what = SHUT_RD;
+ else if (w)
+ what = SHUT_WR;
+ else
return -EINVAL;
- }
+
err = shutdown(fd, what);
- if(err < 0)
+ if (err < 0)
return -errno;
return 0;
}
@@ -494,19 +482,20 @@ int os_rcv_fd(int fd, int *helper_pid_out)
msg.msg_flags = 0;
n = recvmsg(fd, &msg, 0);
- if(n < 0)
+ if (n < 0)
return -errno;
- else if(n != iov.iov_len)
+ else if (n != iov.iov_len)
*helper_pid_out = -1;
cmsg = CMSG_FIRSTHDR(&msg);
- if(cmsg == NULL){
- printk("rcv_fd didn't receive anything, error = %d\n", errno);
+ if (cmsg == NULL) {
+ printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
+ "error = %d\n", errno);
return -1;
}
- if((cmsg->cmsg_level != SOL_SOCKET) ||
- (cmsg->cmsg_type != SCM_RIGHTS)){
- printk("rcv_fd didn't receive a descriptor\n");
+ if ((cmsg->cmsg_level != SOL_SOCKET) ||
+ (cmsg->cmsg_type != SCM_RIGHTS)) {
+ printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
return -1;
}
@@ -514,29 +503,28 @@ int os_rcv_fd(int fd, int *helper_pid_out)
return new;
}
-int os_create_unix_socket(char *file, int len, int close_on_exec)
+int os_create_unix_socket(const char *file, int len, int close_on_exec)
{
struct sockaddr_un addr;
int sock, err;
sock = socket(PF_UNIX, SOCK_DGRAM, 0);
- if(sock < 0)
+ if (sock < 0)
return -errno;
- if(close_on_exec) {
+ if (close_on_exec) {
err = os_set_exec_close(sock);
- if(err < 0)
- printk("create_unix_socket : close_on_exec failed, "
- "err = %d", -err);
+ if (err < 0)
+ printk(UM_KERN_ERR "create_unix_socket : "
+ "close_on_exec failed, err = %d", -err);
}
addr.sun_family = AF_UNIX;
- /* XXX Be more careful about overflow */
snprintf(addr.sun_path, len, "%s", file);
err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
- if(err < 0)
+ if (err < 0)
return -errno;
return sock;
@@ -557,17 +545,18 @@ int os_lock_file(int fd, int excl)
int err, save;
err = fcntl(fd, F_SETLK, &lock);
- if(!err)
+ if (!err)
goto out;
save = -errno;
err = fcntl(fd, F_GETLK, &lock);
- if(err){
+ if (err) {
err = -errno;
goto out;
}
- printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
+ printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
+ lock.l_pid);
err = save;
out:
return err;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index fba3f0fefee..f4bd349d441 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -1,22 +1,19 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sched.h>
-#include <limits.h>
-#include <sys/signal.h>
-#include <sys/wait.h>
#include <sys/socket.h>
-#include "user.h"
+#include <sys/wait.h>
+#include "kern_constants.h"
#include "kern_util.h"
#include "os.h"
#include "um_malloc.h"
-#include "kern_constants.h"
+#include "user.h"
struct helper_data {
void (*pre_exec)(void*);
@@ -30,21 +27,19 @@ static int helper_child(void *arg)
{
struct helper_data *data = arg;
char **argv = data->argv;
- int errval;
+ int err;
if (data->pre_exec != NULL)
(*data->pre_exec)(data->pre_data);
- errval = execvp_noalloc(data->buf, argv[0], argv);
- printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0],
- -errval);
- write(data->fd, &errval, sizeof(errval));
- kill(os_getpid(), SIGKILL);
+ err = execvp_noalloc(data->buf, argv[0], argv);
+
+ /* If the exec succeeds, we don't get here */
+ write(data->fd, &err, sizeof(err));
+
return 0;
}
-/* Returns either the pid of the child process we run or -E* on failure.
- * XXX The alloc_stack here breaks if this is called in the tracing thread, so
- * we need to receive a preallocated stack (a local buffer is ok). */
+/* Returns either the pid of the child process we run or -E* on failure. */
int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
{
struct helper_data data;
@@ -58,14 +53,15 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
if (ret < 0) {
ret = -errno;
- printk("run_helper : pipe failed, errno = %d\n", errno);
+ printk(UM_KERN_ERR "run_helper : pipe failed, errno = %d\n",
+ errno);
goto out_free;
}
ret = os_set_exec_close(fds[1]);
if (ret < 0) {
- printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
- -ret);
+ printk(UM_KERN_ERR "run_helper : setting FD_CLOEXEC failed, "
+ "ret = %d\n", -ret);
goto out_close;
}
@@ -79,7 +75,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
pid = clone(helper_child, (void *) sp, CLONE_VM, &data);
if (pid < 0) {
ret = -errno;
- printk("run_helper : clone failed, errno = %d\n", errno);
+ printk(UM_KERN_ERR "run_helper : clone failed, errno = %d\n",
+ errno);
goto out_free2;
}
@@ -96,10 +93,9 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
} else {
if (n < 0) {
n = -errno;
- printk("run_helper : read on pipe failed, ret = %d\n",
- -n);
+ printk(UM_KERN_ERR "run_helper : read on pipe failed, "
+ "ret = %d\n", -n);
ret = n;
- kill(pid, SIGKILL);
}
CATCH_EINTR(waitpid(pid, NULL, __WCLONE));
}
@@ -129,50 +125,40 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
pid = clone(proc, (void *) sp, flags, arg);
if (pid < 0) {
err = -errno;
- printk("run_helper_thread : clone failed, errno = %d\n",
- errno);
+ printk(UM_KERN_ERR "run_helper_thread : clone failed, "
+ "errno = %d\n", errno);
return err;
}
if (stack_out == NULL) {
CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE));
if (pid < 0) {
err = -errno;
- printk("run_helper_thread - wait failed, errno = %d\n",
- errno);
+ printk(UM_KERN_ERR "run_helper_thread - wait failed, "
+ "errno = %d\n", errno);
pid = err;
}
if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
- printk("run_helper_thread - thread returned status "
- "0x%x\n", status);
+ printk(UM_KERN_ERR "run_helper_thread - thread "
+ "returned status 0x%x\n", status);
free_stack(stack, 0);
} else
*stack_out = stack;
return pid;
}
-int helper_wait(int pid, int nohang, char *pname)
+int helper_wait(int pid)
{
int ret, status;
int wflags = __WCLONE;
- if (nohang)
- wflags |= WNOHANG;
-
- if (!pname)
- pname = "helper_wait";
-
CATCH_EINTR(ret = waitpid(pid, &status, wflags));
if (ret < 0) {
- printk(UM_KERN_ERR "%s : waitpid process %d failed, "
- "errno = %d\n", pname, pid, errno);
+ printk(UM_KERN_ERR "helper_wait : waitpid process %d failed, "
+ "errno = %d\n", pid, errno);
return -errno;
- } else if (nohang && ret == 0) {
- printk(UM_KERN_ERR "%s : process %d has not exited\n",
- pname, pid);
- return -ECHILD;
} else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- printk(UM_KERN_ERR "%s : process %d didn't exit with "
- "status 0\n", pname, pid);
+ printk(UM_KERN_ERR "helper_wait : process %d exited with "
+ "status 0x%x\n", pid, status);
return -ECHILD;
} else
return 0;
diff --git a/arch/um/os-Linux/include/file.h b/arch/um/os-Linux/include/file.h
index d82711efacf..fe71be24bd5 100644
--- a/arch/um/os-Linux/include/file.h
+++ b/arch/um/os-Linux/include/file.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -9,14 +9,3 @@
#define DEV_NULL "/dev/null"
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index 6aa6f95d652..0348b975e81 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -1,23 +1,19 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <stdlib.h>
-#include <unistd.h>
#include <errno.h>
+#include <poll.h>
#include <signal.h>
#include <string.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include "kern_util.h"
-#include "user.h"
-#include "process.h"
-#include "sigio.h"
#include "irq_user.h"
+#include "kern_constants.h"
#include "os.h"
+#include "process.h"
#include "um_malloc.h"
+#include "user.h"
/*
* Locked by irq_lock in arch/um/kernel/irq.c. Changed by os_create_pollfd
@@ -36,7 +32,7 @@ int os_waiting_for_events(struct irq_fd *active_fds)
if (n < 0) {
err = -errno;
if (errno != EINTR)
- printk("sigio_handler: os_waiting_for_events:"
+ printk(UM_KERN_ERR "os_waiting_for_events:"
" poll returned %d, errno = %d\n", n, errno);
return err;
}
@@ -95,24 +91,26 @@ void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
struct irq_fd *old_fd = *prev;
if ((pollfds[i].fd != -1) &&
(pollfds[i].fd != (*prev)->fd)) {
- printk("os_free_irq_by_cb - mismatch between "
- "active_fds and pollfds, fd %d vs %d\n",
+ printk(UM_KERN_ERR "os_free_irq_by_cb - "
+ "mismatch between active_fds and "
+ "pollfds, fd %d vs %d\n",
(*prev)->fd, pollfds[i].fd);
goto out;
}
pollfds_num--;
- /* This moves the *whole* array after pollfds[i]
+ /*
+ * This moves the *whole* array after pollfds[i]
* (though it doesn't spot as such)!
*/
memmove(&pollfds[i], &pollfds[i + 1],
(pollfds_num - i) * sizeof(pollfds[0]));
- if(*last_irq_ptr2 == &old_fd->next)
+ if (*last_irq_ptr2 == &old_fd->next)
*last_irq_ptr2 = prev;
*prev = (*prev)->next;
- if(old_fd->type == IRQ_WRITE)
+ if (old_fd->type == IRQ_WRITE)
ignore_sigio_fd(old_fd->fd);
kfree(old_fd);
continue;
@@ -138,14 +136,3 @@ void os_set_ioignore(void)
{
signal(SIGIO, SIG_IGN);
}
-
-void init_irq_signals(int on_sigstack)
-{
- int flags;
-
- flags = on_sigstack ? SA_ONSTACK : 0;
-
- set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
- SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- signal(SIGWINCH, SIG_IGN);
-}
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 82c3778627b..abb9b0ffd96 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -73,7 +73,7 @@ static void install_fatal_handler(int sig)
action.sa_handler = last_ditch_exit;
if (sigaction(sig, &action, NULL) < 0) {
printf("failed to install handler for signal %d - errno = %d\n",
- errno);
+ sig, errno);
exit(1);
}
}
@@ -92,7 +92,8 @@ static void setup_env_path(void)
* just use the default + /usr/lib/uml
*/
if (!old_path || (path_len = strlen(old_path)) == 0) {
- putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH);
+ if (putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH))
+ perror("couldn't putenv");
return;
}
@@ -100,15 +101,16 @@ static void setup_env_path(void)
path_len += strlen("PATH=" UML_LIB_PATH) + 1;
new_path = malloc(path_len);
if (!new_path) {
- perror("coudn't malloc to set a new PATH");
+ perror("couldn't malloc to set a new PATH");
return;
}
snprintf(new_path, path_len, "PATH=%s" UML_LIB_PATH, old_path);
- putenv(new_path);
+ if (putenv(new_path)) {
+ perror("couldn't putenv to set a new PATH");
+ free(new_path);
+ }
}
-extern int uml_exitcode;
-
extern void scan_elf_aux( char **envp);
int __init main(int argc, char **argv, char **envp)
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 436f8d20b20..93a11d7edfa 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -1,23 +1,21 @@
+/*
+ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Licensed under the GPL
+ */
+
#include <stdio.h>
-#include <stdlib.h>
#include <stddef.h>
-#include <stdarg.h>
+#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
-#include <string.h>
#include <fcntl.h>
-#include <sys/types.h>
+#include <string.h>
#include <sys/mman.h>
-#include <sys/statfs.h>
-#include "kern_util.h"
-#include "user.h"
-#include "mem_user.h"
+#include <sys/param.h>
#include "init.h"
-#include "os.h"
-#include "tempfile.h"
#include "kern_constants.h"
-
-#include <sys/param.h>
+#include "os.h"
+#include "user.h"
/* Modified by which_tmpdir, which is called during early boot */
static char *default_tmpdir = "/tmp";
@@ -30,22 +28,23 @@ static char *tempdir = NULL;
static void __init find_tempdir(void)
{
- char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
+ const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
int i;
char *dir = NULL;
- if(tempdir != NULL) /* We've already been called */
+ if (tempdir != NULL)
+ /* We've already been called */
return;
- for(i = 0; dirs[i]; i++){
+ for (i = 0; dirs[i]; i++) {
dir = getenv(dirs[i]);
- if((dir != NULL) && (*dir != '\0'))
+ if ((dir != NULL) && (*dir != '\0'))
break;
}
- if((dir == NULL) || (*dir == '\0'))
+ if ((dir == NULL) || (*dir == '\0'))
dir = default_tmpdir;
tempdir = malloc(strlen(dir) + 2);
- if(tempdir == NULL){
+ if (tempdir == NULL) {
fprintf(stderr, "Failed to malloc tempdir, "
"errno = %d\n", errno);
return;
@@ -54,21 +53,23 @@ static void __init find_tempdir(void)
strcat(tempdir, "/");
}
-/* This will return 1, with the first character in buf being the
+/*
+ * This will return 1, with the first character in buf being the
* character following the next instance of c in the file. This will
* read the file as needed. If there's an error, -errno is returned;
* if the end of the file is reached, 0 is returned.
*/
-static int next(int fd, char *buf, int size, char c)
+static int next(int fd, char *buf, size_t size, char c)
{
- int n, len;
+ ssize_t n;
+ size_t len;
char *ptr;
- while((ptr = strchr(buf, c)) == NULL){
+ while ((ptr = strchr(buf, c)) == NULL) {
n = read(fd, buf, size - 1);
- if(n == 0)
+ if (n == 0)
return 0;
- else if(n < 0)
+ else if (n < 0)
return -errno;
buf[n] = '\0';
@@ -78,11 +79,12 @@ static int next(int fd, char *buf, int size, char c)
len = strlen(ptr);
memmove(buf, ptr, len + 1);
- /* Refill the buffer so that if there's a partial string that we care
+ /*
+ * Refill the buffer so that if there's a partial string that we care
* about, it will be completed, and we can recognize it.
*/
n = read(fd, &buf[len], size - len - 1);
- if(n < 0)
+ if (n < 0)
return -errno;
buf[len + n] = '\0';
@@ -92,7 +94,8 @@ static int next(int fd, char *buf, int size, char c)
/* which_tmpdir is called only during early boot */
static int checked_tmpdir = 0;
-/* Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner
+/*
+ * Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner
* way to do this than to parse /proc/mounts. statfs will return the
* same filesystem magic number and fs id for both /dev and /dev/shm
* when they are both tmpfs, so you can't tell if they are different
@@ -107,7 +110,7 @@ static void which_tmpdir(void)
int fd, found;
char buf[128] = { '\0' };
- if(checked_tmpdir)
+ if (checked_tmpdir)
return;
checked_tmpdir = 1;
@@ -115,28 +118,28 @@ static void which_tmpdir(void)
printf("Checking for tmpfs mount on /dev/shm...");
fd = open("/proc/mounts", O_RDONLY);
- if(fd < 0){
+ if (fd < 0) {
printf("failed to open /proc/mounts, errno = %d\n", errno);
return;
}
- while(1){
+ while (1) {
found = next(fd, buf, ARRAY_SIZE(buf), ' ');
- if(found != 1)
+ if (found != 1)
break;
- if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
+ if (!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
goto found;
found = next(fd, buf, ARRAY_SIZE(buf), '\n');
- if(found != 1)
+ if (found != 1)
break;
}
err:
- if(found == 0)
+ if (found == 0)
printf("nothing mounted on /dev/shm\n");
- else if(found < 0)
+ else if (found < 0)
printf("read returned errno %d\n", -found);
out:
@@ -146,10 +149,10 @@ out:
found:
found = next(fd, buf, ARRAY_SIZE(buf), ' ');
- if(found != 1)
+ if (found != 1)
goto err;
- if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
+ if (strncmp(buf, "tmpfs", strlen("tmpfs"))) {
printf("not tmpfs\n");
goto out;
}
@@ -159,41 +162,40 @@ found:
goto out;
}
-/*
- * This proc still used in tt-mode
- * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
- * So it isn't 'static' yet.
- */
-int __init make_tempfile(const char *template, char **out_tempname,
- int do_unlink)
+static int __init make_tempfile(const char *template, char **out_tempname,
+ int do_unlink)
{
char *tempname;
int fd;
which_tmpdir();
tempname = malloc(MAXPATHLEN);
+ if (tempname == NULL)
+ return -1;
find_tempdir();
+ if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN))
+ return -1;
+
if (template[0] != '/')
strcpy(tempname, tempdir);
else
tempname[0] = '\0';
- strcat(tempname, template);
+ strncat(tempname, template, MAXPATHLEN-1-strlen(tempname));
fd = mkstemp(tempname);
- if(fd < 0){
+ if (fd < 0) {
fprintf(stderr, "open - cannot create %s: %s\n", tempname,
strerror(errno));
goto out;
}
- if(do_unlink && (unlink(tempname) < 0)){
+ if (do_unlink && (unlink(tempname) < 0)) {
perror("unlink");
goto out;
}
- if(out_tempname){
+ if (out_tempname) {
*out_tempname = tempname;
- } else {
+ } else
free(tempname);
- }
return fd;
out:
free(tempname);
@@ -202,27 +204,23 @@ out:
#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
-/*
- * This proc is used in start_up.c
- * So it isn't 'static'.
- */
-int __init create_tmp_file(unsigned long long len)
+static int __init create_tmp_file(unsigned long long len)
{
int fd, err;
char zero;
fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
- if(fd < 0) {
+ if (fd < 0)
exit(1);
- }
err = fchmod(fd, 0777);
- if(err < 0){
+ if (err < 0) {
perror("fchmod");
exit(1);
}
- /* Seek to len - 1 because writing a character there will
+ /*
+ * Seek to len - 1 because writing a character there will
* increase the file size by one byte, to the desired length.
*/
if (lseek64(fd, len - 1, SEEK_SET) < 0) {
@@ -233,7 +231,7 @@ int __init create_tmp_file(unsigned long long len)
zero = 0;
err = write(fd, &zero, 1);
- if(err != 1){
+ if (err != 1) {
perror("write");
exit(1);
}
@@ -248,7 +246,7 @@ int __init create_mem_file(unsigned long long len)
fd = create_tmp_file(len);
err = os_set_exec_close(fd);
- if(err < 0){
+ if (err < 0) {
errno = -err;
perror("exec_close");
}
@@ -265,10 +263,11 @@ void __init check_tmpexec(void)
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
printf("Checking PROT_EXEC mmap in %s...",tempdir);
fflush(stdout);
- if(addr == MAP_FAILED){
+ if (addr == MAP_FAILED) {
err = errno;
perror("failed");
- if(err == EPERM)
+ close(fd);
+ if (err == EPERM)
printf("%s must be not mounted noexec\n",tempdir);
exit(1);
}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index bda5c3150d6..e0477c3ee89 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -224,7 +224,7 @@ int __init can_drop_memory(void)
goto out_unmap;
}
- printk("OK\n");
+ printk(UM_KERN_CONT "OK\n");
ok = 1;
out_unmap:
@@ -249,7 +249,10 @@ void init_new_thread_signals(void)
SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
signal(SIGHUP, SIG_IGN);
- init_irq_signals(1);
+ set_handler(SIGIO, (__sighandler_t) sig_handler,
+ SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM,
+ SIGVTALRM, -1);
+ signal(SIGWINCH, SIG_IGN);
}
int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr)
diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c
index a32ba6ab121..830fe6a1518 100644
--- a/arch/um/os-Linux/registers.c
+++ b/arch/um/os-Linux/registers.c
@@ -8,47 +8,41 @@
#include <string.h>
#include <sys/ptrace.h>
#include "sysdep/ptrace.h"
-#include "user.h"
-/* This is set once at boot time and not changed thereafter */
-
-static unsigned long exec_regs[MAX_REG_NR];
-
-void init_thread_registers(struct uml_pt_regs *to)
-{
- memcpy(to->gp, exec_regs, sizeof(to->gp));
-}
-
-void save_registers(int pid, struct uml_pt_regs *regs)
+int save_registers(int pid, struct uml_pt_regs *regs)
{
int err;
err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp);
if (err < 0)
- panic("save_registers - saving registers failed, errno = %d\n",
- errno);
+ return -errno;
+ return 0;
}
-void restore_registers(int pid, struct uml_pt_regs *regs)
+int restore_registers(int pid, struct uml_pt_regs *regs)
{
int err;
err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp);
if (err < 0)
- panic("restore_registers - saving registers failed, "
- "errno = %d\n", errno);
+ return -errno;
+ return 0;
}
-void init_registers(int pid)
+/* This is set once at boot time and not changed thereafter */
+
+static unsigned long exec_regs[MAX_REG_NR];
+
+int init_registers(int pid)
{
int err;
err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
- if (err)
- panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
- errno);
+ if (err < 0)
+ return -errno;
arch_init_registers(pid);
+ return 0;
}
void get_safe_registers(unsigned long *regs)
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index dc03e9cccb6..abf47a7c4ab 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -1,34 +1,33 @@
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <unistd.h>
-#include <stdlib.h>
-#include <termios.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
#include <pty.h>
+#include <sched.h>
#include <signal.h>
-#include <fcntl.h>
-#include <errno.h>
#include <string.h>
-#include <sched.h>
-#include <sys/socket.h>
-#include <sys/poll.h>
-#include "init.h"
-#include "user.h"
+#include "kern_constants.h"
#include "kern_util.h"
-#include "sigio.h"
+#include "init.h"
#include "os.h"
+#include "sigio.h"
#include "um_malloc.h"
-#include "init.h"
+#include "user.h"
-/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
+/*
+ * Protected by sigio_lock(), also used by sigio_cleanup, which is an
* exitcall.
*/
static int write_sigio_pid = -1;
static unsigned long write_sigio_stack;
-/* These arrays are initialized before the sigio thread is started, and
+/*
+ * These arrays are initialized before the sigio thread is started, and
* the descriptors closed after it is killed. So, it can't see them change.
* On the UML side, they are changed under the sigio_lock.
*/
@@ -43,7 +42,8 @@ struct pollfds {
int used;
};
-/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
+/*
+ * Protected by sigio_lock(). Used by the sigio thread, but the UML thread
* synchronizes with it.
*/
static struct pollfds current_poll;
@@ -57,23 +57,26 @@ static int write_sigio_thread(void *unused)
int i, n, respond_fd;
char c;
- signal(SIGWINCH, SIG_IGN);
+ signal(SIGWINCH, SIG_IGN);
fds = &current_poll;
- while(1){
+ while (1) {
n = poll(fds->poll, fds->used, -1);
- if(n < 0){
- if(errno == EINTR) continue;
- printk("write_sigio_thread : poll returned %d, "
- "errno = %d\n", n, errno);
+ if (n < 0) {
+ if (errno == EINTR)
+ continue;
+ printk(UM_KERN_ERR "write_sigio_thread : poll returned "
+ "%d, errno = %d\n", n, errno);
}
- for(i = 0; i < fds->used; i++){
+ for (i = 0; i < fds->used; i++) {
p = &fds->poll[i];
- if(p->revents == 0) continue;
- if(p->fd == sigio_private[1]){
+ if (p->revents == 0)
+ continue;
+ if (p->fd == sigio_private[1]) {
CATCH_EINTR(n = read(sigio_private[1], &c,
sizeof(c)));
- if(n != sizeof(c))
- printk("write_sigio_thread : "
+ if (n != sizeof(c))
+ printk(UM_KERN_ERR
+ "write_sigio_thread : "
"read on socket failed, "
"err = %d\n", errno);
tmp = current_poll;
@@ -89,9 +92,10 @@ static int write_sigio_thread(void *unused)
}
CATCH_EINTR(n = write(respond_fd, &c, sizeof(c)));
- if(n != sizeof(c))
- printk("write_sigio_thread : write on socket "
- "failed, err = %d\n", errno);
+ if (n != sizeof(c))
+ printk(UM_KERN_ERR "write_sigio_thread : "
+ "write on socket failed, err = %d\n",
+ errno);
}
}
@@ -102,12 +106,13 @@ static int need_poll(struct pollfds *polls, int n)
{
struct pollfd *new;
- if(n <= polls->size)
+ if (n <= polls->size)
return 0;
new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC);
- if(new == NULL){
- printk("need_poll : failed to allocate new pollfds\n");
+ if (new == NULL) {
+ printk(UM_KERN_ERR "need_poll : failed to allocate new "
+ "pollfds\n");
return -ENOMEM;
}
@@ -119,7 +124,8 @@ static int need_poll(struct pollfds *polls, int n)
return 0;
}
-/* Must be called with sigio_lock held, because it's needed by the marked
+/*
+ * Must be called with sigio_lock held, because it's needed by the marked
* critical section.
*/
static void update_thread(void)
@@ -129,15 +135,17 @@ static void update_thread(void)
char c;
flags = set_signals(0);
- n = write(sigio_private[0], &c, sizeof(c));
- if(n != sizeof(c)){
- printk("update_thread : write failed, err = %d\n", errno);
+ CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c)));
+ if (n != sizeof(c)) {
+ printk(UM_KERN_ERR "update_thread : write failed, err = %d\n",
+ errno);
goto fail;
}
CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c)));
- if(n != sizeof(c)){
- printk("update_thread : read failed, err = %d\n", errno);
+ if (n != sizeof(c)) {
+ printk(UM_KERN_ERR "update_thread : read failed, err = %d\n",
+ errno);
goto fail;
}
@@ -164,23 +172,23 @@ int add_sigio_fd(int fd)
int err = 0, i, n;
sigio_lock();
- for(i = 0; i < all_sigio_fds.used; i++){
- if(all_sigio_fds.poll[i].fd == fd)
+ for (i = 0; i < all_sigio_fds.used; i++) {
+ if (all_sigio_fds.poll[i].fd == fd)
break;
}
- if(i == all_sigio_fds.used)
+ if (i == all_sigio_fds.used)
goto out;
p = &all_sigio_fds.poll[i];
- for(i = 0; i < current_poll.used; i++){
- if(current_poll.poll[i].fd == fd)
+ for (i = 0; i < current_poll.used; i++) {
+ if (current_poll.poll[i].fd == fd)
goto out;
}
n = current_poll.used;
err = need_poll(&next_poll, n + 1);
- if(err)
+ if (err)
goto out;
memcpy(next_poll.poll, current_poll.poll,
@@ -198,27 +206,29 @@ int ignore_sigio_fd(int fd)
struct pollfd *p;
int err = 0, i, n = 0;
- /* This is called from exitcalls elsewhere in UML - if
+ /*
+ * This is called from exitcalls elsewhere in UML - if
* sigio_cleanup has already run, then update_thread will hang
* or fail because the thread is no longer running.
*/
- if(write_sigio_pid == -1)
+ if (write_sigio_pid == -1)
return -EIO;
sigio_lock();
- for(i = 0; i < current_poll.used; i++){
- if(current_poll.poll[i].fd == fd) break;
+ for (i = 0; i < current_poll.used; i++) {
+ if (current_poll.poll[i].fd == fd)
+ break;
}
- if(i == current_poll.used)
+ if (i == current_poll.used)
goto out;
err = need_poll(&next_poll, current_poll.used - 1);
- if(err)
+ if (err)
goto out;
- for(i = 0; i < current_poll.used; i++){
+ for (i = 0; i < current_poll.used; i++) {
p = &current_poll.poll[i];
- if(p->fd != fd)
+ if (p->fd != fd)
next_poll.poll[n++] = *p;
}
next_poll.used = current_poll.used - 1;
@@ -235,7 +245,8 @@ static struct pollfd *setup_initial_poll(int fd)
p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL);
if (p == NULL) {
- printk("setup_initial_poll : failed to allocate poll\n");
+ printk(UM_KERN_ERR "setup_initial_poll : failed to allocate "
+ "poll\n");
return NULL;
}
*p = ((struct pollfd) { .fd = fd,
@@ -261,27 +272,29 @@ static void write_sigio_workaround(void)
return;
err = os_pipe(l_write_sigio_fds, 1, 1);
- if(err < 0){
- printk("write_sigio_workaround - os_pipe 1 failed, "
+ if (err < 0) {
+ printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 1 failed, "
"err = %d\n", -err);
return;
}
err = os_pipe(l_sigio_private, 1, 1);
- if(err < 0){
- printk("write_sigio_workaround - os_pipe 2 failed, "
+ if (err < 0) {
+ printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 2 failed, "
"err = %d\n", -err);
goto out_close1;
}
p = setup_initial_poll(l_sigio_private[1]);
- if(!p)
+ if (!p)
goto out_close2;
sigio_lock();
- /* Did we race? Don't try to optimize this, please, it's not so likely
- * to happen, and no more than once at the boot. */
- if(write_sigio_pid != -1)
+ /*
+ * Did we race? Don't try to optimize this, please, it's not so likely
+ * to happen, and no more than once at the boot.
+ */
+ if (write_sigio_pid != -1)
goto out_free;
current_poll = ((struct pollfds) { .poll = p,
@@ -333,19 +346,19 @@ void maybe_sigio_broken(int fd, int read)
{
int err;
- if(!isatty(fd))
+ if (!isatty(fd))
return;
- if((read || pty_output_sigio) && (!read || pty_close_sigio))
+ if ((read || pty_output_sigio) && (!read || pty_close_sigio))
return;
write_sigio_workaround();
sigio_lock();
err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
- if(err){
- printk("maybe_sigio_broken - failed to add pollfd for "
- "descriptor %d\n", fd);
+ if (err) {
+ printk(UM_KERN_ERR "maybe_sigio_broken - failed to add pollfd "
+ "for descriptor %d\n", fd);
goto out;
}
@@ -388,7 +401,7 @@ static void openpty_cb(void *arg)
struct openpty_arg *info = arg;
info->err = 0;
- if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
+ if (openpty(&info->master, &info->slave, NULL, NULL, NULL))
info->err = -errno;
}
@@ -397,17 +410,17 @@ static int async_pty(int master, int slave)
int flags;
flags = fcntl(master, F_GETFL);
- if(flags < 0)
+ if (flags < 0)
return -errno;
- if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
- (fcntl(master, F_SETOWN, os_getpid()) < 0))
+ if ((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
+ (fcntl(master, F_SETOWN, os_getpid()) < 0))
return -errno;
- if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
+ if ((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
return -errno;
- return(0);
+ return 0;
}
static void __init check_one_sigio(void (*proc)(int, int))
@@ -417,34 +430,49 @@ static void __init check_one_sigio(void (*proc)(int, int))
int master, slave, err;
initial_thread_cb(openpty_cb, &pty);
- if(pty.err){
- printk("openpty failed, errno = %d\n", -pty.err);
+ if (pty.err) {
+ printk(UM_KERN_ERR "check_one_sigio failed, errno = %d\n",
+ -pty.err);
return;
}
master = pty.master;
slave = pty.slave;
- if((master == -1) || (slave == -1)){
- printk("openpty failed to allocate a pty\n");
+ if ((master == -1) || (slave == -1)) {
+ printk(UM_KERN_ERR "check_one_sigio failed to allocate a "
+ "pty\n");
return;
}
/* Not now, but complain so we now where we failed. */
err = raw(master);
- if (err < 0)
- panic("check_sigio : __raw failed, errno = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : raw failed, errno = %d\n",
+ -err);
+ return;
+ }
err = async_pty(master, slave);
- if(err < 0)
- panic("tty_fds : sigio_async failed, err = %d\n", -err);
+ if (err < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : sigio_async failed, "
+ "err = %d\n", -err);
+ return;
+ }
+
+ if (sigaction(SIGIO, NULL, &old) < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : sigaction 1 failed, "
+ "errno = %d\n", errno);
+ return;
+ }
- if(sigaction(SIGIO, NULL, &old) < 0)
- panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
new = old;
new.sa_handler = handler;
- if(sigaction(SIGIO, &new, NULL) < 0)
- panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
+ if (sigaction(SIGIO, &new, NULL) < 0) {
+ printk(UM_KERN_ERR "check_one_sigio : sigaction 2 failed, "
+ "errno = %d\n", errno);
+ return;
+ }
got_sigio = 0;
(*proc)(master, slave);
@@ -452,8 +480,9 @@ static void __init check_one_sigio(void (*proc)(int, int))
close(master);
close(slave);
- if(sigaction(SIGIO, &old, NULL) < 0)
- panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
+ if (sigaction(SIGIO, &old, NULL) < 0)
+ printk(UM_KERN_ERR "check_one_sigio : sigaction 3 failed, "
+ "errno = %d\n", errno);
}
static void tty_output(int master, int slave)
@@ -461,42 +490,45 @@ static void tty_output(int master, int slave)
int n;
char buf[512];
- printk("Checking that host ptys support output SIGIO...");
+ printk(UM_KERN_INFO "Checking that host ptys support output SIGIO...");
memset(buf, 0, sizeof(buf));
- while(write(master, buf, sizeof(buf)) > 0) ;
- if(errno != EAGAIN)
- panic("tty_output : write failed, errno = %d\n", errno);
- while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
+ while (write(master, buf, sizeof(buf)) > 0) ;
+ if (errno != EAGAIN)
+ printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n",
+ errno);
+ while (((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio)
+ ;
- if(got_sigio){
- printk("Yes\n");
+ if (got_sigio) {
+ printk(UM_KERN_CONT "Yes\n");
pty_output_sigio = 1;
- }
- else if(n == -EAGAIN)
- printk("No, enabling workaround\n");
- else panic("tty_output : read failed, err = %d\n", n);
+ } else if (n == -EAGAIN)
+ printk(UM_KERN_CONT "No, enabling workaround\n");
+ else
+ printk(UM_KERN_CONT "tty_output : read failed, err = %d\n", n);
}
static void tty_close(int master, int slave)
{
- printk("Checking that host ptys support SIGIO on close...");
+ printk(UM_KERN_INFO "Checking that host ptys support SIGIO on "
+ "close...");
close(slave);
- if(got_sigio){
- printk("Yes\n");
+ if (got_sigio) {
+ printk(UM_KERN_CONT "Yes\n");
pty_close_sigio = 1;
- }
- else printk("No, enabling workaround\n");
+ } else
+ printk(UM_KERN_CONT "No, enabling workaround\n");
}
void __init check_sigio(void)
{
- if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
- (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
- printk("No pseudo-terminals available - skipping pty SIGIO "
- "check\n");
+ if ((access("/dev/ptmx", R_OK) < 0) &&
+ (access("/dev/ptyp0", R_OK) < 0)) {
+ printk(UM_KERN_WARNING "No pseudo-terminals available - "
+ "skipping pty SIGIO check\n");
return;
}
check_one_sigio(tty_output);
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index e9800b0b568..3f1694b134c 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -9,11 +9,47 @@
#include <errno.h>
#include <signal.h>
#include <strings.h>
+#include "as-layout.h"
+#include "kern_util.h"
#include "os.h"
#include "sysdep/barrier.h"
#include "sysdep/sigcontext.h"
#include "user.h"
+/* Copied from linux/compiler-gcc.h since we can't include it directly */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
+ [SIGTRAP] = relay_signal,
+ [SIGFPE] = relay_signal,
+ [SIGILL] = relay_signal,
+ [SIGWINCH] = winch,
+ [SIGBUS] = bus_handler,
+ [SIGSEGV] = segv_handler,
+ [SIGIO] = sigio_handler,
+ [SIGVTALRM] = timer_handler };
+
+static void sig_handler_common(int sig, struct sigcontext *sc)
+{
+ struct uml_pt_regs r;
+ int save_errno = errno;
+
+ r.is_user = 0;
+ if (sig == SIGSEGV) {
+ /* For segfaults, we want the data from the sigcontext. */
+ copy_sc(&r, sc);
+ GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
+ }
+
+ /* enable signals if sig isn't IRQ signal */
+ if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
+ unblock_signals();
+
+ (*sig_info[sig])(sig, &r);
+
+ errno = save_errno;
+}
+
/*
* These are the asynchronous signals. SIGPROF is excluded because we want to
* be able to profile all of UML, not just the non-critical sections. If
@@ -26,13 +62,8 @@
#define SIGVTALRM_BIT 1
#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
-/*
- * These are used by both the signal handlers and
- * block/unblock_signals. I don't want modifications cached in a
- * register - they must go straight to memory.
- */
-static volatile int signals_enabled = 1;
-static volatile int pending = 0;
+static int signals_enabled;
+static unsigned int signals_pending;
void sig_handler(int sig, struct sigcontext *sc)
{
@@ -40,13 +71,13 @@ void sig_handler(int sig, struct sigcontext *sc)
enabled = signals_enabled;
if (!enabled && (sig == SIGIO)) {
- pending |= SIGIO_MASK;
+ signals_pending |= SIGIO_MASK;
return;
}
block_signals();
- sig_handler_common_skas(sig, sc);
+ sig_handler_common(sig, sc);
set_signals(enabled);
}
@@ -68,7 +99,7 @@ void alarm_handler(int sig, struct sigcontext *sc)
enabled = signals_enabled;
if (!signals_enabled) {
- pending |= SIGVTALRM_MASK;
+ signals_pending |= SIGVTALRM_MASK;
return;
}
@@ -94,16 +125,6 @@ void set_sigstack(void *sig_stack, int size)
panic("enabling signal stack failed, errno = %d\n", errno);
}
-void remove_sigstack(void)
-{
- stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
- .ss_sp = NULL,
- .ss_size = 0 });
-
- if (sigaltstack(&stack, NULL) != 0)
- panic("disabling signal stack failed, errno = %d\n", errno);
-}
-
void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
void handle_signal(int sig, struct sigcontext *sc)
@@ -166,6 +187,9 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
sigaddset(&action.sa_mask, mask);
va_end(ap);
+ if (sig == SIGSEGV)
+ flags |= SA_NODEFER;
+
action.sa_flags = flags;
action.sa_restorer = NULL;
if (sigaction(sig, &action, NULL) < 0)
@@ -179,12 +203,14 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
int change_sig(int signal, int on)
{
- sigset_t sigset, old;
+ sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, signal);
- sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
- return !sigismember(&old, signal);
+ if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0)
+ return -errno;
+
+ return 0;
}
void block_signals(void)
@@ -196,7 +222,7 @@ void block_signals(void)
* This might matter if gcc figures out how to inline this and
* decides to shuffle this code into the caller.
*/
- mb();
+ barrier();
}
void unblock_signals(void)
@@ -209,36 +235,26 @@ void unblock_signals(void)
/*
* We loop because the IRQ handler returns with interrupts off. So,
* interrupts may have arrived and we need to re-enable them and
- * recheck pending.
+ * recheck signals_pending.
*/
- while(1) {
+ while (1) {
/*
* Save and reset save_pending after enabling signals. This
- * way, pending won't be changed while we're reading it.
+ * way, signals_pending won't be changed while we're reading it.
*/
signals_enabled = 1;
/*
- * Setting signals_enabled and reading pending must
+ * Setting signals_enabled and reading signals_pending must
* happen in this order.
*/
- mb();
-
- save_pending = pending;
- if (save_pending == 0) {
- /*
- * This must return with signals enabled, so
- * this barrier ensures that writes are
- * flushed out before the return. This might
- * matter if gcc figures out how to inline
- * this (unlikely, given its size) and decides
- * to shuffle this code into the caller.
- */
- mb();
+ barrier();
+
+ save_pending = signals_pending;
+ if (save_pending == 0)
return;
- }
- pending = 0;
+ signals_pending = 0;
/*
* We have pending interrupts, so disable signals, as the
@@ -254,7 +270,7 @@ void unblock_signals(void)
* back here.
*/
if (save_pending & SIGIO_MASK)
- sig_handler_common_skas(SIGIO, NULL);
+ sig_handler_common(SIGIO, NULL);
if (save_pending & SIGVTALRM_MASK)
real_alarm_handler(NULL);
diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile
index 5fd8d4dad66..d2ea3409e07 100644
--- a/arch/um/os-Linux/skas/Makefile
+++ b/arch/um/os-Linux/skas/Makefile
@@ -1,10 +1,10 @@
#
-# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
+# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
# Licensed under the GPL
#
-obj-y := mem.o process.o trap.o
+obj-y := mem.o process.o
-USER_OBJS := mem.o process.o trap.o
+USER_OBJS := $(obj-y)
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index e8b7a97e83d..b14829469fa 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -15,6 +15,7 @@
#include "as-layout.h"
#include "chan_user.h"
#include "kern_constants.h"
+#include "kern_util.h"
#include "mem.h"
#include "os.h"
#include "process.h"
@@ -37,27 +38,27 @@ int is_skas_winch(int pid, int fd, void *data)
static int ptrace_dump_regs(int pid)
{
- unsigned long regs[MAX_REG_NR];
- int i;
+ unsigned long regs[MAX_REG_NR];
+ int i;
- if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
- return -errno;
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+ return -errno;
printk(UM_KERN_ERR "Stub registers -\n");
for (i = 0; i < ARRAY_SIZE(regs); i++)
printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]);
- return 0;
+ return 0;
}
/*
* Signals that are OK to receive in the stub - we'll just continue it.
* SIGWINCH will happen when UML is inside a detached screen.
*/
-#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH))
+#define STUB_SIG_MASK (1 << SIGVTALRM)
/* Signals that the stub will finish with - anything else is an error */
-#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP))
+#define STUB_DONE_MASK (1 << SIGTRAP)
void wait_stub_done(int pid)
{
@@ -72,9 +73,11 @@ void wait_stub_done(int pid)
break;
err = ptrace(PTRACE_CONT, pid, 0, 0);
- if (err)
- panic("wait_stub_done : continue failed, errno = %d\n",
- errno);
+ if (err) {
+ printk(UM_KERN_ERR "wait_stub_done : continue failed, "
+ "errno = %d\n", errno);
+ fatal_sigsegv();
+ }
}
if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
@@ -85,8 +88,10 @@ bad_wait:
if (err)
printk(UM_KERN_ERR "Failed to get registers from stub, "
"errno = %d\n", -err);
- panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, "
- "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status);
+ printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, "
+ "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno,
+ status);
+ fatal_sigsegv();
}
extern unsigned long current_stub_stack(void);
@@ -97,9 +102,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
if (ptrace_faultinfo) {
err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
- if (err)
- panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
- "errno = %d\n", errno);
+ if (err) {
+ printk(UM_KERN_ERR "get_skas_faultinfo - "
+ "PTRACE_FAULTINFO failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
/* Special handling for i386, which has different structs */
if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
@@ -109,9 +116,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
}
else {
err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
- if (err)
- panic("Failed to continue stub, pid = %d, errno = %d\n",
- pid, errno);
+ if (err) {
+ printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
+ "errno = %d\n", pid, errno);
+ fatal_sigsegv();
+ }
wait_stub_done(pid);
/*
@@ -137,6 +146,9 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
{
int err, status;
+ if ((UPT_IP(regs) >= STUB_START) && (UPT_IP(regs) < STUB_END))
+ fatal_sigsegv();
+
/* Mark this as a syscall */
UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp);
@@ -144,25 +156,31 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
{
err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
__NR_getpid);
- if (err < 0)
- panic("handle_trap - nullifying syscall failed, "
- "errno = %d\n", errno);
+ if (err < 0) {
+ printk(UM_KERN_ERR "handle_trap - nullifying syscall "
+ "failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
- if (err < 0)
- panic("handle_trap - continuing to end of syscall "
- "failed, errno = %d\n", errno);
+ if (err < 0) {
+ printk(UM_KERN_ERR "handle_trap - continuing to end of "
+ "syscall failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
if ((err < 0) || !WIFSTOPPED(status) ||
- (WSTOPSIG(status) != SIGTRAP + 0x80)) {
- err = ptrace_dump_regs(pid);
- if (err)
- printk(UM_KERN_ERR "Failed to get registers "
+ (WSTOPSIG(status) != SIGTRAP + 0x80)) {
+ err = ptrace_dump_regs(pid);
+ if (err)
+ printk(UM_KERN_ERR "Failed to get registers "
"from process, errno = %d\n", -err);
- panic("handle_trap - failed to wait at end of syscall, "
- "errno = %d, status = %d\n", errno, status);
- }
+ printk(UM_KERN_ERR "handle_trap - failed to wait at "
+ "end of syscall, errno = %d, status = %d\n",
+ errno, status);
+ fatal_sigsegv();
+ }
}
handle_syscall(regs);
@@ -178,10 +196,13 @@ static int userspace_tramp(void *stack)
ptrace(PTRACE_TRACEME, 0, 0, 0);
signal(SIGTERM, SIG_DFL);
+ signal(SIGWINCH, SIG_IGN);
err = set_interval();
- if (err)
- panic("userspace_tramp - setting timer failed, errno = %d\n",
- err);
+ if (err) {
+ printk(UM_KERN_ERR "userspace_tramp - setting timer failed, "
+ "errno = %d\n", err);
+ exit(1);
+ }
if (!proc_mm) {
/*
@@ -221,16 +242,14 @@ static int userspace_tramp(void *stack)
set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGIO);
- sigaddset(&sa.sa_mask, SIGWINCH);
- sigaddset(&sa.sa_mask, SIGVTALRM);
- sigaddset(&sa.sa_mask, SIGUSR1);
- sa.sa_flags = SA_ONSTACK;
+ sa.sa_flags = SA_ONSTACK | SA_NODEFER;
sa.sa_handler = (void *) v;
sa.sa_restorer = NULL;
- if (sigaction(SIGSEGV, &sa, NULL) < 0)
- panic("userspace_tramp - setting SIGSEGV handler "
- "failed - errno = %d\n", errno);
+ if (sigaction(SIGSEGV, &sa, NULL) < 0) {
+ printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
+ "handler failed - errno = %d\n", errno);
+ exit(1);
+ }
}
kill(os_getpid(), SIGSTOP);
@@ -246,13 +265,18 @@ int start_userspace(unsigned long stub_stack)
{
void *stack;
unsigned long sp;
- int pid, status, n, flags;
+ int pid, status, n, flags, err;
stack = mmap(NULL, UM_KERN_PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (stack == MAP_FAILED)
- panic("start_userspace : mmap failed, errno = %d", errno);
+ if (stack == MAP_FAILED) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : mmap failed, "
+ "errno = %d\n", errno);
+ return err;
+ }
+
sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
flags = CLONE_FILES;
@@ -262,29 +286,50 @@ int start_userspace(unsigned long stub_stack)
flags |= SIGCHLD;
pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
- if (pid < 0)
- panic("start_userspace : clone failed, errno = %d", errno);
+ if (pid < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : clone failed, "
+ "errno = %d\n", errno);
+ return err;
+ }
do {
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
- if (n < 0)
- panic("start_userspace : wait failed, errno = %d",
- errno);
+ if (n < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : wait failed, "
+ "errno = %d\n", errno);
+ goto out_kill;
+ }
} while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
- if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
- panic("start_userspace : expected SIGSTOP, got status = %d",
- status);
+ if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {
+ err = -EINVAL;
+ printk(UM_KERN_ERR "start_userspace : expected SIGSTOP, got "
+ "status = %d\n", status);
+ goto out_kill;
+ }
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
- (void *) PTRACE_O_TRACESYSGOOD) < 0)
- panic("start_userspace : PTRACE_OLDSETOPTIONS failed, "
- "errno = %d\n", errno);
+ (void *) PTRACE_O_TRACESYSGOOD) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : PTRACE_OLDSETOPTIONS "
+ "failed, errno = %d\n", errno);
+ goto out_kill;
+ }
- if (munmap(stack, UM_KERN_PAGE_SIZE) < 0)
- panic("start_userspace : munmap failed, errno = %d\n", errno);
+ if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "start_userspace : munmap failed, "
+ "errno = %d\n", errno);
+ goto out_kill;
+ }
return pid;
+
+ out_kill:
+ os_kill_ptraced_process(pid, 1);
+ return err;
}
void userspace(struct uml_pt_regs *regs)
@@ -296,13 +341,22 @@ void userspace(struct uml_pt_regs *regs)
int local_using_sysemu;
if (getitimer(ITIMER_VIRTUAL, &timer))
- printk("Failed to get itimer, errno = %d\n", errno);
+ printk(UM_KERN_ERR "Failed to get itimer, errno = %d\n", errno);
nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC +
timer.it_value.tv_usec * UM_NSEC_PER_USEC;
nsecs += os_nsecs();
while (1) {
- restore_registers(pid, regs);
+ /*
+ * This can legitimately fail if the process loads a
+ * bogus value into a segment register. It will
+ * segfault and PTRACE_GETREGS will read that value
+ * out of the process. However, PTRACE_SETREGS will
+ * fail. In this case, there is nothing to do but
+ * just kill the process.
+ */
+ if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp))
+ fatal_sigsegv();
/* Now we set local_using_sysemu to be used for one loop */
local_using_sysemu = get_using_sysemu();
@@ -310,24 +364,31 @@ void userspace(struct uml_pt_regs *regs)
op = SELECT_PTRACE_OPERATION(local_using_sysemu,
singlestepping(NULL));
- err = ptrace(op, pid, 0, 0);
- if (err)
- panic("userspace - could not resume userspace process, "
- "pid=%d, ptrace operation = %d, errno = %d\n",
- pid, op, errno);
+ if (ptrace(op, pid, 0, 0)) {
+ printk(UM_KERN_ERR "userspace - ptrace continue "
+ "failed, op = %d, errno = %d\n", op, errno);
+ fatal_sigsegv();
+ }
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
- if (err < 0)
- panic("userspace - waitpid failed, errno = %d\n",
- errno);
+ if (err < 0) {
+ printk(UM_KERN_ERR "userspace - wait failed, "
+ "errno = %d\n", errno);
+ fatal_sigsegv();
+ }
regs->is_user = 1;
- save_registers(pid, regs);
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) {
+ printk(UM_KERN_ERR "userspace - PTRACE_GETREGS failed, "
+ "errno = %d\n", errno);
+ fatal_sigsegv();
+ }
+
UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
if (WIFSTOPPED(status)) {
int sig = WSTOPSIG(status);
- switch(sig) {
+ switch (sig) {
case SIGSEGV:
if (PTRACE_FULL_FAULTINFO ||
!ptrace_faultinfo) {
@@ -345,7 +406,7 @@ void userspace(struct uml_pt_regs *regs)
break;
case SIGVTALRM:
now = os_nsecs();
- if(now < nsecs)
+ if (now < nsecs)
break;
block_signals();
(*sig_info[sig])(sig, regs);
@@ -368,6 +429,7 @@ void userspace(struct uml_pt_regs *regs)
default:
printk(UM_KERN_ERR "userspace - child stopped "
"with signal %d\n", sig);
+ fatal_sigsegv();
}
pid = userspace_pid[0];
interrupt_end();
@@ -419,9 +481,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
.it_interval = tv }) });
err = ptrace_setregs(pid, thread_regs);
- if (err < 0)
- panic("copy_context_skas0 : PTRACE_SETREGS failed, "
- "pid = %d, errno = %d\n", pid, -err);
+ if (err < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_SETREGS "
+ "failed, pid = %d, errno = %d\n", pid, -err);
+ return err;
+ }
/* set a well known return code for detection of child write failure */
child_data->err = 12345678;
@@ -431,31 +496,47 @@ int copy_context_skas0(unsigned long new_stack, int pid)
* parent's stack, and check, if bad result.
*/
err = ptrace(PTRACE_CONT, pid, 0, 0);
- if (err)
- panic("Failed to continue new process, pid = %d, "
- "errno = %d\n", pid, errno);
+ if (err) {
+ err = -errno;
+ printk(UM_KERN_ERR "Failed to continue new process, pid = %d, "
+ "errno = %d\n", pid, errno);
+ return err;
+ }
+
wait_stub_done(pid);
pid = data->err;
- if (pid < 0)
- panic("copy_context_skas0 - stub-parent reports error %d\n",
- -pid);
+ if (pid < 0) {
+ printk(UM_KERN_ERR "copy_context_skas0 - stub-parent reports "
+ "error %d\n", -pid);
+ return pid;
+ }
/*
* Wait, until child has finished too: read child's result from
* child's stack and check it.
*/
wait_stub_done(pid);
- if (child_data->err != STUB_DATA)
- panic("copy_context_skas0 - stub-child reports error %ld\n",
- child_data->err);
+ if (child_data->err != STUB_DATA) {
+ printk(UM_KERN_ERR "copy_context_skas0 - stub-child reports "
+ "error %ld\n", child_data->err);
+ err = child_data->err;
+ goto out_kill;
+ }
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
- (void *)PTRACE_O_TRACESYSGOOD) < 0)
- panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, "
- "errno = %d\n", errno);
+ (void *)PTRACE_O_TRACESYSGOOD) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_OLDSETOPTIONS "
+ "failed, errno = %d\n", errno);
+ goto out_kill;
+ }
return pid;
+
+ out_kill:
+ os_kill_ptraced_process(pid, 1);
+ return err;
}
/*
@@ -463,8 +544,8 @@ int copy_context_skas0(unsigned long new_stack, int pid)
* available. Opening /proc/mm creates a new mm_context, which lacks
* the stub-pages. Thus, we map them using /proc/mm-fd
*/
-void map_stub_pages(int fd, unsigned long code,
- unsigned long data, unsigned long stack)
+int map_stub_pages(int fd, unsigned long code, unsigned long data,
+ unsigned long stack)
{
struct proc_mm_op mmop;
int n;
@@ -488,8 +569,9 @@ void map_stub_pages(int fd, unsigned long code,
printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, "
"offset = %llx\n", code, code_fd,
(unsigned long long) code_offset);
- panic("map_stub_pages : /proc/mm map for code failed, "
- "err = %d\n", n);
+ printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for code "
+ "failed, err = %d\n", n);
+ return -n;
}
if (stack) {
@@ -507,10 +589,15 @@ void map_stub_pages(int fd, unsigned long code,
.offset = map_offset
} } });
CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
- if (n != sizeof(mmop))
- panic("map_stub_pages : /proc/mm map for data failed, "
- "err = %d\n", errno);
+ if (n != sizeof(mmop)) {
+ n = errno;
+ printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for "
+ "data failed, err = %d\n", n);
+ return -n;
+ }
}
+
+ return 0;
}
void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
@@ -554,7 +641,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
* after returning to the jumper.
*/
n = setjmp(initial_jmpbuf);
- switch(n) {
+ switch (n) {
case INIT_JMP_NEW_THREAD:
(*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
(*switch_buf)[0].JB_SP = (unsigned long) stack +
@@ -571,7 +658,9 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
kmalloc_ok = 0;
return 1;
default:
- panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
+ printk(UM_KERN_ERR "Bad sigsetjmp return in "
+ "start_idle_thread - %d\n", n);
+ fatal_sigsegv();
}
longjmp(*switch_buf, 1);
}
@@ -614,9 +703,11 @@ void __switch_mm(struct mm_id *mm_idp)
if (proc_mm) {
err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
mm_idp->u.mm_fd);
- if (err)
- panic("__switch_mm - PTRACE_SWITCH_MM failed, "
- "errno = %d\n", errno);
+ if (err) {
+ printk(UM_KERN_ERR "__switch_mm - PTRACE_SWITCH_MM "
+ "failed, errno = %d\n", errno);
+ fatal_sigsegv();
+ }
}
else userspace_pid[0] = mm_idp->u.pid;
}
diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c
deleted file mode 100644
index 3b1b9244f46..00000000000
--- a/arch/um/os-Linux/skas/trap.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#if 0
-#include "kern_util.h"
-#include "skas.h"
-#include "ptrace_user.h"
-#include "sysdep/ptrace_user.h"
-#endif
-
-#include <errno.h>
-#include <signal.h>
-#include "sysdep/ptrace.h"
-#include "kern_constants.h"
-#include "as-layout.h"
-#include "os.h"
-#include "sigcontext.h"
-#include "task.h"
-
-static struct uml_pt_regs ksig_regs[UM_NR_CPUS];
-
-void sig_handler_common_skas(int sig, void *sc_ptr)
-{
- struct sigcontext *sc = sc_ptr;
- struct uml_pt_regs *r;
- void (*handler)(int, struct uml_pt_regs *);
- int save_user, save_errno = errno;
-
- /*
- * This is done because to allow SIGSEGV to be delivered inside a SEGV
- * handler. This can happen in copy_user, and if SEGV is disabled,
- * the process will die.
- * XXX Figure out why this is better than SA_NODEFER
- */
- if (sig == SIGSEGV) {
- change_sig(SIGSEGV, 1);
- /*
- * For segfaults, we want the data from the
- * sigcontext. In this case, we don't want to mangle
- * the process registers, so use a static set of
- * registers. For other signals, the process
- * registers are OK.
- */
- r = &ksig_regs[cpu()];
- copy_sc(r, sc_ptr);
- }
- else r = TASK_REGS(get_current());
-
- save_user = r->is_user;
- r->is_user = 0;
- if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
- (sig == SIGILL) || (sig == SIGTRAP))
- GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
-
- change_sig(SIGUSR1, 1);
-
- handler = sig_info[sig];
-
- /* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */
- if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
- unblock_signals();
-
- handler(sig, r);
-
- errno = save_errno;
- r->is_user = save_user;
-}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 7b81f6c08a5..b616e15638f 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -60,10 +60,11 @@ static int ptrace_child(void)
* the UML code itself.
*/
ret = 2;
- _exit(ret);
+
+ exit(ret);
}
-static void fatal_perror(char *str)
+static void fatal_perror(const char *str)
{
perror(str);
exit(1);
@@ -341,6 +342,8 @@ static void __init check_coredump_limit(void)
void __init os_early_checks(void)
{
+ int pid;
+
/* Print out the core dump limits early */
check_coredump_limit();
@@ -350,6 +353,11 @@ void __init os_early_checks(void)
* kernel is running.
*/
check_tmpexec();
+
+ pid = start_ptraced_child();
+ if (init_registers(pid))
+ fatal("Failed to initialize default registers");
+ stop_ptraced_child(pid, 1, 1);
}
static int __init noprocmm_cmd_param(char *str, int* add)
@@ -411,7 +419,6 @@ static inline void check_skas3_ptrace_faultinfo(void)
non_fatal("found\n");
}
- init_registers(pid);
stop_ptraced_child(pid, 1, 1);
}
@@ -466,7 +473,7 @@ static inline void check_skas3_proc_mm(void)
else non_fatal("found\n");
}
-int can_do_skas(void)
+void can_do_skas(void)
{
non_fatal("Checking for the skas3 patch in the host:\n");
@@ -476,8 +483,6 @@ int can_do_skas(void)
if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt)
skas_needs_stub = 1;
-
- return 1;
}
int __init parse_iomem(char *str, int *add)
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
index a841262c594..b4bc6ac4f30 100644
--- a/arch/um/os-Linux/sys-i386/Makefile
+++ b/arch/um/os-Linux/sys-i386/Makefile
@@ -3,7 +3,7 @@
# Licensed under the GPL
#
-obj-y = registers.o signal.o tls.o
+obj-y = registers.o signal.o task_size.o tls.o
USER_OBJS := $(obj-y)
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index d1997ca76e5..f74d853a0ee 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -62,10 +62,10 @@ void arch_init_registers(int pid)
int err;
err = ptrace(PTRACE_GETFPXREGS, pid, 0, fpx_regs);
- if(!err)
+ if (!err)
return;
- if(errno != EIO)
+ if (errno != EIO)
panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
errno);
diff --git a/arch/um/os-Linux/sys-i386/task_size.c b/arch/um/os-Linux/sys-i386/task_size.c
new file mode 100644
index 00000000000..48d211b3d9a
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/task_size.c
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include "longjmp.h"
+#include "kern_constants.h"
+
+static jmp_buf buf;
+
+static void segfault(int sig)
+{
+ longjmp(buf, 1);
+}
+
+static int page_ok(unsigned long page)
+{
+ unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
+ unsigned long n = ~0UL;
+ void *mapped = NULL;
+ int ok = 0;
+
+ /*
+ * First see if the page is readable. If it is, it may still
+ * be a VDSO, so we go on to see if it's writable. If not
+ * then try mapping memory there. If that fails, then we're
+ * still in the kernel area. As a sanity check, we'll fail if
+ * the mmap succeeds, but gives us an address different from
+ * what we wanted.
+ */
+ if (setjmp(buf) == 0)
+ n = *address;
+ else {
+ mapped = mmap(address, UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (mapped == MAP_FAILED)
+ return 0;
+ if (mapped != address)
+ goto out;
+ }
+
+ /*
+ * Now, is it writeable? If so, then we're in user address
+ * space. If not, then try mprotecting it and try the write
+ * again.
+ */
+ if (setjmp(buf) == 0) {
+ *address = n;
+ ok = 1;
+ goto out;
+ } else if (mprotect(address, UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_WRITE) != 0)
+ goto out;
+
+ if (setjmp(buf) == 0) {
+ *address = n;
+ ok = 1;
+ }
+
+ out:
+ if (mapped != NULL)
+ munmap(mapped, UM_KERN_PAGE_SIZE);
+ return ok;
+}
+
+unsigned long os_get_task_size(void)
+{
+ struct sigaction sa, old;
+ unsigned long bottom = 0;
+ /*
+ * A 32-bit UML on a 64-bit host gets confused about the VDSO at
+ * 0xffffe000. It is mapped, is readable, can be reprotected writeable
+ * and written. However, exec discovers later that it can't be
+ * unmapped. So, just set the highest address to be checked to just
+ * below it. This might waste some address space on 4G/4G 32-bit
+ * hosts, but shouldn't hurt otherwise.
+ */
+ unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
+ unsigned long test;
+
+ printf("Locating the top of the address space ... ");
+ fflush(stdout);
+
+ /*
+ * We're going to be longjmping out of the signal handler, so
+ * SA_DEFER needs to be set.
+ */
+ sa.sa_handler = segfault;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_NODEFER;
+ sigaction(SIGSEGV, &sa, &old);
+
+ if (!page_ok(bottom)) {
+ fprintf(stderr, "Address 0x%x no good?\n",
+ bottom << UM_KERN_PAGE_SHIFT);
+ exit(1);
+ }
+
+ /* This could happen with a 4G/4G split */
+ if (page_ok(top))
+ goto out;
+
+ do {
+ test = bottom + (top - bottom) / 2;
+ if (page_ok(test))
+ bottom = test;
+ else
+ top = test;
+ } while (top - bottom > 1);
+
+out:
+ /* Restore the old SIGSEGV handling */
+ sigaction(SIGSEGV, &old, NULL);
+
+ top <<= UM_KERN_PAGE_SHIFT;
+ printf("0x%x\n", top);
+ fflush(stdout);
+
+ return top;
+}
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
index a42a4ef02e1..a44a47f8f57 100644
--- a/arch/um/os-Linux/sys-x86_64/Makefile
+++ b/arch/um/os-Linux/sys-x86_64/Makefile
@@ -3,7 +3,7 @@
# Licensed under the GPL
#
-obj-y = registers.o prctl.o signal.o
+obj-y = registers.o prctl.o signal.o task_size.o
USER_OBJS := $(obj-y)
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index 9bfa789992d..a375853337a 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Copyright (C) 2006 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -7,31 +7,36 @@
#include <sys/ptrace.h>
#define __FRAME_OFFSETS
#include <asm/ptrace.h>
+#include "kern_constants.h"
#include "longjmp.h"
#include "user.h"
int save_fp_registers(int pid, unsigned long *fp_regs)
{
- if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
+ if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
return -errno;
return 0;
}
int restore_fp_registers(int pid, unsigned long *fp_regs)
{
- if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
+ if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
return -errno;
return 0;
}
unsigned long get_thread_reg(int reg, jmp_buf *buf)
{
- switch(reg){
- case RIP: return buf[0]->__rip;
- case RSP: return buf[0]->__rsp;
- case RBP: return buf[0]->__rbp;
+ switch (reg) {
+ case RIP:
+ return buf[0]->__rip;
+ case RSP:
+ return buf[0]->__rsp;
+ case RBP:
+ return buf[0]->__rbp;
default:
- printk("get_thread_regs - unknown register %d\n", reg);
+ printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n",
+ reg);
return 0;
}
}
diff --git a/arch/um/os-Linux/sys-x86_64/task_size.c b/arch/um/os-Linux/sys-x86_64/task_size.c
new file mode 100644
index 00000000000..fad6f57f8ee
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/task_size.c
@@ -0,0 +1,5 @@
+unsigned long os_get_task_size(unsigned long shift)
+{
+ /* The old value of CONFIG_TOP_ADDR */
+ return 0x7fc0000000;
+}
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
deleted file mode 100644
index 2a1c9843e32..00000000000
--- a/arch/um/os-Linux/trap.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include "os.h"
-#include "sysdep/ptrace.h"
-
-/* Initialized from linux_main() */
-void (*sig_info[NSIG])(int, struct uml_pt_regs *);
-
-void os_fill_handlinfo(struct kern_handlers h)
-{
- sig_info[SIGTRAP] = h.relay_signal;
- sig_info[SIGFPE] = h.relay_signal;
- sig_info[SIGILL] = h.relay_signal;
- sig_info[SIGWINCH] = h.winch;
- sig_info[SIGBUS] = h.bus_handler;
- sig_info[SIGSEGV] = h.page_fault;
- sig_info[SIGIO] = h.sigio_handler;
- sig_info[SIGVTALRM] = h.timer_handler;
-}
diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c
index 4cfdd18ea1e..b09ff66a77e 100644
--- a/arch/um/os-Linux/tty.c
+++ b/arch/um/os-Linux/tty.c
@@ -1,13 +1,16 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <stdlib.h>
+#include <unistd.h>
#include <errno.h>
+#include <fcntl.h>
+#include "kern_constants.h"
+#include "kern_util.h"
#include "os.h"
#include "user.h"
-#include "kern_util.h"
struct grantpt_info {
int fd;
@@ -26,36 +29,34 @@ static void grantpt_cb(void *arg)
int get_pty(void)
{
struct grantpt_info info;
- int fd;
-
- fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0);
- if(fd < 0){
- printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd);
- return(fd);
+ int fd, err;
+
+ fd = open("/dev/ptmx", O_RDWR);
+ if (fd < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "get_pty : Couldn't open /dev/ptmx - "
+ "err = %d\n", errno);
+ return err;
}
info.fd = fd;
initial_thread_cb(grantpt_cb, &info);
- if(info.res < 0){
- printk("get_pty : Couldn't grant pty - errno = %d\n",
- -info.err);
- return(-1);
+ if (info.res < 0) {
+ err = -info.err;
+ printk(UM_KERN_ERR "get_pty : Couldn't grant pty - "
+ "errno = %d\n", -info.err);
+ goto out;
}
- if(unlockpt(fd) < 0){
- printk("get_pty : Couldn't unlock pty - errno = %d\n", errno);
- return(-1);
+
+ if (unlockpt(fd) < 0) {
+ err = -errno;
+ printk(UM_KERN_ERR "get_pty : Couldn't unlock pty - "
+ "errno = %d\n", errno);
+ goto out;
}
- return(fd);
+ return fd;
+out:
+ close(fd);
+ return err;
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/tty_log.c b/arch/um/os-Linux/tty_log.c
index d11a55baa6b..cc648e6fd3a 100644
--- a/arch/um/os-Linux/tty_log.c
+++ b/arch/um/os-Linux/tty_log.c
@@ -12,7 +12,6 @@
#include <sys/time.h>
#include "init.h"
#include "user.h"
-#include "kern_util.h"
#include "os.h"
#define TTY_LOG_DIR "./"
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 8d27b6d1df9..087ed74ffca 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
@@ -16,7 +16,7 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
jmp_buf jbuf;
*fault_catcher = &jbuf;
- if(UML_SETJMP(&jbuf) == 0){
+ if (UML_SETJMP(&jbuf) == 0) {
(*op)(to, from, n);
ret = 0;
*faulted_out = 0;
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 4c37b1b1d0b..74f49bb9b12 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -34,8 +34,8 @@ EXPORT_SYMBOL(printf);
* good; so the versions of these symbols will always match
*/
#define EXPORT_SYMBOL_PROTO(sym) \
- int sym(void); \
- EXPORT_SYMBOL(sym);
+ int sym(void); \
+ EXPORT_SYMBOL(sym);
extern void readdir64(void) __attribute__((weak));
EXPORT_SYMBOL(readdir64);
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 3e058ce9ffb..6ea77979531 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -1,39 +1,24 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <limits.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/utsname.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include "asm/types.h"
-#include <ctype.h>
-#include <signal.h>
-#include <wait.h>
#include <errno.h>
-#include <stdarg.h>
-#include <sched.h>
-#include <termios.h>
+#include <signal.h>
#include <string.h>
-#include "kern_util.h"
-#include "user.h"
-#include "mem_user.h"
-#include "init.h"
-#include "ptrace_user.h"
-#include "uml-config.h"
-#include "os.h"
-#include "longjmp.h"
+#include <termios.h>
+#include <wait.h>
+#include <sys/mman.h>
+#include <sys/utsname.h>
#include "kern_constants.h"
+#include "os.h"
+#include "user.h"
void stack_protections(unsigned long address)
{
- if(mprotect((void *) address, UM_THREAD_SIZE,
+ if (mprotect((void *) address, UM_THREAD_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
panic("protecting stack failed, errno = %d", errno);
}
@@ -44,17 +29,19 @@ int raw(int fd)
int err;
CATCH_EINTR(err = tcgetattr(fd, &tt));
- if(err < 0)
+ if (err < 0)
return -errno;
cfmakeraw(&tt);
CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
- if(err < 0)
+ if (err < 0)
return -errno;
- /* XXX tcsetattr could have applied only some changes
- * (and cfmakeraw() is a set of changes) */
+ /*
+ * XXX tcsetattr could have applied only some changes
+ * (and cfmakeraw() is a set of changes)
+ */
return 0;
}
@@ -88,21 +75,6 @@ void setup_hostinfo(char *buf, int len)
host.release, host.version, host.machine);
}
-int setjmp_wrapper(void (*proc)(void *, void *), ...)
-{
- va_list args;
- jmp_buf buf;
- int n;
-
- n = UML_SETJMP(&buf);
- if(n == 0){
- va_start(args, proc);
- (*proc)(&buf, &args);
- }
- va_end(args);
- return n;
-}
-
void os_dump_core(void)
{
int pid;
diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c
index a4360b5207d..8d4f273f121 100644
--- a/arch/um/sys-i386/bug.c
+++ b/arch/um/sys-i386/bug.c
@@ -4,6 +4,7 @@
*/
#include <linux/uaccess.h>
+#include <asm/errno.h>
/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
* that's not relevant in skas mode.
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
index 806895d73bc..a74442d1376 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/um/sys-i386/bugs.c
@@ -3,171 +3,47 @@
* Licensed under the GPL
*/
-#include <errno.h>
#include <signal.h>
-#include <string.h>
#include "kern_constants.h"
-#include "os.h"
+#include "kern_util.h"
+#include "longjmp.h"
#include "task.h"
#include "user.h"
-
-#define MAXTOKEN 64
+#include "sysdep/ptrace.h"
/* Set during early boot */
int host_has_cmov = 1;
-int host_has_xmm = 0;
+static jmp_buf cmov_test_return;
-static char token(int fd, char *buf, int len, char stop)
+static void cmov_sigill_test_handler(int sig)
{
- int n;
- char *ptr, *end, c;
-
- ptr = buf;
- end = &buf[len];
- do {
- n = os_read_file(fd, ptr, sizeof(*ptr));
- c = *ptr++;
- if (n != sizeof(*ptr)) {
- if (n == 0)
- return 0;
- printk(UM_KERN_ERR "Reading /proc/cpuinfo failed, "
- "err = %d\n", -n);
- if (n < 0)
- return n;
- else return -EIO;
- }
- } while ((c != '\n') && (c != stop) && (ptr < end));
-
- if (ptr == end) {
- printk(UM_KERN_ERR "Failed to find '%c' in /proc/cpuinfo\n",
- stop);
- return -1;
- }
- *(ptr - 1) = '\0';
- return c;
-}
-
-static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
-{
- int n;
- char c;
-
- scratch[len - 1] = '\0';
- while (1) {
- c = token(fd, scratch, len - 1, ':');
- if (c <= 0)
- return 0;
- else if (c != ':') {
- printk(UM_KERN_ERR "Failed to find ':' in "
- "/proc/cpuinfo\n");
- return 0;
- }
-
- if (!strncmp(scratch, key, strlen(key)))
- return 1;
-
- do {
- n = os_read_file(fd, &c, sizeof(c));
- if (n != sizeof(c)) {
- printk(UM_KERN_ERR "Failed to find newline in "
- "/proc/cpuinfo, err = %d\n", -n);
- return 0;
- }
- } while (c != '\n');
- }
- return 0;
+ host_has_cmov = 0;
+ longjmp(cmov_test_return, 1);
}
-static int check_cpu_flag(char *feature, int *have_it)
-{
- char buf[MAXTOKEN], c;
- int fd, len = ARRAY_SIZE(buf);
-
- printk(UM_KERN_INFO "Checking for host processor %s support...",
- feature);
- fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
- if (fd < 0) {
- printk(UM_KERN_ERR "Couldn't open /proc/cpuinfo, err = %d\n",
- -fd);
- return 0;
- }
-
- *have_it = 0;
- if (!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf)))
- goto out;
-
- c = token(fd, buf, len - 1, ' ');
- if (c < 0)
- goto out;
- else if (c != ' ') {
- printk(UM_KERN_ERR "Failed to find ' ' in /proc/cpuinfo\n");
- goto out;
- }
-
- while (1) {
- c = token(fd, buf, len - 1, ' ');
- if (c < 0)
- goto out;
- else if (c == '\n')
- break;
-
- if (!strcmp(buf, feature)) {
- *have_it = 1;
- goto out;
- }
- }
- out:
- if (*have_it == 0)
- printk("No\n");
- else if (*have_it == 1)
- printk("Yes\n");
- os_close_file(fd);
- return 1;
-}
-
-#if 0 /*
- * This doesn't work in tt mode, plus it's causing compilation problems
- * for some people.
- */
-static void disable_lcall(void)
+void arch_check_bugs(void)
{
- struct modify_ldt_ldt_s ldt;
- int err;
+ struct sigaction old, new;
- bzero(&ldt, sizeof(ldt));
- ldt.entry_number = 7;
- ldt.base_addr = 0;
- ldt.limit = 0;
- err = modify_ldt(1, &ldt, sizeof(ldt));
- if (err)
- printk(UM_KERN_ERR "Failed to disable lcall7 - errno = %d\n",
- errno);
-}
-#endif
+ printk(UM_KERN_INFO "Checking for host processor cmov support...");
+ new.sa_handler = cmov_sigill_test_handler;
-void arch_init_thread(void)
-{
-#if 0
- disable_lcall();
-#endif
-}
+ /* Make sure that SIGILL is enabled after the handler longjmps back */
+ new.sa_flags = SA_NODEFER;
+ sigemptyset(&new.sa_mask);
+ sigaction(SIGILL, &new, &old);
-void arch_check_bugs(void)
-{
- int have_it;
+ if (setjmp(cmov_test_return) == 0) {
+ unsigned long foo = 0;
+ __asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
+ printk(UM_KERN_CONT "Yes\n");
+ } else
+ printk(UM_KERN_CONT "No\n");
- if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) {
- printk(UM_KERN_ERR "/proc/cpuinfo not available - skipping CPU "
- "capability checks\n");
- return;
- }
- if (check_cpu_flag("cmov", &have_it))
- host_has_cmov = have_it;
- if (check_cpu_flag("xmm", &have_it))
- host_has_xmm = have_it;
+ sigaction(SIGILL, &old, &new);
}
-int arch_handle_signal(int sig, struct uml_pt_regs *regs)
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
{
unsigned char tmp[2];
@@ -176,24 +52,25 @@ int arch_handle_signal(int sig, struct uml_pt_regs *regs)
* SIGILL in init.
*/
if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
- return 0;
+ return;
+
+ if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
+ printk(UM_KERN_ERR "SIGILL in init, could not read "
+ "instructions!\n");
+ return;
+ }
- if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2))
- panic("SIGILL in init, could not read instructions!\n");
if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
- return 0;
+ return;
if (host_has_cmov == 0)
- panic("SIGILL caused by cmov, which this processor doesn't "
- "implement, boot a filesystem compiled for older "
- "processors");
+ printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+ "processor doesn't implement. Boot a filesystem "
+ "compiled for older processors");
else if (host_has_cmov == 1)
- panic("SIGILL caused by cmov, which this processor claims to "
- "implement");
- else if (host_has_cmov == -1)
- panic("SIGILL caused by cmov, couldn't tell if this processor "
- "implements it, boot a filesystem compiled for older "
- "processors");
- else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
- return 0;
+ printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
+ "processor claims to implement");
+ else
+ printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
+ host_has_cmov);
}
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 67c0958eb98..a34263e6b08 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -3,8 +3,9 @@
* Licensed under the GPL
*/
-#include "linux/mm.h"
-#include "asm/unistd.h"
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <asm/unistd.h>
#include "os.h"
#include "proc_mm.h"
#include "skas.h"
@@ -146,7 +147,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
if (ptrace_ldt)
return read_ldt_from_host(ptr, bytecount);
- down(&ldt->semaphore);
+ mutex_lock(&ldt->lock);
if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
if (size > bytecount)
@@ -170,7 +171,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
ptr += size;
}
}
- up(&ldt->semaphore);
+ mutex_unlock(&ldt->lock);
if (bytecount == 0 || err == -EFAULT)
goto out;
@@ -228,7 +229,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
}
if (!ptrace_ldt)
- down(&ldt->semaphore);
+ mutex_lock(&ldt->lock);
err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
if (err)
@@ -288,7 +289,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
err = 0;
out_unlock:
- up(&ldt->semaphore);
+ mutex_unlock(&ldt->lock);
out:
return err;
}
@@ -395,7 +396,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
if (!ptrace_ldt)
- init_MUTEX(&new_mm->ldt.semaphore);
+ mutex_init(&new_mm->ldt.lock);
if (!from_mm) {
memset(&desc, 0, sizeof(desc));
@@ -455,7 +456,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
* i.e., we have to use the stub for modify_ldt, which
* can't handle the big read buffer of up to 64kB.
*/
- down(&from_mm->ldt.semaphore);
+ mutex_lock(&from_mm->ldt.lock);
if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES)
memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
sizeof(new_mm->ldt.u.entries));
@@ -474,7 +475,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
}
}
new_mm->ldt.entry_count = from_mm->ldt.entry_count;
- up(&from_mm->ldt.semaphore);
+ mutex_unlock(&from_mm->ldt.lock);
}
out:
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index bd3da8a61f6..6b4499906a6 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -8,11 +8,11 @@
#include "asm/uaccess.h"
#include "skas.h"
-extern int arch_switch_tls(struct task_struct *from, struct task_struct *to);
+extern int arch_switch_tls(struct task_struct *to);
-void arch_switch_to(struct task_struct *from, struct task_struct *to)
+void arch_switch_to(struct task_struct *to)
{
- int err = arch_switch_tls(from, to);
+ int err = arch_switch_tls(to);
if (!err)
return;
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 5cf97bc229b..0b10c3e7402 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -19,17 +19,3 @@ int ptrace_setregs(long pid, unsigned long *regs)
return -errno;
return 0;
}
-
-int ptrace_getfpregs(long pid, unsigned long *regs)
-{
- if (ptrace(PTRACE_GETFPREGS, pid, 0, regs) < 0)
- return -errno;
- return 0;
-}
-
-int ptrace_setfpregs(long pid, unsigned long *regs)
-{
- if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
- return -errno;
- return 0;
-}
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 19053d46cb6..fd0c25ad6af 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -168,12 +168,13 @@ static int copy_sc_from_user(struct pt_regs *regs,
struct sigcontext __user *from)
{
struct sigcontext sc;
- int err;
+ int err, pid;
err = copy_from_user(&sc, from, sizeof(sc));
if (err)
return err;
+ pid = userspace_pid[current_thread_info()->cpu];
copy_sc(&regs->regs, &sc);
if (have_fpx_regs) {
struct user_fxsr_struct fpx;
@@ -187,8 +188,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
if (err)
return 1;
- err = restore_fpx_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fpx);
+ err = restore_fpx_registers(pid, (unsigned long *) &fpx);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - "
"restore_fpx_registers failed, errno = %d\n",
@@ -204,8 +204,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
if (err)
return 1;
- err = restore_fp_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fp);
+ err = restore_fp_registers(pid, (unsigned long *) &fp);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - "
"restore_fp_registers failed, errno = %d\n",
@@ -223,7 +222,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
{
struct sigcontext sc;
struct faultinfo * fi = &current->thread.arch.faultinfo;
- int err;
+ int err, pid;
sc.gs = REGS_GS(regs->regs.gp);
sc.fs = REGS_FS(regs->regs.gp);
@@ -249,11 +248,11 @@ static int copy_sc_to_user(struct sigcontext __user *to,
to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
sc.fpstate = to_fp;
+ pid = userspace_pid[current_thread_info()->cpu];
if (have_fpx_regs) {
struct user_fxsr_struct fpx;
- err = save_fpx_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fpx);
+ err = save_fpx_registers(pid, (unsigned long *) &fpx);
if (err < 0){
printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
"failed, errno = %d\n", err);
@@ -276,8 +275,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
else {
struct user_i387_struct fp;
- err = save_fp_registers(userspace_pid[current_thread->cpu],
- (unsigned long *) &fp);
+ err = save_fp_registers(pid, (unsigned long *) &fp);
if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
return 1;
}
diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S
index e730772c401..7699e89f660 100644
--- a/arch/um/sys-i386/stub.S
+++ b/arch/um/sys-i386/stub.S
@@ -7,7 +7,7 @@
.globl batch_syscall_stub
batch_syscall_stub:
/* load pointer to first operation */
- mov $(ASM_STUB_DATA+8), %esp
+ mov $(STUB_DATA+8), %esp
again:
/* load length of additional data */
@@ -15,12 +15,12 @@ again:
/* if(length == 0) : end of list */
/* write possible 0 to header */
- mov %eax, ASM_STUB_DATA+4
+ mov %eax, STUB_DATA+4
cmpl $0, %eax
jz done
/* save current pointer */
- mov %esp, ASM_STUB_DATA+4
+ mov %esp, STUB_DATA+4
/* skip additional data */
add %eax, %esp
@@ -46,7 +46,7 @@ again:
done:
/* save return value */
- mov %eax, ASM_STUB_DATA
+ mov %eax, STUB_DATA
/* stop */
int3
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
index b3999cb76bf..28ccf737a79 100644
--- a/arch/um/sys-i386/stub_segv.c
+++ b/arch/um/sys-i386/stub_segv.c
@@ -1,32 +1,17 @@
/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <signal.h>
-#include <sys/select.h> /* The only way I can see to get sigset_t */
-#include <asm/unistd.h>
-#include "as-layout.h"
-#include "uml-config.h"
#include "sysdep/stub.h"
#include "sysdep/sigcontext.h"
-#include "sysdep/faultinfo.h"
void __attribute__ ((__section__ (".__syscall_stub")))
stub_segv_handler(int sig)
{
struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
- int pid;
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc);
- pid = stub_syscall0(__NR_getpid);
- stub_syscall2(__NR_kill, pid, SIGUSR1);
-
- /* Load pointer to sigcontext into esp, since we need to leave
- * the stack in its original form when we do the sigreturn here, by
- * hand.
- */
- __asm__ __volatile__("mov %0,%%esp ; movl %1, %%eax ; "
- "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
+ trap_myself();
}
diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S
index 12d4148dba3..00e5f5203ee 100644
--- a/arch/um/sys-i386/sys_call_table.S
+++ b/arch/um/sys-i386/sys_call_table.S
@@ -9,4 +9,9 @@
#define old_mmap old_mmap_i386
+.section .rodata,"a"
+
#include "../../x86/kernel/syscall_table_32.S"
+
+ENTRY(syscall_table_size)
+.long .-sys_call_table
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
index fcaff86b000..c6c7131e563 100644
--- a/arch/um/sys-i386/tls.c
+++ b/arch/um/sys-i386/tls.c
@@ -26,6 +26,11 @@ int do_set_thread_area(struct user_desc *info)
cpu = get_cpu();
ret = os_set_thread_area(info, userspace_pid[cpu]);
put_cpu();
+
+ if (ret)
+ printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, "
+ "index = %d\n", ret, info->entry_number);
+
return ret;
}
@@ -37,6 +42,11 @@ int do_get_thread_area(struct user_desc *info)
cpu = get_cpu();
ret = os_get_thread_area(info, userspace_pid[cpu]);
put_cpu();
+
+ if (ret)
+ printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, "
+ "index = %d\n", ret, info->entry_number);
+
return ret;
}
@@ -172,7 +182,7 @@ void clear_flushed_tls(struct task_struct *task)
* SKAS patch.
*/
-int arch_switch_tls(struct task_struct *from, struct task_struct *to)
+int arch_switch_tls(struct task_struct *to)
{
if (!host_supports_tls)
return 0;
@@ -225,7 +235,8 @@ out:
}
/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
-static int get_tls_entry(struct task_struct* task, struct user_desc *info, int idx)
+static int get_tls_entry(struct task_struct *task, struct user_desc *info,
+ int idx)
{
struct thread_struct *t = &task->thread;
@@ -263,7 +274,7 @@ clear:
goto out;
}
-asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
+int sys_set_thread_area(struct user_desc __user *user_desc)
{
struct user_desc info;
int idx, ret;
@@ -298,7 +309,7 @@ asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
* i386. However the only possible error are caused by bugs.
*/
int ptrace_set_thread_area(struct task_struct *child, int idx,
- struct user_desc __user *user_desc)
+ struct user_desc __user *user_desc)
{
struct user_desc info;
@@ -311,7 +322,7 @@ int ptrace_set_thread_area(struct task_struct *child, int idx,
return set_tls_entry(child, &info, idx, 0);
}
-asmlinkage int sys_get_thread_area(struct user_desc __user *user_desc)
+int sys_get_thread_area(struct user_desc __user *user_desc)
{
struct user_desc info;
int idx, ret;
@@ -355,10 +366,9 @@ out:
return ret;
}
-
/*
- * XXX: This part is probably common to i386 and x86-64. Don't create a common
- * file for now, do that when implementing x86-64 support.
+ * This code is really i386-only, but it detects and logs x86_64 GDT indexes
+ * if a 32-bit UML is running on a 64-bit host.
*/
static int __init __setup_host_supports_tls(void)
{
@@ -367,13 +377,16 @@ static int __init __setup_host_supports_tls(void)
printk(KERN_INFO "Host TLS support detected\n");
printk(KERN_INFO "Detected host type: ");
switch (host_gdt_entry_tls_min) {
- case GDT_ENTRY_TLS_MIN_I386:
- printk("i386\n");
- break;
- case GDT_ENTRY_TLS_MIN_X86_64:
- printk("x86_64\n");
- break;
+ case GDT_ENTRY_TLS_MIN_I386:
+ printk(KERN_CONT "i386");
+ break;
+ case GDT_ENTRY_TLS_MIN_X86_64:
+ printk(KERN_CONT "x86_64");
+ break;
}
+ printk(KERN_CONT " (GDT indexes %d to %d)\n",
+ host_gdt_entry_tls_min,
+ host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES);
} else
printk(KERN_ERR " Host TLS support NOT detected! "
"TLS support inside UML will not work\n");
diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
index a9814a7ae60..08901526e89 100644
--- a/arch/um/sys-ppc/Makefile
+++ b/arch/um/sys-ppc/Makefile
@@ -6,7 +6,7 @@ OBJ = built-in.o
OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \
ptrace_user.o sysrq.o
-EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(TOPDIR)/arch/ppc/kernel
+EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
all: $(OBJ)
@@ -22,25 +22,25 @@ sigcontext.o: sigcontext.c
semaphore.c:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
+ ln -s $(srctree)/arch/ppc/kernel/$@ $@
checksum.S:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/lib/$@ $@
+ ln -s $(srctree)/arch/ppc/lib/$@ $@
mk_defs.c:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
+ ln -s $(srctree)/arch/ppc/kernel/$@ $@
ppc_defs.head:
rm -f $@
- ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
+ ln -s $(srctree)/arch/ppc/kernel/$@ $@
ppc_defs.h: mk_defs.c ppc_defs.head \
- $(TOPDIR)/include/asm-ppc/mmu.h \
- $(TOPDIR)/include/asm-ppc/processor.h \
- $(TOPDIR)/include/asm-ppc/pgtable.h \
- $(TOPDIR)/include/asm-ppc/ptrace.h
+ $(srctree)/include/asm-ppc/mmu.h \
+ $(srctree)/include/asm-ppc/processor.h \
+ $(srctree)/include/asm-ppc/pgtable.h \
+ $(srctree)/include/asm-ppc/ptrace.h
# $(CC) $(CFLAGS) -S mk_defs.c
cp ppc_defs.head ppc_defs.h
# for bk, this way we can write to the file even if it's not checked out
@@ -56,13 +56,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \
checksum.o: checksum.S
rm -f asm
- ln -s $(TOPDIR)/include/asm-ppc asm
+ ln -s $(srctree)/include/asm-ppc asm
$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
rm -f asm
misc.o: misc.S ppc_defs.h
rm -f asm
- ln -s $(TOPDIR)/include/asm-ppc asm
+ ln -s $(srctree)/include/asm-ppc asm
$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
rm -f asm
diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c
index a4360b5207d..e8034e363d8 100644
--- a/arch/um/sys-x86_64/bug.c
+++ b/arch/um/sys-x86_64/bug.c
@@ -5,7 +5,8 @@
#include <linux/uaccess.h>
-/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+/*
+ * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
* that's not relevant in skas mode.
*/
diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c
index 506b6765bbc..44e02ba2a26 100644
--- a/arch/um/sys-x86_64/bugs.c
+++ b/arch/um/sys-x86_64/bugs.c
@@ -6,15 +6,10 @@
#include "sysdep/ptrace.h"
-void arch_init_thread(void)
-{
-}
-
void arch_check_bugs(void)
{
}
-int arch_handle_signal(int sig, struct uml_pt_regs *regs)
+void arch_examine_signal(int sig, struct uml_pt_regs *regs)
{
- return 0;
}
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index b7631b0e9dd..f3458d7d1c5 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -5,13 +5,12 @@
* Licensed under the GPL
*/
-#define __FRAME_OFFSETS
-#include <asm/ptrace.h>
+#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/errno.h>
-#include <linux/mm.h>
+#define __FRAME_OFFSETS
+#include <asm/ptrace.h>
#include <asm/uaccess.h>
-#include <asm/elf.h>
/*
* determines which flags the user has access to.
@@ -24,12 +23,14 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
unsigned long tmp;
#ifdef TIF_IA32
- /* Some code in the 64bit emulation may not be 64bit clean.
- Don't take any chances. */
+ /*
+ * Some code in the 64bit emulation may not be 64bit clean.
+ * Don't take any chances.
+ */
if (test_tsk_thread_flag(child, TIF_IA32))
value &= 0xffffffff;
#endif
- switch (regno){
+ switch (regno) {
case FS:
case GS:
case DS:
@@ -66,7 +67,7 @@ int poke_user(struct task_struct *child, long addr, long data)
if (addr < MAX_REG_OFFSET)
return putreg(child, addr, data);
else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
+ (addr <= offsetof(struct user, u_debugreg[7]))) {
addr -= offsetof(struct user, u_debugreg[0]);
addr = addr >> 2;
if ((addr == 4) || (addr == 5))
@@ -108,11 +109,10 @@ int peek_user(struct task_struct *child, long addr, long data)
return -EIO;
tmp = 0; /* Default return condition */
- if (addr < MAX_REG_OFFSET){
+ if (addr < MAX_REG_OFFSET)
tmp = getreg(child, addr);
- }
else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
- (addr <= offsetof(struct user, u_debugreg[7]))){
+ (addr <= offsetof(struct user, u_debugreg[7]))) {
addr -= offsetof(struct user, u_debugreg[0]);
addr = addr >> 2;
tmp = child->thread.arch.debugregs[addr];
@@ -127,8 +127,9 @@ int is_syscall(unsigned long addr)
int n;
n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
- if (n){
- /* access_process_vm() grants access to vsyscall and stub,
+ if (n) {
+ /*
+ * access_process_vm() grants access to vsyscall and stub,
* while copy_from_user doesn't. Maybe access_process_vm is
* slow, but that doesn't matter, since it will be called only
* in case of singlestepping, if copy_from_user failed.
@@ -155,7 +156,7 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
return err;
n = copy_to_user(buf, fpregs, sizeof(fpregs));
- if(n > 0)
+ if (n > 0)
return -EFAULT;
return n;
diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c
index b5f9c33e311..c57a496d3f5 100644
--- a/arch/um/sys-x86_64/ptrace_user.c
+++ b/arch/um/sys-x86_64/ptrace_user.c
@@ -4,55 +4,19 @@
* Licensed under the GPL
*/
-#include <stddef.h>
#include <errno.h>
#include "ptrace_user.h"
-#include "user.h"
-#include "kern_constants.h"
int ptrace_getregs(long pid, unsigned long *regs_out)
{
- if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
- return(-errno);
- return(0);
-}
-
-int ptrace_setregs(long pid, unsigned long *regs)
-{
- if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
- return(-errno);
+ if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
+ return -errno;
return(0);
}
-int ptrace_setfpregs(long pid, unsigned long *regs)
+int ptrace_setregs(long pid, unsigned long *regs_out)
{
- if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
+ if (ptrace(PTRACE_SETREGS, pid, 0, regs_out) < 0)
return -errno;
- return 0;
-}
-
-void ptrace_pokeuser(unsigned long addr, unsigned long data)
-{
- panic("ptrace_pokeuser");
-}
-
-#define DS 184
-#define ES 192
-#define __USER_DS 0x2b
-
-void arch_enter_kernel(void *task, int pid)
-{
-}
-
-void arch_leave_kernel(void *task, int pid)
-{
-#ifdef UM_USER_CS
- if(ptrace(PTRACE_POKEUSR, pid, CS, UM_USER_CS) < 0)
- printk("POKEUSR CS failed");
-#endif
-
- if(ptrace(PTRACE_POKEUSR, pid, DS, __USER_DS) < 0)
- printk("POKEUSR DS failed");
- if(ptrace(PTRACE_POKEUSR, pid, ES, __USER_DS) < 0)
- printk("POKEUSR ES failed");
+ return(0);
}
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index 14070181407..1a899a7ed7a 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -81,7 +81,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
if (err)
return 1;
- err = restore_fp_registers(userspace_pid[current_thread->cpu],
+ err = restore_fp_registers(userspace_pid[current_thread_info()->cpu],
(unsigned long *) &fp);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - "
@@ -143,7 +143,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
if (err)
return 1;
- err = save_fp_registers(userspace_pid[current_thread->cpu],
+ err = save_fp_registers(userspace_pid[current_thread_info()->cpu],
(unsigned long *) &fp);
if (err < 0) {
printk(KERN_ERR "copy_sc_from_user - restore_fp_registers "
diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S
index 4afe204a6af..56876876315 100644
--- a/arch/um/sys-x86_64/stub.S
+++ b/arch/um/sys-x86_64/stub.S
@@ -8,18 +8,18 @@ syscall_stub:
/* We don't have 64-bit constants, so this constructs the address
* we need.
*/
- movq $(ASM_STUB_DATA >> 32), %rbx
+ movq $(STUB_DATA >> 32), %rbx
salq $32, %rbx
- movq $(ASM_STUB_DATA & 0xffffffff), %rcx
+ movq $(STUB_DATA & 0xffffffff), %rcx
or %rcx, %rbx
movq %rax, (%rbx)
int3
.globl batch_syscall_stub
batch_syscall_stub:
- mov $(ASM_STUB_DATA >> 32), %rbx
+ mov $(STUB_DATA >> 32), %rbx
sal $32, %rbx
- mov $(ASM_STUB_DATA & 0xffffffff), %rax
+ mov $(STUB_DATA & 0xffffffff), %rax
or %rax, %rbx
/* load pointer to first operation */
mov %rbx, %rsp
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index 3afb590f007..ced051afc70 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -1,51 +1,22 @@
/*
- * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
-#include <stddef.h>
#include <signal.h>
-#include <asm/unistd.h>
#include "as-layout.h"
-#include "uml-config.h"
-#include "sysdep/sigcontext.h"
-#include "sysdep/faultinfo.h"
#include "sysdep/stub.h"
-
-/* Copied from sys-x86_64/signal.c - Can't find an equivalent definition
- * in the libc headers anywhere.
- */
-struct rt_sigframe
-{
- char *pretcode;
- struct ucontext uc;
- struct siginfo info;
-};
-
-/* Copied here from <linux/kernel.h> - we're userspace. */
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
+#include "sysdep/faultinfo.h"
+#include "sysdep/sigcontext.h"
void __attribute__ ((__section__ (".__syscall_stub")))
stub_segv_handler(int sig)
{
struct ucontext *uc;
- int pid;
__asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA),
&uc->uc_mcontext);
-
- pid = stub_syscall0(__NR_getpid);
- stub_syscall2(__NR_kill, pid, SIGUSR1);
-
- /* sys_sigreturn expects that the stack pointer will be 8 bytes into
- * the signal frame. So, we use the ucontext pointer, which we know
- * already, to get the signal frame pointer, and add 8 to that.
- */
- __asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
- "g" ((unsigned long)
- container_of(uc, struct rt_sigframe, uc) + 8),
- "g" (__NR_rt_sigreturn));
+ trap_myself();
}
+
diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c
index 71b2ae4ad5d..c128eb89700 100644
--- a/arch/um/sys-x86_64/syscall_table.c
+++ b/arch/um/sys-x86_64/syscall_table.c
@@ -1,5 +1,7 @@
-/* System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
- * with some changes for UML. */
+/*
+ * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
+ * with some changes for UML.
+ */
#include <linux/linkage.h>
#include <linux/sys.h>
@@ -8,22 +10,26 @@
#define __NO_STUBS
-/* Below you can see, in terms of #define's, the differences between the x86-64
- * and the UML syscall table. */
+/*
+ * Below you can see, in terms of #define's, the differences between the x86-64
+ * and the UML syscall table.
+ */
/* Not going to be implemented by UML, since we have no hardware. */
#define stub_iopl sys_ni_syscall
#define sys_ioperm sys_ni_syscall
-/* The UML TLS problem. Note that x86_64 does not implement this, so the below
- * is needed only for the ia32 compatibility. */
-/*#define sys_set_thread_area sys_ni_syscall
-#define sys_get_thread_area sys_ni_syscall*/
+/*
+ * The UML TLS problem. Note that x86_64 does not implement this, so the below
+ * is needed only for the ia32 compatibility.
+ */
/* On UML we call it this way ("old" means it's not mmap2) */
#define sys_mmap old_mmap
-/* On x86-64 sys_uname is actually sys_newuname plus a compatibility trick.
- * See arch/x86_64/kernel/sys_x86_64.c */
+/*
+ * On x86-64 sys_uname is actually sys_newuname plus a compatibility trick.
+ * See arch/x86_64/kernel/sys_x86_64.c
+ */
#define sys_uname sys_uname64
#define stub_clone sys_clone
@@ -46,8 +52,19 @@ typedef void (*sys_call_ptr_t)(void);
extern void sys_ni_syscall(void);
-sys_call_ptr_t sys_call_table[UM_NR_syscall_max+1] __cacheline_aligned = {
- /* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */
- [0 ... UM_NR_syscall_max] = &sys_ni_syscall,
+/*
+ * We used to have a trick here which made sure that holes in the
+ * x86_64 table were filled in with sys_ni_syscall, but a comment in
+ * unistd_64.h says that holes aren't allowed, so the trick was
+ * removed.
+ * The trick looked like this
+ * [0 ... UM_NR_syscall_max] = &sys_ni_syscall
+ * before including unistd_64.h - the later initializations overwrote
+ * the sys_ni_syscall filler.
+ */
+
+sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
#include <asm-x86/unistd_64.h>
};
+
+int syscall_table_size = sizeof(sys_call_table);
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 86f6b18410e..f1199fd34d3 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -48,7 +48,9 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
switch (code) {
case ARCH_SET_FS:
case ARCH_SET_GS:
- restore_registers(pid, &current->thread.regs.regs);
+ ret = restore_registers(pid, &current->thread.regs.regs);
+ if (ret)
+ return ret;
break;
case ARCH_GET_FS:
case ARCH_GET_GS:
@@ -70,10 +72,10 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
switch (code) {
case ARCH_SET_FS:
current->thread.arch.fs = (unsigned long) ptr;
- save_registers(pid, &current->thread.regs.regs);
+ ret = save_registers(pid, &current->thread.regs.regs);
break;
case ARCH_SET_GS:
- save_registers(pid, &current->thread.regs.regs);
+ ret = save_registers(pid, &current->thread.regs.regs);
break;
case ARCH_GET_FS:
ret = put_user(tmp, addr);
@@ -105,7 +107,7 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
return ret;
}
-void arch_switch_to(struct task_struct *from, struct task_struct *to)
+void arch_switch_to(struct task_struct *to)
{
if ((to->thread.arch.fs == 0) || (to->mm == NULL))
return;
diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c
index 76544403181..f4f82beb350 100644
--- a/arch/um/sys-x86_64/sysrq.c
+++ b/arch/um/sys-x86_64/sysrq.c
@@ -4,32 +4,33 @@
* Licensed under the GPL
*/
-#include "linux/kernel.h"
-#include "linux/utsname.h"
-#include "linux/module.h"
-#include "asm/current.h"
-#include "asm/ptrace.h"
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/utsname.h>
+#include <asm/current.h>
+#include <asm/ptrace.h>
#include "sysrq.h"
-void __show_regs(struct pt_regs * regs)
+void __show_regs(struct pt_regs *regs)
{
printk("\n");
print_modules();
- printk("Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
+ printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
current->comm, print_tainted(), init_utsname()->release);
- printk("RIP: %04lx:[<%016lx>] ", PT_REGS_CS(regs) & 0xffff,
+ printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
PT_REGS_RIP(regs));
- printk("\nRSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs),
+ printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs),
PT_REGS_EFLAGS(regs));
- printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
+ printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
- printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
+ printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
- printk("RBP: %016lx R08: %016lx R09: %016lx\n",
+ printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
- printk("R10: %016lx R11: %016lx R12: %016lx\n",
+ printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
- printk("R13: %016lx R14: %016lx R15: %016lx\n",
+ printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
}
diff --git a/arch/um/sys-x86_64/um_module.c b/arch/um/sys-x86_64/um_module.c
index 8b8eff1bd97..3dead392a41 100644
--- a/arch/um/sys-x86_64/um_module.c
+++ b/arch/um/sys-x86_64/um_module.c
@@ -1,7 +1,7 @@
#include <linux/vmalloc.h>
#include <linux/moduleloader.h>
-/*Copied from i386 arch/i386/kernel/module.c */
+/* Copied from i386 arch/i386/kernel/module.c */
void *module_alloc(unsigned long size)
{
if (size == 0)
@@ -13,7 +13,9 @@ void *module_alloc(unsigned long size)
void module_free(struct module *mod, void *module_region)
{
vfree(module_region);
- /* FIXME: If module_region == mod->init_region, trim exception
- table entries. */
+ /*
+ * FIXME: If module_region == mod->init_region, trim exception
+ * table entries.
+ */
}
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
index ace479ab273..4379f43505e 100644
--- a/arch/v850/Kconfig
+++ b/arch/v850/Kconfig
@@ -53,6 +53,9 @@ config ARCH_HAS_ILOG2_U64
bool
default n
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
# Turn off some random 386 crap that can affect device config
config ISA
bool
@@ -75,6 +78,7 @@ config MCA
config V850
bool
default y
+ select HAVE_IDE
menu "Processor type and features"
@@ -212,6 +216,13 @@ menu "Processor type and features"
bool
default !V850E_CACHE && !V850E2_CACHE
+ # HZ depends on the platform
+ config HZ
+ int
+ default 24 if V850E_SIM || V850E2_SIM85E2
+ default 122 if V850E2_FPGA85E2C
+ default 100
+
#### Misc config
config ROM_KERNEL
diff --git a/arch/v850/kernel/anna.c b/arch/v850/kernel/anna.c
index 0e429041a11..5978a25170f 100644
--- a/arch/v850/kernel/anna.c
+++ b/arch/v850/kernel/anna.c
@@ -85,7 +85,8 @@ void __init mach_reserve_bootmem ()
/* The space between SRAM and SDRAM is filled with duplicate
images of SRAM. Prevent the kernel from using them. */
reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
- SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE));
+ SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE),
+ BOOTMEM_DEFAULT);
}
void mach_gettimeofday (struct timespec *tv)
diff --git a/arch/v850/kernel/as85ep1.c b/arch/v850/kernel/as85ep1.c
index 18437bc5c3a..b525ecf3aea 100644
--- a/arch/v850/kernel/as85ep1.c
+++ b/arch/v850/kernel/as85ep1.c
@@ -116,7 +116,8 @@ void __init mach_reserve_bootmem ()
if (SDRAM_ADDR < RAM_END && SDRAM_ADDR > RAM_START)
/* We can't use the space between SRAM and SDRAM, so
prevent the kernel from trying. */
- reserve_bootmem (SRAM_END, SDRAM_ADDR - SRAM_END);
+ reserve_bootmem(SRAM_END, SDRAM_ADDR - SRAM_END,
+ BOOTMEM_DEFAULT);
}
void mach_gettimeofday (struct timespec *tv)
diff --git a/arch/v850/kernel/procfs.c b/arch/v850/kernel/procfs.c
index e6f9d060ad5..e433cde789b 100644
--- a/arch/v850/kernel/procfs.c
+++ b/arch/v850/kernel/procfs.c
@@ -59,7 +59,7 @@ static void cpuinfo_stop (struct seq_file *m, void *v)
{
}
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
.start = cpuinfo_start,
.next = cpuinfo_next,
.stop = cpuinfo_stop,
diff --git a/arch/v850/kernel/rte_ma1_cb.c b/arch/v850/kernel/rte_ma1_cb.c
index 9a716f94642..08abf3d5f8d 100644
--- a/arch/v850/kernel/rte_ma1_cb.c
+++ b/arch/v850/kernel/rte_ma1_cb.c
@@ -46,13 +46,15 @@ void __init mach_reserve_bootmem ()
{
#ifdef CONFIG_RTE_CB_MULTI
/* Prevent the kernel from touching the monitor's scratch RAM. */
- reserve_bootmem (MON_SCRATCH_ADDR, MON_SCRATCH_SIZE);
+ reserve_bootmem(MON_SCRATCH_ADDR, MON_SCRATCH_SIZE,
+ BOOTMEM_DEFAULT);
#endif
/* The space between SRAM and SDRAM is filled with duplicate
images of SRAM. Prevent the kernel from using them. */
reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
- SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE));
+ SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE),
+ BOOTMEM_DEFAULT);
}
void mach_gettimeofday (struct timespec *tv)
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
index a914f244f49..a0a8456a843 100644
--- a/arch/v850/kernel/setup.c
+++ b/arch/v850/kernel/setup.c
@@ -241,15 +241,18 @@ init_bootmem_alloc (unsigned long ram_start, unsigned long ram_len)
if (kram_end > kram_start)
/* Reserve the RAM part of the kernel's address space, so it
doesn't get allocated. */
- reserve_bootmem (kram_start, kram_end - kram_start);
+ reserve_bootmem(kram_start, kram_end - kram_start,
+ BOOTMEM_DEFAULT);
if (intv_in_ram && !intv_in_kram)
/* Reserve the interrupt vector space. */
- reserve_bootmem (intv_start, intv_end - intv_start);
+ reserve_bootmem(intv_start, intv_end - intv_start,
+ BOOTMEM_DEFAULT);
if (bootmap >= ram_start && bootmap < ram_end)
/* Reserve the bootmap space. */
- reserve_bootmem (bootmap, bootmap_len);
+ reserve_bootmem(bootmap, bootmap_len,
+ BOOTMEM_DEFAULT);
/* Reserve the memory used by the root filesystem image if it's
in RAM. */
@@ -257,7 +260,8 @@ init_bootmem_alloc (unsigned long ram_start, unsigned long ram_len)
&& (unsigned long)&_root_fs_image_start >= ram_start
&& (unsigned long)&_root_fs_image_start < ram_end)
reserve_bootmem ((unsigned long)&_root_fs_image_start,
- &_root_fs_image_end - &_root_fs_image_start);
+ &_root_fs_image_end - &_root_fs_image_start,
+ BOOTMEM_DEFAULT);
/* Let the platform-dependent code reserve some too. */
if (mrb)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 59eef1c7fda..3be2305709b 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -18,8 +18,11 @@ config X86_64
### Arch settings
config X86
def_bool y
+ select HAVE_IDE
select HAVE_OPROFILE
select HAVE_KPROBES
+ select HAVE_KVM
+
config GENERIC_LOCKBREAK
def_bool n
@@ -52,6 +55,10 @@ config HAVE_LATENCYTOP_SUPPORT
config SEMAPHORE_SLEEPERS
def_bool y
+config FAST_CMPXCHG_LOCAL
+ bool
+ default y
+
config MMU
def_bool y
@@ -98,6 +105,9 @@ config ARCH_HAS_ILOG2_U32
config ARCH_HAS_ILOG2_U64
def_bool n
+config ARCH_HAS_CPU_IDLE_WAIT
+ def_bool y
+
config GENERIC_CALIBRATE_DELAY
def_bool y
@@ -105,11 +115,12 @@ config GENERIC_TIME_VSYSCALL
bool
default X86_64
+config ARCH_HAS_CPU_RELAX
+ def_bool y
+
config HAVE_SETUP_PER_CPU_AREA
def_bool X86_64
-select HAVE_KVM
-
config ARCH_HIBERNATION_POSSIBLE
def_bool y
depends on !SMP || !X86_VOYAGER
@@ -129,6 +140,9 @@ config AUDIT_ARCH
bool
default X86_64
+config ARCH_SUPPORTS_AOUT
+ def_bool y
+
# Use the generic interrupt handling code in kernel/irq/:
config GENERIC_HARDIRQS
bool
@@ -415,7 +429,7 @@ config HPET_TIMER
config HPET_EMULATE_RTC
def_bool y
- depends on HPET_TIMER && (RTC=y || RTC=m)
+ depends on HPET_TIMER && (RTC=y || RTC=m || RTC_DRV_CMOS=m || RTC_DRV_CMOS=y)
# Mark as embedded because too many people got it wrong.
# The code disables itself when not needed.
@@ -465,6 +479,9 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT
Calgary anyway, pass 'iommu=calgary' on the kernel command line.
If unsure, say Y.
+config IOMMU_HELPER
+ def_bool (CALGARY_IOMMU || GART_IOMMU)
+
# need this always selected by IOMMU for the VIA workaround
config SWIOTLB
bool
@@ -628,7 +645,6 @@ config TOSHIBA
config I8K
tristate "Dell laptop support"
- depends on X86_32
---help---
This adds a driver to safely access the System Management Mode
of the CPU on the Dell Inspiron 8000. The System Management Mode
@@ -1568,7 +1584,7 @@ config IA32_EMULATION
config IA32_AOUT
tristate "IA32 a.out support"
- depends on IA32_EMULATION
+ depends on IA32_EMULATION && ARCH_SUPPORTS_AOUT
help
Support old a.out binaries in the 32bit emulation.
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 2e1e3af28c3..864affc9a7b 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -34,13 +34,9 @@ config DEBUG_STACK_USAGE
This option will slow down process creation somewhat.
-comment "Page alloc debug is incompatible with Software Suspend on i386"
- depends on DEBUG_KERNEL && HIBERNATION
- depends on X86_32
-
config DEBUG_PAGEALLOC
bool "Debug page memory allocations"
- depends on DEBUG_KERNEL && X86_32
+ depends on DEBUG_KERNEL
help
Unmap pages from the kernel linear mapping after free_pages().
This results in a large slowdown, but helps to find certain types
@@ -220,9 +216,9 @@ config DEBUG_BOOT_PARAMS
This option will cause struct boot_params to be exported via debugfs.
config CPA_DEBUG
- bool "CPA self test code"
+ bool "CPA self-test code"
depends on DEBUG_KERNEL
help
- Do change_page_attr self tests at boot.
+ Do change_page_attr() self-tests every 30 seconds.
endmenu
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 364865b1b08..204af43535c 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -191,8 +191,10 @@ drivers-$(CONFIG_PCI) += arch/x86/pci/
# must be linked after kernel/
drivers-$(CONFIG_OPROFILE) += arch/x86/oprofile/
-ifeq ($(CONFIG_X86_32),y)
+# suspend and hibernation support
drivers-$(CONFIG_PM) += arch/x86/power/
+
+ifeq ($(CONFIG_X86_32),y)
drivers-$(CONFIG_FB) += arch/x86/video/
endif
diff --git a/arch/x86/boot/.gitignore b/arch/x86/boot/.gitignore
index 18465143cfa..b1bdc4c6f9f 100644
--- a/arch/x86/boot/.gitignore
+++ b/arch/x86/boot/.gitignore
@@ -3,3 +3,5 @@ bzImage
setup
setup.bin
setup.elf
+cpustr.h
+mkcpustr
diff --git a/arch/x86/boot/printf.c b/arch/x86/boot/printf.c
index 1a09f9309d3..7e7e890699b 100644
--- a/arch/x86/boot/printf.c
+++ b/arch/x86/boot/printf.c
@@ -33,8 +33,8 @@ static int skip_atoi(const char **s)
#define PLUS 4 /* show plus */
#define SPACE 8 /* space if plus */
#define LEFT 16 /* left justified */
-#define SPECIAL 32 /* 0x */
-#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+#define SMALL 32 /* Must be 32 == 0x20 */
+#define SPECIAL 64 /* 0x */
#define do_div(n,base) ({ \
int __res; \
@@ -45,12 +45,16 @@ __res; })
static char *number(char *str, long num, int base, int size, int precision,
int type)
{
- char c, sign, tmp[66];
- const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+ /* we are called with base 8, 10 or 16, only, thus don't need "G..." */
+ static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
+
+ char tmp[66];
+ char c, sign, locase;
int i;
- if (type & LARGE)
- digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ /* locase = 0 or 0x20. ORing digits or letters with 'locase'
+ * produces same digits or (maybe lowercased) letters */
+ locase = (type & SMALL);
if (type & LEFT)
type &= ~ZEROPAD;
if (base < 2 || base > 36)
@@ -81,7 +85,7 @@ static char *number(char *str, long num, int base, int size, int precision,
tmp[i++] = '0';
else
while (num != 0)
- tmp[i++] = digits[do_div(num, base)];
+ tmp[i++] = (digits[do_div(num, base)] | locase);
if (i > precision)
precision = i;
size -= precision;
@@ -95,7 +99,7 @@ static char *number(char *str, long num, int base, int size, int precision,
*str++ = '0';
else if (base == 16) {
*str++ = '0';
- *str++ = digits[33];
+ *str++ = ('X' | locase);
}
}
if (!(type & LEFT))
@@ -244,9 +248,9 @@ int vsprintf(char *buf, const char *fmt, va_list args)
base = 8;
break;
- case 'X':
- flags |= LARGE;
case 'x':
+ flags |= SMALL;
+ case 'X':
base = 16;
break;
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index 77562e7cdab..3df340b54e5 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -1421,7 +1421,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_FRAME_POINTER is not set
-# CONFIG_FORCED_INLINING is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index 9e2b0ef851d..eef98cb00c6 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -1346,7 +1346,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_FRAME_POINTER is not set
-# CONFIG_FORCED_INLINING is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index e4c12079171..58cccb6483b 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -172,8 +172,7 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,
has_dumped = 1;
current->flags |= PF_DUMPCORE;
strncpy(dump.u_comm, current->comm, sizeof(current->comm));
- dump.u_ar0 = (u32)(((unsigned long)(&dump.regs)) -
- ((unsigned long)(&dump)));
+ dump.u_ar0 = offsetof(struct user32, regs);
dump.signal = signr;
dump_thread32(regs, &dump);
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 0db0a6291bb..8022d3c695c 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -722,7 +722,9 @@ ia32_sys_call_table:
.quad sys_epoll_pwait
.quad compat_sys_utimensat /* 320 */
.quad compat_sys_signalfd
- .quad compat_sys_timerfd
+ .quad sys_timerfd_create
.quad sys_eventfd
.quad sys32_fallocate
+ .quad compat_sys_timerfd_settime /* 325 */
+ .quad compat_sys_timerfd_gettime
ia32_syscall_end:
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 21dc1a061bf..76ec0f8f138 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -84,8 +84,6 @@ ifeq ($(CONFIG_X86_64),y)
obj-y += genapic_64.o genapic_flat_64.o
obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
obj-$(CONFIG_AUDIT) += audit_64.o
- obj-$(CONFIG_PM) += suspend_64.o
- obj-$(CONFIG_HIBERNATION) += suspend_asm_64.o
obj-$(CONFIG_GART_IOMMU) += pci-gart_64.o aperture_64.o
obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index d2a58431a07..680b7300a48 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -78,7 +78,6 @@ int acpi_ht __initdata = 1; /* enable HT */
int acpi_lapic;
int acpi_ioapic;
int acpi_strict;
-EXPORT_SYMBOL(acpi_strict);
u8 acpi_sci_flags __initdata;
int acpi_sci_override_gsi __initdata;
@@ -106,7 +105,7 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
#ifdef CONFIG_X86_64
/* rely on all ACPI tables being in the direct mapping */
-char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
+char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
{
if (!phys_addr || !size)
return NULL;
@@ -131,7 +130,7 @@ char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
* from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and
* count idx down while incrementing the phys address.
*/
-char *__acpi_map_table(unsigned long phys, unsigned long size)
+char *__init __acpi_map_table(unsigned long phys, unsigned long size)
{
unsigned long base, offset, mapped_size;
int idx;
@@ -490,8 +489,6 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity)
return irq;
}
-EXPORT_SYMBOL(acpi_register_gsi);
-
/*
* ACPI based hotplug support for CPU
*/
@@ -587,25 +584,6 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
EXPORT_SYMBOL(acpi_unregister_ioapic);
-static unsigned long __init
-acpi_scan_rsdp(unsigned long start, unsigned long length)
-{
- unsigned long offset = 0;
- unsigned long sig_len = sizeof("RSD PTR ") - 1;
-
- /*
- * Scan all 16-byte boundaries of the physical memory region for the
- * RSDP signature.
- */
- for (offset = 0; offset < length; offset += 16) {
- if (strncmp((char *)(phys_to_virt(start) + offset), "RSD PTR ", sig_len))
- continue;
- return (start + offset);
- }
-
- return 0;
-}
-
static int __init acpi_parse_sbf(struct acpi_table_header *table)
{
struct acpi_table_boot *sb;
@@ -748,27 +726,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
return 0;
}
-unsigned long __init acpi_find_rsdp(void)
-{
- unsigned long rsdp_phys = 0;
-
- if (efi_enabled) {
- if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
- return efi.acpi20;
- else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
- return efi.acpi;
- }
- /*
- * Scan memory looking for the RSDP signature. First search EBDA (low
- * memory) paragraphs and then search upper memory (E0000-FFFFF).
- */
- rsdp_phys = acpi_scan_rsdp(0, 0x400);
- if (!rsdp_phys)
- rsdp_phys = acpi_scan_rsdp(0xE0000, 0x20000);
-
- return rsdp_phys;
-}
-
#ifdef CONFIG_X86_LOCAL_APIC
/*
* Parse LAPIC entries in MADT
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index 10b67170b13..8ca3557a6d5 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -126,6 +126,8 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d "
"state\n", cx->type);
}
+ snprintf(cx->desc, ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
+ cx->address);
out:
set_cpus_allowed(current, saved_mask);
diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c
index a25db514c71..324eb0cab19 100644
--- a/arch/x86/kernel/acpi/processor.c
+++ b/arch/x86/kernel/acpi/processor.c
@@ -46,6 +46,12 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
buf[1] = 1;
buf[2] = ACPI_PDC_C_CAPABILITY_SMP;
+ /*
+ * The default of PDC_SMP_T_SWCOORD bit is set for intel x86 cpu so
+ * that OSPM is capable of native ACPI throttling software
+ * coordination using BIOS supplied _TSD info.
+ */
+ buf[2] |= ACPI_PDC_SMP_T_SWCOORD;
if (cpu_has(c, X86_FEATURE_EST))
buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index d9313d9adce..f86a3c4a266 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -637,7 +637,7 @@ void __init early_cpu_init(void)
}
/* Make sure %fs is initialized properly in idle threads */
-struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
+struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
{
memset(regs, 0, sizeof(struct pt_regs));
regs->fs = __KERNEL_PERCPU;
diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig b/arch/x86/kernel/cpu/cpufreq/Kconfig
index 151eda0a23f..cb7a5715596 100644
--- a/arch/x86/kernel/cpu/cpufreq/Kconfig
+++ b/arch/x86/kernel/cpu/cpufreq/Kconfig
@@ -29,7 +29,7 @@ config X86_ACPI_CPUFREQ
config ELAN_CPUFREQ
tristate "AMD Elan SC400 and SC410"
select CPU_FREQ_TABLE
- depends on X86_32 && X86_ELAN
+ depends on X86_ELAN
---help---
This adds the CPUFreq driver for AMD Elan SC400 and SC410
processors.
@@ -45,7 +45,7 @@ config ELAN_CPUFREQ
config SC520_CPUFREQ
tristate "AMD Elan SC520"
select CPU_FREQ_TABLE
- depends on X86_32 && X86_ELAN
+ depends on X86_ELAN
---help---
This adds the CPUFreq driver for AMD Elan SC520 processor.
diff --git a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
index 326a4c81f68..39f8cb18296 100644
--- a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
+++ b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
@@ -23,6 +23,7 @@
#define EPS_BRAND_C7 1
#define EPS_BRAND_EDEN 2
#define EPS_BRAND_C3 3
+#define EPS_BRAND_C7D 4
struct eps_cpu_data {
u32 fsb;
@@ -54,6 +55,7 @@ static int eps_set_state(struct eps_cpu_data *centaur,
{
struct cpufreq_freqs freqs;
u32 lo, hi;
+ u8 current_multiplier, current_voltage;
int err = 0;
int i;
@@ -93,6 +95,15 @@ postchange:
rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
freqs.new = centaur->fsb * ((lo >> 8) & 0xff);
+ /* Print voltage and multiplier */
+ rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+ current_voltage = lo & 0xff;
+ printk(KERN_INFO "eps: Current voltage = %dmV\n",
+ current_voltage * 16 + 700);
+ current_multiplier = (lo >> 8) & 0xff;
+ printk(KERN_INFO "eps: Current multiplier = %d\n",
+ current_multiplier);
+
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return err;
}
@@ -141,9 +152,10 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
u8 current_multiplier, current_voltage;
u8 max_multiplier, max_voltage;
u8 min_multiplier, min_voltage;
- u8 brand;
+ u8 brand = 0;
u32 fsb;
struct eps_cpu_data *centaur;
+ struct cpuinfo_x86 *c = &cpu_data(0);
struct cpufreq_frequency_table *f_table;
int k, step, voltage;
int ret;
@@ -153,21 +165,36 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
return -ENODEV;
/* Check brand */
- printk("eps: Detected VIA ");
- rdmsr(0x1153, lo, hi);
- brand = (((lo >> 2) ^ lo) >> 18) & 3;
+ printk(KERN_INFO "eps: Detected VIA ");
+
+ switch (c->x86_model) {
+ case 10:
+ rdmsr(0x1153, lo, hi);
+ brand = (((lo >> 2) ^ lo) >> 18) & 3;
+ printk(KERN_CONT "Model A ");
+ break;
+ case 13:
+ rdmsr(0x1154, lo, hi);
+ brand = (((lo >> 4) ^ (lo >> 2))) & 0x000000ff;
+ printk(KERN_CONT "Model D ");
+ break;
+ }
+
switch(brand) {
case EPS_BRAND_C7M:
- printk("C7-M\n");
+ printk(KERN_CONT "C7-M\n");
break;
case EPS_BRAND_C7:
- printk("C7\n");
+ printk(KERN_CONT "C7\n");
break;
case EPS_BRAND_EDEN:
- printk("Eden\n");
+ printk(KERN_CONT "Eden\n");
+ break;
+ case EPS_BRAND_C7D:
+ printk(KERN_CONT "C7-D\n");
break;
case EPS_BRAND_C3:
- printk("C3\n");
+ printk(KERN_CONT "C3\n");
return -ENODEV;
break;
}
@@ -179,7 +206,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
/* Can be locked at 0 */
rdmsrl(MSR_IA32_MISC_ENABLE, val);
if (!(val & 1 << 16)) {
- printk("eps: Can't enable Enhanced PowerSaver\n");
+ printk(KERN_INFO "eps: Can't enable Enhanced PowerSaver\n");
return -ENODEV;
}
}
@@ -187,19 +214,19 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
/* Print voltage and multiplier */
rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
current_voltage = lo & 0xff;
- printk("eps: Current voltage = %dmV\n", current_voltage * 16 + 700);
+ printk(KERN_INFO "eps: Current voltage = %dmV\n", current_voltage * 16 + 700);
current_multiplier = (lo >> 8) & 0xff;
- printk("eps: Current multiplier = %d\n", current_multiplier);
+ printk(KERN_INFO "eps: Current multiplier = %d\n", current_multiplier);
/* Print limits */
max_voltage = hi & 0xff;
- printk("eps: Highest voltage = %dmV\n", max_voltage * 16 + 700);
+ printk(KERN_INFO "eps: Highest voltage = %dmV\n", max_voltage * 16 + 700);
max_multiplier = (hi >> 8) & 0xff;
- printk("eps: Highest multiplier = %d\n", max_multiplier);
+ printk(KERN_INFO "eps: Highest multiplier = %d\n", max_multiplier);
min_voltage = (hi >> 16) & 0xff;
- printk("eps: Lowest voltage = %dmV\n", min_voltage * 16 + 700);
+ printk(KERN_INFO "eps: Lowest voltage = %dmV\n", min_voltage * 16 + 700);
min_multiplier = (hi >> 24) & 0xff;
- printk("eps: Lowest multiplier = %d\n", min_multiplier);
+ printk(KERN_INFO "eps: Lowest multiplier = %d\n", min_multiplier);
/* Sanity checks */
if (current_multiplier == 0 || max_multiplier == 0
@@ -208,7 +235,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
if (current_multiplier > max_multiplier
|| max_multiplier <= min_multiplier)
return -EINVAL;
- if (current_voltage > 0x1c || max_voltage > 0x1c)
+ if (current_voltage > 0x1f || max_voltage > 0x1f)
return -EINVAL;
if (max_voltage < min_voltage)
return -EINVAL;
@@ -310,7 +337,7 @@ static int __init eps_init(void)
/* This driver will work only on Centaur C7 processors with
* Enhanced SpeedStep/PowerSaver registers */
if (c->x86_vendor != X86_VENDOR_CENTAUR
- || c->x86 != 6 || c->x86_model != 10)
+ || c->x86 != 6 || c->x86_model < 10)
return -ENODEV;
if (!cpu_has(c, X86_FEATURE_EST))
return -ENODEV;
diff --git a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c
index 2ed7db2fd25..9d9eae82e60 100644
--- a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c
+++ b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c
@@ -181,8 +181,8 @@ static __init struct pci_dev *gx_detect_chipset(void)
struct pci_dev *gx_pci = NULL;
/* check if CPU is a MediaGX or a Geode. */
- if ((current_cpu_data.x86_vendor != X86_VENDOR_NSC) &&
- (current_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) {
+ if ((boot_cpu_data.x86_vendor != X86_VENDOR_NSC) &&
+ (boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) {
dprintk("error: no MediaGX/Geode processor found!\n");
return NULL;
}
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
index b5a9863d6cd..0a61159d7b7 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
@@ -460,7 +460,7 @@ static int powernow_decode_bios (int maxfid, int startvid)
latency = psb->settlingtime;
if (latency < 100) {
- printk (KERN_INFO PFX "BIOS set settling time to %d microseconds."
+ printk(KERN_INFO PFX "BIOS set settling time to %d microseconds. "
"Should be at least 100. Correcting.\n", latency);
latency = 100;
}
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index a0522735dd9..c99d59d8ef2 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -578,10 +578,9 @@ static void print_basics(struct powernow_k8_data *data)
for (j = 0; j < data->numps; j++) {
if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) {
if (cpu_family == CPU_HW_PSTATE) {
- printk(KERN_INFO PFX " %d : fid 0x%x did 0x%x (%d MHz)\n",
+ printk(KERN_INFO PFX " %d : pstate %d (%d MHz)\n",
j,
- (data->powernow_table[j].index & 0xff00) >> 8,
- (data->powernow_table[j].index & 0xff0000) >> 16,
+ data->powernow_table[j].index,
data->powernow_table[j].frequency/1000);
} else {
printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n",
@@ -827,7 +826,6 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpuf
for (i = 0; i < data->acpi_data.state_count; i++) {
u32 index;
- u32 hi = 0, lo = 0;
index = data->acpi_data.states[i].control & HW_PSTATE_MASK;
if (index > data->max_hw_pstate) {
@@ -1236,8 +1234,10 @@ static unsigned int powernowk8_get (unsigned int cpu)
struct powernow_k8_data *data;
cpumask_t oldmask = current->cpus_allowed;
unsigned int khz = 0;
+ unsigned int first;
- data = per_cpu(powernow_data, first_cpu(per_cpu(cpu_core_map, cpu)));
+ first = first_cpu(per_cpu(cpu_core_map, cpu));
+ data = per_cpu(powernow_data, first);
if (!data)
return -EINVAL;
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
index afd2b520d35..ab48cfed4d9 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
@@ -47,7 +47,7 @@ struct powernow_k8_data {
#define CPUID_XFAM 0x0ff00000 /* extended family */
#define CPUID_XFAM_K8 0
#define CPUID_XMOD 0x000f0000 /* extended model */
-#define CPUID_XMOD_REV_MASK 0x00080000
+#define CPUID_XMOD_REV_MASK 0x000c0000
#define CPUID_XFAM_10H 0x00100000 /* family 0x10 */
#define CPUID_USE_XFAM_XMOD 0x00000f00
#define CPUID_GET_MAX_CAPABILITIES 0x80000000
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
index 76c3ab0da46..98d4fdb7dc0 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
@@ -189,10 +189,7 @@ static unsigned int pentium4_get_frequency(void)
printk(KERN_DEBUG "speedstep-lib: couldn't detect FSB speed. Please send an e-mail to <linux@brodo.de>\n");
/* Multiplier. */
- if (c->x86_model < 2)
- mult = msr_lo >> 27;
- else
- mult = msr_lo >> 24;
+ mult = msr_lo >> 24;
dprintk("P4 - FSB %u kHz; Multiplier %u; Speed %u kHz\n", fsb, mult, (fsb * mult));
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c
index 404a6a2d401..7139b026270 100644
--- a/arch/x86/kernel/cpu/cyrix.c
+++ b/arch/x86/kernel/cpu/cyrix.c
@@ -83,8 +83,6 @@ static char cyrix_model_mult2[] __cpuinitdata = "12233445";
* FIXME: our newer udelay uses the tsc. We don't need to frob with SLOP
*/
-extern void calibrate_delay(void) __init;
-
static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c)
{
unsigned long flags;
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 24885be5c48..9b7e01daa1c 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -118,7 +118,7 @@ static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev)
static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev)
{
- return sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
+ sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
}
/* Mutex protecting device creation against CPU hotplug */
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index 1e27b69a7a0..b6e136f23d3 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -659,7 +659,7 @@ static __init int amd_special_default_mtrr(void)
*/
int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
{
- unsigned long i, base, size, highest_addr = 0, def, dummy;
+ unsigned long i, base, size, highest_pfn = 0, def, dummy;
mtrr_type type;
u64 trim_start, trim_size;
@@ -682,28 +682,27 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
mtrr_if->get(i, &base, &size, &type);
if (type != MTRR_TYPE_WRBACK)
continue;
- base <<= PAGE_SHIFT;
- size <<= PAGE_SHIFT;
- if (highest_addr < base + size)
- highest_addr = base + size;
+ if (highest_pfn < base + size)
+ highest_pfn = base + size;
}
/* kvm/qemu doesn't have mtrr set right, don't trim them all */
- if (!highest_addr) {
+ if (!highest_pfn) {
printk(KERN_WARNING "WARNING: strange, CPU MTRRs all blank?\n");
WARN_ON(1);
return 0;
}
- if ((highest_addr >> PAGE_SHIFT) < end_pfn) {
+ if (highest_pfn < end_pfn) {
printk(KERN_WARNING "WARNING: BIOS bug: CPU MTRRs don't cover"
- " all of memory, losing %LdMB of RAM.\n",
- (((u64)end_pfn << PAGE_SHIFT) - highest_addr) >> 20);
+ " all of memory, losing %luMB of RAM.\n",
+ (end_pfn - highest_pfn) >> (20 - PAGE_SHIFT));
WARN_ON(1);
printk(KERN_INFO "update e820 for mtrr\n");
- trim_start = highest_addr;
+ trim_start = highest_pfn;
+ trim_start <<= PAGE_SHIFT;
trim_size = end_pfn;
trim_size <<= PAGE_SHIFT;
trim_size -= trim_start;
diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c
index 32dd62b36ff..0c0eeb163d9 100644
--- a/arch/x86/kernel/efi.c
+++ b/arch/x86/kernel/efi.c
@@ -384,9 +384,6 @@ static void __init runtime_code_page_mkexec(void)
efi_memory_desc_t *md;
void *p;
- if (!(__supported_pte_mask & _PAGE_NX))
- return;
-
/* Make EFI runtime service code area executable */
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
md = p;
@@ -394,7 +391,7 @@ static void __init runtime_code_page_mkexec(void)
if (md->type != EFI_RUNTIME_SERVICES_CODE)
continue;
- set_memory_x(md->virt_addr, md->num_pages << EFI_PAGE_SHIFT);
+ set_memory_x(md->virt_addr, md->num_pages);
}
}
@@ -428,9 +425,6 @@ void __init efi_enter_virtual_mode(void)
else
va = efi_ioremap(md->phys_addr, size);
- if (md->attribute & EFI_MEMORY_WB)
- set_memory_uc(md->virt_addr, size);
-
md->virt_addr = (u64) (unsigned long) va;
if (!va) {
@@ -439,6 +433,9 @@ void __init efi_enter_virtual_mode(void)
continue;
}
+ if (!(md->attribute & EFI_MEMORY_WB))
+ set_memory_uc(md->virt_addr, md->num_pages);
+
systab = (u64) (unsigned long) efi_phys.systab;
if (md->phys_addr <= systab && systab < end) {
systab += md->virt_addr - md->phys_addr;
@@ -476,7 +473,8 @@ void __init efi_enter_virtual_mode(void)
efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
efi.reset_system = virt_efi_reset_system;
efi.set_virtual_address_map = virt_efi_set_virtual_address_map;
- runtime_code_page_mkexec();
+ if (__supported_pte_mask & _PAGE_NX)
+ runtime_code_page_mkexec();
early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
memmap.map = NULL;
}
diff --git a/arch/x86/kernel/efi_64.c b/arch/x86/kernel/efi_64.c
index 09d5c233093..d143a1e76b3 100644
--- a/arch/x86/kernel/efi_64.c
+++ b/arch/x86/kernel/efi_64.c
@@ -35,6 +35,7 @@
#include <asm/tlbflush.h>
#include <asm/proto.h>
#include <asm/efi.h>
+#include <asm/cacheflush.h>
static pgd_t save_pgd __initdata;
static unsigned long efi_flags __initdata;
@@ -43,22 +44,15 @@ static void __init early_mapping_set_exec(unsigned long start,
unsigned long end,
int executable)
{
- pte_t *kpte;
- unsigned int level;
-
- while (start < end) {
- kpte = lookup_address((unsigned long)__va(start), &level);
- BUG_ON(!kpte);
- if (executable)
- set_pte(kpte, pte_mkexec(*kpte));
- else
- set_pte(kpte, __pte((pte_val(*kpte) | _PAGE_NX) & \
- __supported_pte_mask));
- if (level == PG_LEVEL_4K)
- start = (start + PAGE_SIZE) & PAGE_MASK;
- else
- start = (start + PMD_SIZE) & PMD_MASK;
- }
+ unsigned long num_pages;
+
+ start &= PMD_MASK;
+ end = (end + PMD_SIZE - 1) & PMD_MASK;
+ num_pages = (end - start) >> PAGE_SHIFT;
+ if (executable)
+ set_memory_x((unsigned long)__va(start), num_pages);
+ else
+ set_memory_nx((unsigned long)__va(start), num_pages);
}
static void __init early_runtime_code_mapping_set_exec(int executable)
@@ -74,7 +68,7 @@ static void __init early_runtime_code_mapping_set_exec(int executable)
md = p;
if (md->type == EFI_RUNTIME_SERVICES_CODE) {
unsigned long end;
- end = md->phys_addr + (md->num_pages << PAGE_SHIFT);
+ end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
early_mapping_set_exec(md->phys_addr, end, executable);
}
}
@@ -84,8 +78,8 @@ void __init efi_call_phys_prelog(void)
{
unsigned long vaddress;
- local_irq_save(efi_flags);
early_runtime_code_mapping_set_exec(1);
+ local_irq_save(efi_flags);
vaddress = (unsigned long)__va(0x0UL);
save_pgd = *pgd_offset_k(0x0UL);
set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress));
@@ -98,9 +92,9 @@ void __init efi_call_phys_epilog(void)
* After the lock is released, the original page table is restored.
*/
set_pgd(pgd_offset_k(0x0UL), save_pgd);
- early_runtime_code_mapping_set_exec(0);
__flush_tlb_all();
local_irq_restore(efi_flags);
+ early_runtime_code_mapping_set_exec(0);
}
void __init efi_reserve_bootmem(void)
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index be5c31d0488..824e21b80aa 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -409,7 +409,8 @@ restore_nocheck_notrace:
RESTORE_REGS
addl $4, %esp # skip orig_eax/error_code
CFI_ADJUST_CFA_OFFSET -4
-1: INTERRUPT_RETURN
+ENTRY(irq_return)
+ INTERRUPT_RETURN
.section .fixup,"ax"
iret_exc:
pushl $0 # no error code
@@ -418,7 +419,7 @@ iret_exc:
.previous
.section __ex_table,"a"
.align 4
- .long 1b,iret_exc
+ .long irq_return,iret_exc
.previous
CFI_RESTORE_STATE
@@ -865,20 +866,16 @@ nmi_espfix_stack:
RESTORE_REGS
lss 12+4(%esp), %esp # back to espfix stack
CFI_ADJUST_CFA_OFFSET -24
-1: INTERRUPT_RETURN
+ jmp irq_return
CFI_ENDPROC
-.section __ex_table,"a"
- .align 4
- .long 1b,iret_exc
-.previous
KPROBE_END(nmi)
#ifdef CONFIG_PARAVIRT
ENTRY(native_iret)
-1: iret
+ iret
.section __ex_table,"a"
.align 4
- .long 1b,iret_exc
+ .long native_iret, iret_exc
.previous
END(native_iret)
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index bea8474744f..6be39a387c5 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -581,25 +581,41 @@ retint_restore_args: /* return to kernel space */
*/
TRACE_IRQS_IRETQ
restore_args:
- RESTORE_ARGS 0,8,0
-iret_label:
-#ifdef CONFIG_PARAVIRT
+ RESTORE_ARGS 0,8,0
+
+ENTRY(irq_return)
INTERRUPT_RETURN
-#endif
+
+ .section __ex_table, "a"
+ .quad irq_return, bad_iret
+ .previous
+
+#ifdef CONFIG_PARAVIRT
ENTRY(native_iret)
iretq
.section __ex_table,"a"
.quad native_iret, bad_iret
.previous
+#endif
+
.section .fixup,"ax"
- /* force a signal here? this matches i386 behaviour */
- /* running with kernel gs */
bad_iret:
- movq $11,%rdi /* SIGSEGV */
- TRACE_IRQS_ON
- ENABLE_INTERRUPTS(CLBR_ANY | ~(CLBR_RDI))
- jmp do_exit
+ /*
+ * The iret traps when the %cs or %ss being restored is bogus.
+ * We've lost the original trap vector and error code.
+ * #GPF is the most likely one to get for an invalid selector.
+ * So pretend we completed the iret and took the #GPF in user mode.
+ *
+ * We are now running with the kernel GS after exception recovery.
+ * But error_entry expects us to have user GS to match the user %cs,
+ * so swap back.
+ */
+ pushq $0
+
+ SWAPGS
+ jmp general_protection
+
.previous
/* edi: workmask, edx: work */
@@ -796,7 +812,7 @@ paranoid_swapgs\trace:
SWAPGS_UNSAFE_STACK
paranoid_restore\trace:
RESTORE_ALL 8
- INTERRUPT_RETURN
+ jmp irq_return
paranoid_userspace\trace:
GET_THREAD_INFO(%rcx)
movl threadinfo_flags(%rcx),%ebx
@@ -911,7 +927,7 @@ error_kernelspace:
iret run with kernel gs again, so don't set the user space flag.
B stepping K8s sometimes report an truncated RIP for IRET
exceptions returning to compat mode. Check for these here too. */
- leaq iret_label(%rip),%rbp
+ leaq irq_return(%rip),%rbp
cmpq %rbp,RIP(%rsp)
je error_swapgs
movl %ebp,%ebp /* zero extend */
diff --git a/arch/x86/kernel/geode_32.c b/arch/x86/kernel/geode_32.c
index 9c7f7d39596..9dad6ca6cd7 100644
--- a/arch/x86/kernel/geode_32.c
+++ b/arch/x86/kernel/geode_32.c
@@ -163,14 +163,11 @@ EXPORT_SYMBOL_GPL(geode_gpio_setup_event);
static int __init geode_southbridge_init(void)
{
- int timers;
-
if (!is_geode())
return -ENODEV;
init_lbars();
- timers = geode_mfgpt_detect();
- printk(KERN_INFO "geode: %d MFGPT timers available.\n", timers);
+ (void) mfgpt_timer_setup();
return 0;
}
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 5d8c5730686..74ef4a41f22 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -19,6 +19,10 @@
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
#include <asm/setup.h>
+#include <asm/processor-flags.h>
+
+/* Physical address */
+#define pa(X) ((X) - __PAGE_OFFSET)
/*
* References to members of the new_cpu_data structure.
@@ -80,10 +84,6 @@ INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_
*/
.section .text.head,"ax",@progbits
ENTRY(startup_32)
- /* check to see if KEEP_SEGMENTS flag is meaningful */
- cmpw $0x207, BP_version(%esi)
- jb 1f
-
/* test KEEP_SEGMENTS flag to see if the bootloader is asking
us to not reload segments */
testb $(1<<6), BP_loadflags(%esi)
@@ -92,7 +92,7 @@ ENTRY(startup_32)
/*
* Set segments to known values.
*/
-1: lgdt boot_gdt_descr - __PAGE_OFFSET
+ lgdt pa(boot_gdt_descr)
movl $(__BOOT_DS),%eax
movl %eax,%ds
movl %eax,%es
@@ -105,8 +105,8 @@ ENTRY(startup_32)
*/
cld
xorl %eax,%eax
- movl $__bss_start - __PAGE_OFFSET,%edi
- movl $__bss_stop - __PAGE_OFFSET,%ecx
+ movl $pa(__bss_start),%edi
+ movl $pa(__bss_stop),%ecx
subl %edi,%ecx
shrl $2,%ecx
rep ; stosl
@@ -118,31 +118,32 @@ ENTRY(startup_32)
* (kexec on panic case). Hence copy out the parameters before initializing
* page tables.
*/
- movl $(boot_params - __PAGE_OFFSET),%edi
+ movl $pa(boot_params),%edi
movl $(PARAM_SIZE/4),%ecx
cld
rep
movsl
- movl boot_params - __PAGE_OFFSET + NEW_CL_POINTER,%esi
+ movl pa(boot_params) + NEW_CL_POINTER,%esi
andl %esi,%esi
jz 1f # No comand line
- movl $(boot_command_line - __PAGE_OFFSET),%edi
+ movl $pa(boot_command_line),%edi
movl $(COMMAND_LINE_SIZE/4),%ecx
rep
movsl
1:
#ifdef CONFIG_PARAVIRT
- cmpw $0x207, (boot_params + BP_version - __PAGE_OFFSET)
+ /* This is can only trip for a broken bootloader... */
+ cmpw $0x207, pa(boot_params + BP_version)
jb default_entry
/* Paravirt-compatible boot parameters. Look to see what architecture
we're booting under. */
- movl (boot_params + BP_hardware_subarch - __PAGE_OFFSET), %eax
+ movl pa(boot_params + BP_hardware_subarch), %eax
cmpl $num_subarch_entries, %eax
jae bad_subarch
- movl subarch_entries - __PAGE_OFFSET(,%eax,4), %eax
+ movl pa(subarch_entries)(,%eax,4), %eax
subl $__PAGE_OFFSET, %eax
jmp *%eax
@@ -170,17 +171,68 @@ num_subarch_entries = (. - subarch_entries) / 4
* Mappings are created both at virtual address 0 (identity mapping)
* and PAGE_OFFSET for up to _end+sizeof(page tables)+INIT_MAP_BEYOND_END.
*
- * Warning: don't use %esi or the stack in this code. However, %esp
- * can be used as a GPR if you really need it...
+ * Note that the stack is not yet set up!
*/
-page_pde_offset = (__PAGE_OFFSET >> 20);
+#define PTE_ATTR 0x007 /* PRESENT+RW+USER */
+#define PDE_ATTR 0x067 /* PRESENT+RW+USER+DIRTY+ACCESSED */
+#define PGD_ATTR 0x001 /* PRESENT (no other attributes) */
default_entry:
- movl $(pg0 - __PAGE_OFFSET), %edi
- movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
- movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */
+#ifdef CONFIG_X86_PAE
+
+ /*
+ * In PAE mode swapper_pg_dir is statically defined to contain enough
+ * entries to cover the VMSPLIT option (that is the top 1, 2 or 3
+ * entries). The identity mapping is handled by pointing two PGD
+ * entries to the first kernel PMD.
+ *
+ * Note the upper half of each PMD or PTE are always zero at
+ * this stage.
+ */
+
+#define KPMDS ((0x100000000-__PAGE_OFFSET) >> 30) /* Number of kernel PMDs */
+
+ xorl %ebx,%ebx /* %ebx is kept at zero */
+
+ movl $pa(pg0), %edi
+ movl $pa(swapper_pg_pmd), %edx
+ movl $PTE_ATTR, %eax
+10:
+ leal PDE_ATTR(%edi),%ecx /* Create PMD entry */
+ movl %ecx,(%edx) /* Store PMD entry */
+ /* Upper half already zero */
+ addl $8,%edx
+ movl $512,%ecx
+11:
+ stosl
+ xchgl %eax,%ebx
+ stosl
+ xchgl %eax,%ebx
+ addl $0x1000,%eax
+ loop 11b
+
+ /*
+ * End condition: we must map up to and including INIT_MAP_BEYOND_END
+ * bytes beyond the end of our own page tables.
+ */
+ leal (INIT_MAP_BEYOND_END+PTE_ATTR)(%edi),%ebp
+ cmpl %ebp,%eax
+ jb 10b
+1:
+ movl %edi,pa(init_pg_tables_end)
+
+ /* Do early initialization of the fixmap area */
+ movl $pa(swapper_pg_fixmap)+PDE_ATTR,%eax
+ movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8)
+#else /* Not PAE */
+
+page_pde_offset = (__PAGE_OFFSET >> 20);
+
+ movl $pa(pg0), %edi
+ movl $pa(swapper_pg_dir), %edx
+ movl $PTE_ATTR, %eax
10:
- leal 0x007(%edi),%ecx /* Create PDE entry */
+ leal PDE_ATTR(%edi),%ecx /* Create PDE entry */
movl %ecx,(%edx) /* Store identity PDE entry */
movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */
addl $4,%edx
@@ -189,19 +241,20 @@ default_entry:
stosl
addl $0x1000,%eax
loop 11b
- /* End condition: we must map up to and including INIT_MAP_BEYOND_END */
- /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */
- leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp
+ /*
+ * End condition: we must map up to and including INIT_MAP_BEYOND_END
+ * bytes beyond the end of our own page tables; the +0x007 is
+ * the attribute bits
+ */
+ leal (INIT_MAP_BEYOND_END+PTE_ATTR)(%edi),%ebp
cmpl %ebp,%eax
jb 10b
- movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
-
- /* Do an early initialization of the fixmap area */
- movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
- movl $(swapper_pg_pmd - __PAGE_OFFSET), %eax
- addl $0x67, %eax /* 0x67 == _PAGE_TABLE */
- movl %eax, 4092(%edx)
+ movl %edi,pa(init_pg_tables_end)
+ /* Do early initialization of the fixmap area */
+ movl $pa(swapper_pg_fixmap)+PDE_ATTR,%eax
+ movl %eax,pa(swapper_pg_dir+0xffc)
+#endif
jmp 3f
/*
* Non-boot CPU entry point; entered from trampoline.S
@@ -241,7 +294,7 @@ ENTRY(startup_32_smp)
* NOTE! We have to correct for the fact that we're
* not yet offset PAGE_OFFSET..
*/
-#define cr4_bits mmu_cr4_features-__PAGE_OFFSET
+#define cr4_bits pa(mmu_cr4_features)
movl cr4_bits,%edx
andl %edx,%edx
jz 6f
@@ -276,10 +329,10 @@ ENTRY(startup_32_smp)
/*
* Enable paging
*/
- movl $swapper_pg_dir-__PAGE_OFFSET,%eax
+ movl $pa(swapper_pg_dir),%eax
movl %eax,%cr3 /* set the page table pointer.. */
movl %cr0,%eax
- orl $0x80000000,%eax
+ orl $X86_CR0_PG,%eax
movl %eax,%cr0 /* ..and set paging (PG) bit */
ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */
1:
@@ -552,16 +605,44 @@ ENTRY(_stext)
*/
.section ".bss.page_aligned","wa"
.align PAGE_SIZE_asm
+#ifdef CONFIG_X86_PAE
+ENTRY(swapper_pg_pmd)
+ .fill 1024*KPMDS,4,0
+#else
ENTRY(swapper_pg_dir)
.fill 1024,4,0
-ENTRY(swapper_pg_pmd)
+#endif
+ENTRY(swapper_pg_fixmap)
.fill 1024,4,0
ENTRY(empty_zero_page)
.fill 4096,1,0
-
/*
* This starts the data section.
*/
+#ifdef CONFIG_X86_PAE
+.section ".data.page_aligned","wa"
+ /* Page-aligned for the benefit of paravirt? */
+ .align PAGE_SIZE_asm
+ENTRY(swapper_pg_dir)
+ .long pa(swapper_pg_pmd+PGD_ATTR),0 /* low identity map */
+# if KPMDS == 3
+ .long pa(swapper_pg_pmd+PGD_ATTR),0
+ .long pa(swapper_pg_pmd+PGD_ATTR+0x1000),0
+ .long pa(swapper_pg_pmd+PGD_ATTR+0x2000),0
+# elif KPMDS == 2
+ .long 0,0
+ .long pa(swapper_pg_pmd+PGD_ATTR),0
+ .long pa(swapper_pg_pmd+PGD_ATTR+0x1000),0
+# elif KPMDS == 1
+ .long 0,0
+ .long 0,0
+ .long pa(swapper_pg_pmd+PGD_ATTR),0
+# else
+# error "Kernel PMDs should be 1, 2 or 3"
+# endif
+ .align PAGE_SIZE_asm /* needs to be page-sized too */
+#endif
+
.data
ENTRY(stack_start)
.long init_thread_union+THREAD_SIZE
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 4f283ad215e..09b38d539b0 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -250,18 +250,13 @@ ENTRY(secondary_startup_64)
lretq
/* SMP bootup changes these two */
-#ifndef CONFIG_HOTPLUG_CPU
- .pushsection .init.data
-#endif
+ __CPUINITDATA
.align 8
- .globl initial_code
-initial_code:
+ ENTRY(initial_code)
.quad x86_64_start_kernel
-#ifndef CONFIG_HOTPLUG_CPU
- .popsection
-#endif
- .globl init_rsp
-init_rsp:
+ __FINITDATA
+
+ ENTRY(init_rsp)
.quad init_thread_union+THREAD_SIZE-8
bad_address:
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c
index ef62b07b2b4..8540abe86ad 100644
--- a/arch/x86/kernel/i8253.c
+++ b/arch/x86/kernel/i8253.c
@@ -95,7 +95,7 @@ static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
* registered. This mechanism replaces the previous #ifdef LOCAL_APIC -
* !using_apic_timer decisions in do_timer_interrupt_hook()
*/
-struct clock_event_device pit_clockevent = {
+static struct clock_event_device pit_clockevent = {
.name = "pit",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_mode = init_pit_timer,
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index c1cfd60639d..d0b234c9fc3 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -151,7 +151,7 @@ NORET_TYPE void machine_kexec(struct kimage *image)
void arch_crash_save_vmcoreinfo(void)
{
-#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
+#ifdef CONFIG_NUMA
VMCOREINFO_SYMBOL(node_data);
VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
#endif
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index a1fef42f8cd..236d2f8f7dd 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -234,5 +234,10 @@ NORET_TYPE void machine_kexec(struct kimage *image)
void arch_crash_save_vmcoreinfo(void)
{
VMCOREINFO_SYMBOL(init_level4_pgt);
+
+#ifdef CONFIG_NUMA
+ VMCOREINFO_SYMBOL(node_data);
+ VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
+#endif
}
diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c
index 219f86eb612..027fc067b39 100644
--- a/arch/x86/kernel/mfgpt_32.c
+++ b/arch/x86/kernel/mfgpt_32.c
@@ -12,48 +12,37 @@
*/
/*
- * We are using the 32Khz input clock - its the only one that has the
+ * We are using the 32.768kHz input clock - it's the only one that has the
* ranges we find desirable. The following table lists the suitable
- * divisors and the associated hz, minimum interval
- * and the maximum interval:
+ * divisors and the associated Hz, minimum interval and the maximum interval:
*
- * Divisor Hz Min Delta (S) Max Delta (S)
- * 1 32000 .0005 2.048
- * 2 16000 .001 4.096
- * 4 8000 .002 8.192
- * 8 4000 .004 16.384
- * 16 2000 .008 32.768
- * 32 1000 .016 65.536
- * 64 500 .032 131.072
- * 128 250 .064 262.144
- * 256 125 .128 524.288
+ * Divisor Hz Min Delta (s) Max Delta (s)
+ * 1 32768 .00048828125 2.000
+ * 2 16384 .0009765625 4.000
+ * 4 8192 .001953125 8.000
+ * 8 4096 .00390625 16.000
+ * 16 2048 .0078125 32.000
+ * 32 1024 .015625 64.000
+ * 64 512 .03125 128.000
+ * 128 256 .0625 256.000
+ * 256 128 .125 512.000
*/
#include <linux/kernel.h>
#include <linux/interrupt.h>
-#include <linux/module.h>
#include <asm/geode.h>
-#define F_AVAIL 0x01
-
static struct mfgpt_timer_t {
- int flags;
- struct module *owner;
+ unsigned int avail:1;
} mfgpt_timers[MFGPT_MAX_TIMERS];
/* Selected from the table above */
#define MFGPT_DIVISOR 16
#define MFGPT_SCALE 4 /* divisor = 2^(scale) */
-#define MFGPT_HZ (32000 / MFGPT_DIVISOR)
+#define MFGPT_HZ (32768 / MFGPT_DIVISOR)
#define MFGPT_PERIODIC (MFGPT_HZ / HZ)
-#ifdef CONFIG_GEODE_MFGPT_TIMER
-static int __init mfgpt_timer_setup(void);
-#else
-#define mfgpt_timer_setup() (0)
-#endif
-
/* Allow for disabling of MFGPTs */
static int disable;
static int __init mfgpt_disable(char *s)
@@ -85,28 +74,37 @@ __setup("mfgptfix", mfgpt_fix);
* In other cases (such as with VSAless OpenFirmware), the system firmware
* leaves timers available for us to use.
*/
-int __init geode_mfgpt_detect(void)
+
+
+static int timers = -1;
+
+static void geode_mfgpt_detect(void)
{
- int count = 0, i;
+ int i;
u16 val;
+ timers = 0;
+
if (disable) {
- printk(KERN_INFO "geode-mfgpt: Skipping MFGPT setup\n");
- return 0;
+ printk(KERN_INFO "geode-mfgpt: MFGPT support is disabled\n");
+ goto done;
+ }
+
+ if (!geode_get_dev_base(GEODE_DEV_MFGPT)) {
+ printk(KERN_INFO "geode-mfgpt: MFGPT LBAR is not set up\n");
+ goto done;
}
for (i = 0; i < MFGPT_MAX_TIMERS; i++) {
val = geode_mfgpt_read(i, MFGPT_REG_SETUP);
if (!(val & MFGPT_SETUP_SETUP)) {
- mfgpt_timers[i].flags = F_AVAIL;
- count++;
+ mfgpt_timers[i].avail = 1;
+ timers++;
}
}
- /* set up clock event device, if desired */
- i = mfgpt_timer_setup();
-
- return count;
+done:
+ printk(KERN_INFO "geode-mfgpt: %d MFGPT timers available.\n", timers);
}
int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable)
@@ -183,36 +181,41 @@ int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable)
return 0;
}
-static int mfgpt_get(int timer, struct module *owner)
+static int mfgpt_get(int timer)
{
- mfgpt_timers[timer].flags &= ~F_AVAIL;
- mfgpt_timers[timer].owner = owner;
+ mfgpt_timers[timer].avail = 0;
printk(KERN_INFO "geode-mfgpt: Registered timer %d\n", timer);
return timer;
}
-int geode_mfgpt_alloc_timer(int timer, int domain, struct module *owner)
+int geode_mfgpt_alloc_timer(int timer, int domain)
{
int i;
- if (!geode_get_dev_base(GEODE_DEV_MFGPT))
- return -ENODEV;
+ if (timers == -1) {
+ /* timers haven't been detected yet */
+ geode_mfgpt_detect();
+ }
+
+ if (!timers)
+ return -1;
+
if (timer >= MFGPT_MAX_TIMERS)
- return -EIO;
+ return -1;
if (timer < 0) {
/* Try to find an available timer */
for (i = 0; i < MFGPT_MAX_TIMERS; i++) {
- if (mfgpt_timers[i].flags & F_AVAIL)
- return mfgpt_get(i, owner);
+ if (mfgpt_timers[i].avail)
+ return mfgpt_get(i);
if (i == 5 && domain == MFGPT_DOMAIN_WORKING)
break;
}
} else {
/* If they requested a specific timer, try to honor that */
- if (mfgpt_timers[timer].flags & F_AVAIL)
- return mfgpt_get(timer, owner);
+ if (mfgpt_timers[timer].avail)
+ return mfgpt_get(timer);
}
/* No timers available - too bad */
@@ -244,10 +247,11 @@ static int __init mfgpt_setup(char *str)
}
__setup("mfgpt_irq=", mfgpt_setup);
-static inline void mfgpt_disable_timer(u16 clock)
+static void mfgpt_disable_timer(u16 clock)
{
- u16 val = geode_mfgpt_read(clock, MFGPT_REG_SETUP);
- geode_mfgpt_write(clock, MFGPT_REG_SETUP, val & ~MFGPT_SETUP_CNTEN);
+ /* avoid races by clearing CMP1 and CMP2 unconditionally */
+ geode_mfgpt_write(clock, MFGPT_REG_SETUP, (u16) ~MFGPT_SETUP_CNTEN |
+ MFGPT_SETUP_CMP1 | MFGPT_SETUP_CMP2);
}
static int mfgpt_next_event(unsigned long, struct clock_event_device *);
@@ -263,7 +267,7 @@ static struct clock_event_device mfgpt_clockevent = {
.shift = 32
};
-static inline void mfgpt_start_timer(u16 clock, u16 delta)
+static void mfgpt_start_timer(u16 delta)
{
geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_CMP2, (u16) delta);
geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_COUNTER, 0);
@@ -278,21 +282,25 @@ static void mfgpt_set_mode(enum clock_event_mode mode,
mfgpt_disable_timer(mfgpt_event_clock);
if (mode == CLOCK_EVT_MODE_PERIODIC)
- mfgpt_start_timer(mfgpt_event_clock, MFGPT_PERIODIC);
+ mfgpt_start_timer(MFGPT_PERIODIC);
mfgpt_tick_mode = mode;
}
static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt)
{
- mfgpt_start_timer(mfgpt_event_clock, delta);
+ mfgpt_start_timer(delta);
return 0;
}
-/* Assume (foolishly?), that this interrupt was due to our tick */
-
static irqreturn_t mfgpt_tick(int irq, void *dev_id)
{
+ u16 val = geode_mfgpt_read(mfgpt_event_clock, MFGPT_REG_SETUP);
+
+ /* See if the interrupt was for us */
+ if (!(val & (MFGPT_SETUP_SETUP | MFGPT_SETUP_CMP2 | MFGPT_SETUP_CMP1)))
+ return IRQ_NONE;
+
/* Turn off the clock (and clear the event) */
mfgpt_disable_timer(mfgpt_event_clock);
@@ -320,13 +328,12 @@ static struct irqaction mfgptirq = {
.name = "mfgpt-timer"
};
-static int __init mfgpt_timer_setup(void)
+int __init mfgpt_timer_setup(void)
{
int timer, ret;
u16 val;
- timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING,
- THIS_MODULE);
+ timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING);
if (timer < 0) {
printk(KERN_ERR
"mfgpt-timer: Could not allocate a MFPGT timer\n");
@@ -363,7 +370,7 @@ static int __init mfgpt_timer_setup(void)
&mfgpt_clockevent);
printk(KERN_INFO
- "mfgpt-timer: registering the MFGT timer as a clock event.\n");
+ "mfgpt-timer: registering the MFGPT timer as a clock event.\n");
clockevents_register_device(&mfgpt_clockevent);
return 0;
diff --git a/arch/x86/kernel/mpparse_32.c b/arch/x86/kernel/mpparse_32.c
index 67009cdd5ec..f349e68e45a 100644
--- a/arch/x86/kernel/mpparse_32.c
+++ b/arch/x86/kernel/mpparse_32.c
@@ -736,7 +736,8 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
smp_found_config = 1;
printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
mpf, virt_to_phys(mpf));
- reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
+ reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE,
+ BOOTMEM_DEFAULT);
if (mpf->mpf_physptr) {
/*
* We cannot access to MPC table to compute
@@ -751,7 +752,8 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
unsigned long end = max_low_pfn * PAGE_SIZE;
if (mpf->mpf_physptr + size > end)
size = end - mpf->mpf_physptr;
- reserve_bootmem(mpf->mpf_physptr, size);
+ reserve_bootmem(mpf->mpf_physptr, size,
+ BOOTMEM_DEFAULT);
}
mpf_found = mpf;
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 1fe7f043ebd..1b5464c2434 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -35,6 +35,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/scatterlist.h>
+#include <linux/iommu-helper.h>
#include <asm/gart.h>
#include <asm/calgary.h>
#include <asm/tce.h>
@@ -260,22 +261,28 @@ static void iommu_range_reserve(struct iommu_table *tbl,
spin_unlock_irqrestore(&tbl->it_lock, flags);
}
-static unsigned long iommu_range_alloc(struct iommu_table *tbl,
- unsigned int npages)
+static unsigned long iommu_range_alloc(struct device *dev,
+ struct iommu_table *tbl,
+ unsigned int npages)
{
unsigned long flags;
unsigned long offset;
+ unsigned long boundary_size;
+
+ boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+ PAGE_SIZE) >> PAGE_SHIFT;
BUG_ON(npages == 0);
spin_lock_irqsave(&tbl->it_lock, flags);
- offset = find_next_zero_string(tbl->it_map, tbl->it_hint,
- tbl->it_size, npages);
+ offset = iommu_area_alloc(tbl->it_map, tbl->it_size, tbl->it_hint,
+ npages, 0, boundary_size, 0);
if (offset == ~0UL) {
tbl->chip_ops->tce_cache_blast(tbl);
- offset = find_next_zero_string(tbl->it_map, 0,
- tbl->it_size, npages);
+
+ offset = iommu_area_alloc(tbl->it_map, tbl->it_size, 0,
+ npages, 0, boundary_size, 0);
if (offset == ~0UL) {
printk(KERN_WARNING "Calgary: IOMMU full.\n");
spin_unlock_irqrestore(&tbl->it_lock, flags);
@@ -286,7 +293,6 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
}
}
- set_bit_string(tbl->it_map, offset, npages);
tbl->it_hint = offset + npages;
BUG_ON(tbl->it_hint > tbl->it_size);
@@ -295,13 +301,13 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
return offset;
}
-static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *vaddr,
- unsigned int npages, int direction)
+static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
+ void *vaddr, unsigned int npages, int direction)
{
unsigned long entry;
dma_addr_t ret = bad_dma_address;
- entry = iommu_range_alloc(tbl, npages);
+ entry = iommu_range_alloc(dev, tbl, npages);
if (unlikely(entry == bad_dma_address))
goto error;
@@ -354,7 +360,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
badbit, tbl, dma_addr, entry, npages);
}
- __clear_bit_string(tbl->it_map, entry, npages);
+ iommu_area_free(tbl->it_map, entry, npages);
spin_unlock_irqrestore(&tbl->it_lock, flags);
}
@@ -438,7 +444,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
vaddr = (unsigned long) sg_virt(s);
npages = num_dma_pages(vaddr, s->length);
- entry = iommu_range_alloc(tbl, npages);
+ entry = iommu_range_alloc(dev, tbl, npages);
if (entry == bad_dma_address) {
/* makes sure unmap knows to stop */
s->dma_length = 0;
@@ -476,7 +482,7 @@ static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
npages = num_dma_pages(uaddr, size);
if (translation_enabled(tbl))
- dma_handle = iommu_alloc(tbl, vaddr, npages, direction);
+ dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction);
else
dma_handle = virt_to_bus(vaddr);
@@ -516,7 +522,7 @@ static void* calgary_alloc_coherent(struct device *dev, size_t size,
if (translation_enabled(tbl)) {
/* set up tces to cover the allocated range */
- mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL);
+ mapping = iommu_alloc(dev, tbl, ret, npages, DMA_BIDIRECTIONAL);
if (mapping == bad_dma_address)
goto free;
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 845cbecd68e..faf3229f8fb 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -25,6 +25,7 @@
#include <linux/bitops.h>
#include <linux/kdebug.h>
#include <linux/scatterlist.h>
+#include <linux/iommu-helper.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/mtrr.h>
@@ -82,17 +83,24 @@ AGPEXTERN __u32 *agp_gatt_table;
static unsigned long next_bit; /* protected by iommu_bitmap_lock */
static int need_flush; /* global flush state. set for each gart wrap */
-static unsigned long alloc_iommu(int size)
+static unsigned long alloc_iommu(struct device *dev, int size)
{
unsigned long offset, flags;
+ unsigned long boundary_size;
+ unsigned long base_index;
+
+ base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev),
+ PAGE_SIZE) >> PAGE_SHIFT;
+ boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+ PAGE_SIZE) >> PAGE_SHIFT;
spin_lock_irqsave(&iommu_bitmap_lock, flags);
- offset = find_next_zero_string(iommu_gart_bitmap, next_bit,
- iommu_pages, size);
+ offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit,
+ size, base_index, boundary_size, 0);
if (offset == -1) {
need_flush = 1;
- offset = find_next_zero_string(iommu_gart_bitmap, 0,
- iommu_pages, size);
+ offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0,
+ size, base_index, boundary_size, 0);
}
if (offset != -1) {
set_bit_string(iommu_gart_bitmap, offset, size);
@@ -114,7 +122,7 @@ static void free_iommu(unsigned long offset, int size)
unsigned long flags;
spin_lock_irqsave(&iommu_bitmap_lock, flags);
- __clear_bit_string(iommu_gart_bitmap, offset, size);
+ iommu_area_free(iommu_gart_bitmap, offset, size);
spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
}
@@ -235,7 +243,7 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
size_t size, int dir)
{
unsigned long npages = to_pages(phys_mem, size);
- unsigned long iommu_page = alloc_iommu(npages);
+ unsigned long iommu_page = alloc_iommu(dev, npages);
int i;
if (iommu_page == -1) {
@@ -355,10 +363,11 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
}
/* Map multiple scatterlist entries continuous into the first. */
-static int __dma_map_cont(struct scatterlist *start, int nelems,
- struct scatterlist *sout, unsigned long pages)
+static int __dma_map_cont(struct device *dev, struct scatterlist *start,
+ int nelems, struct scatterlist *sout,
+ unsigned long pages)
{
- unsigned long iommu_start = alloc_iommu(pages);
+ unsigned long iommu_start = alloc_iommu(dev, pages);
unsigned long iommu_page = iommu_start;
struct scatterlist *s;
int i;
@@ -394,8 +403,8 @@ static int __dma_map_cont(struct scatterlist *start, int nelems,
}
static inline int
-dma_map_cont(struct scatterlist *start, int nelems, struct scatterlist *sout,
- unsigned long pages, int need)
+dma_map_cont(struct device *dev, struct scatterlist *start, int nelems,
+ struct scatterlist *sout, unsigned long pages, int need)
{
if (!need) {
BUG_ON(nelems != 1);
@@ -403,7 +412,7 @@ dma_map_cont(struct scatterlist *start, int nelems, struct scatterlist *sout,
sout->dma_length = start->length;
return 0;
}
- return __dma_map_cont(start, nelems, sout, pages);
+ return __dma_map_cont(dev, start, nelems, sout, pages);
}
/*
@@ -416,6 +425,8 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
struct scatterlist *s, *ps, *start_sg, *sgmap;
int need = 0, nextneed, i, out, start;
unsigned long pages = 0;
+ unsigned int seg_size;
+ unsigned int max_seg_size;
if (nents == 0)
return 0;
@@ -426,6 +437,8 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
out = 0;
start = 0;
start_sg = sgmap = sg;
+ seg_size = 0;
+ max_seg_size = dma_get_max_seg_size(dev);
ps = NULL; /* shut up gcc */
for_each_sg(sg, s, nents, i) {
dma_addr_t addr = sg_phys(s);
@@ -443,11 +456,13 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
* offset.
*/
if (!iommu_merge || !nextneed || !need || s->offset ||
+ (s->length + seg_size > max_seg_size) ||
(ps->offset + ps->length) % PAGE_SIZE) {
- if (dma_map_cont(start_sg, i - start, sgmap,
- pages, need) < 0)
+ if (dma_map_cont(dev, start_sg, i - start,
+ sgmap, pages, need) < 0)
goto error;
out++;
+ seg_size = 0;
sgmap = sg_next(sgmap);
pages = 0;
start = i;
@@ -455,11 +470,12 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
}
}
+ seg_size += s->length;
need = nextneed;
pages += to_pages(s->offset, s->length);
ps = s;
}
- if (dma_map_cont(start_sg, i - start, sgmap, pages, need) < 0)
+ if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0)
goto error;
out++;
flush_gart();
@@ -733,6 +749,15 @@ void __init gart_iommu_init(void)
*/
set_memory_np((unsigned long)__va(iommu_bus_base),
iommu_size >> PAGE_SHIFT);
+ /*
+ * Tricky. The GART table remaps the physical memory range,
+ * so the CPU wont notice potential aliases and if the memory
+ * is remapped to UC later on, we might surprise the PCI devices
+ * with a stray writeout of a cacheline. So play it sure and
+ * do an explicit, full-scale wbinvd() _after_ having marked all
+ * the pages as Not-Present:
+ */
+ wbinvd();
/*
* Try to workaround a bug (thanks to BenH)
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index dabdbeff1f7..a7d50a547dc 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -23,7 +23,6 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/interrupt.h>
#include <linux/utsname.h>
#include <linux/delay.h>
@@ -539,55 +538,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
return err;
}
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
- u16 gs;
-
-/* changed the size calculations - should hopefully work better. lbt */
- dump->magic = CMAGIC;
- dump->start_code = 0;
- dump->start_stack = regs->sp & ~(PAGE_SIZE - 1);
- dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
- dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
- dump->u_dsize -= dump->u_tsize;
- dump->u_ssize = 0;
- dump->u_debugreg[0] = current->thread.debugreg0;
- dump->u_debugreg[1] = current->thread.debugreg1;
- dump->u_debugreg[2] = current->thread.debugreg2;
- dump->u_debugreg[3] = current->thread.debugreg3;
- dump->u_debugreg[4] = 0;
- dump->u_debugreg[5] = 0;
- dump->u_debugreg[6] = current->thread.debugreg6;
- dump->u_debugreg[7] = current->thread.debugreg7;
-
- if (dump->start_stack < TASK_SIZE)
- dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
-
- dump->regs.bx = regs->bx;
- dump->regs.cx = regs->cx;
- dump->regs.dx = regs->dx;
- dump->regs.si = regs->si;
- dump->regs.di = regs->di;
- dump->regs.bp = regs->bp;
- dump->regs.ax = regs->ax;
- dump->regs.ds = (u16)regs->ds;
- dump->regs.es = (u16)regs->es;
- dump->regs.fs = (u16)regs->fs;
- savesegment(gs,gs);
- dump->regs.orig_ax = regs->orig_ax;
- dump->regs.ip = regs->ip;
- dump->regs.cs = (u16)regs->cs;
- dump->regs.flags = regs->flags;
- dump->regs.sp = regs->sp;
- dump->regs.ss = (u16)regs->ss;
-
- dump->u_fpvalid = dump_fpu (regs, &dump->i387);
-}
-EXPORT_SYMBOL(dump_thread);
-
#ifdef CONFIG_SECCOMP
static void hard_disable_TSC(void)
{
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 137a86171c3..b0cc8f0136d 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -26,7 +26,6 @@
#include <linux/smp.h>
#include <linux/slab.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/interrupt.h>
#include <linux/utsname.h>
#include <linux/delay.h>
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 96286df1bb8..702c33efea8 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -103,9 +103,26 @@ static int set_segment_reg(struct task_struct *task,
if (invalid_selector(value))
return -EIO;
- if (offset != offsetof(struct user_regs_struct, gs))
+ /*
+ * For %cs and %ss we cannot permit a null selector.
+ * We can permit a bogus selector as long as it has USER_RPL.
+ * Null selectors are fine for other segment registers, but
+ * we will never get back to user mode with invalid %cs or %ss
+ * and will take the trap in iret instead. Much code relies
+ * on user_mode() to distinguish a user trap frame (which can
+ * safely use invalid selectors) from a kernel trap frame.
+ */
+ switch (offset) {
+ case offsetof(struct user_regs_struct, cs):
+ case offsetof(struct user_regs_struct, ss):
+ if (unlikely(value == 0))
+ return -EIO;
+
+ default:
*pt_regs_access(task_pt_regs(task), offset) = value;
- else {
+ break;
+
+ case offsetof(struct user_regs_struct, gs):
task->thread.gs = value;
if (task == current)
/*
@@ -227,12 +244,16 @@ static int set_segment_reg(struct task_struct *task,
* Can't actually change these in 64-bit mode.
*/
case offsetof(struct user_regs_struct,cs):
+ if (unlikely(value == 0))
+ return -EIO;
#ifdef CONFIG_IA32_EMULATION
if (test_tsk_thread_flag(task, TIF_IA32))
task_pt_regs(task)->cs = value;
#endif
break;
case offsetof(struct user_regs_struct,ss):
+ if (unlikely(value == 0))
+ return -EIO;
#ifdef CONFIG_IA32_EMULATION
if (test_tsk_thread_flag(task, TIF_IA32))
task_pt_regs(task)->ss = value;
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 3cd7a2dcd4f..c47208fc593 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -11,7 +11,7 @@
static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
{
u8 config, rev;
- u32 word;
+ u16 word;
/* BIOS may enable hardware IRQ balancing for
* E7520/E7320/E7525(revision ID 0x9 and below)
@@ -26,8 +26,11 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
pci_read_config_byte(dev, 0xf4, &config);
pci_write_config_byte(dev, 0xf4, config|0x2);
- /* read xTPR register */
- raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
+ /*
+ * read xTPR register. We may not have a pci_dev for device 8
+ * because it might be hidden until the above write.
+ */
+ pci_bus_read_config_word(dev->bus, PCI_DEVFN(8, 0), 0x4c, &word);
if (!(word & (1 << 13))) {
dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
@@ -380,19 +383,19 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0367,
void force_hpet_resume(void)
{
switch (force_hpet_resume_type) {
- case ICH_FORCE_HPET_RESUME:
- return ich_force_hpet_resume();
-
- case OLD_ICH_FORCE_HPET_RESUME:
- return old_ich_force_hpet_resume();
-
- case VT8237_FORCE_HPET_RESUME:
- return vt8237_force_hpet_resume();
-
- case NVIDIA_FORCE_HPET_RESUME:
- return nvidia_force_hpet_resume();
-
- default:
+ case ICH_FORCE_HPET_RESUME:
+ ich_force_hpet_resume();
+ return;
+ case OLD_ICH_FORCE_HPET_RESUME:
+ old_ich_force_hpet_resume();
+ return;
+ case VT8237_FORCE_HPET_RESUME:
+ vt8237_force_hpet_resume();
+ return;
+ case NVIDIA_FORCE_HPET_RESUME:
+ nvidia_force_hpet_resume();
+ return;
+ default:
break;
}
}
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 5818dc28167..7fd6ac43e4a 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -326,7 +326,7 @@ static inline void kb_wait(void)
}
}
-void machine_emergency_restart(void)
+static void native_machine_emergency_restart(void)
{
int i;
@@ -376,7 +376,7 @@ void machine_emergency_restart(void)
}
}
-void machine_shutdown(void)
+static void native_machine_shutdown(void)
{
/* Stop the cpus and apics */
#ifdef CONFIG_SMP
@@ -420,7 +420,7 @@ void machine_shutdown(void)
#endif
}
-void machine_restart(char *__unused)
+static void native_machine_restart(char *__unused)
{
printk("machine restart\n");
@@ -429,11 +429,11 @@ void machine_restart(char *__unused)
machine_emergency_restart();
}
-void machine_halt(void)
+static void native_machine_halt(void)
{
}
-void machine_power_off(void)
+static void native_machine_power_off(void)
{
if (pm_power_off) {
if (!reboot_force)
@@ -443,9 +443,35 @@ void machine_power_off(void)
}
struct machine_ops machine_ops = {
- .power_off = machine_power_off,
- .shutdown = machine_shutdown,
- .emergency_restart = machine_emergency_restart,
- .restart = machine_restart,
- .halt = machine_halt
+ .power_off = native_machine_power_off,
+ .shutdown = native_machine_shutdown,
+ .emergency_restart = native_machine_emergency_restart,
+ .restart = native_machine_restart,
+ .halt = native_machine_halt
};
+
+void machine_power_off(void)
+{
+ machine_ops.power_off();
+}
+
+void machine_shutdown(void)
+{
+ machine_ops.shutdown();
+}
+
+void machine_emergency_restart(void)
+{
+ machine_ops.emergency_restart();
+}
+
+void machine_restart(char *cmd)
+{
+ machine_ops.restart(cmd);
+}
+
+void machine_halt(void)
+{
+ machine_ops.halt();
+}
+
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index 62adc5f20be..691ab4cb167 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -154,7 +154,11 @@ struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
EXPORT_SYMBOL(boot_cpu_data);
+#ifndef CONFIG_X86_PAE
unsigned long mmu_cr4_features;
+#else
+unsigned long mmu_cr4_features = X86_CR4_PAE;
+#endif
/* for MCA, but anyone else can use it if they want */
unsigned int machine_id;
@@ -390,7 +394,7 @@ static void __init reserve_ebda_region(void)
unsigned int addr;
addr = get_bios_ebda();
if (addr)
- reserve_bootmem(addr, PAGE_SIZE);
+ reserve_bootmem(addr, PAGE_SIZE, BOOTMEM_DEFAULT);
}
#ifndef CONFIG_NEED_MULTIPLE_NODES
@@ -484,7 +488,8 @@ static void __init reserve_crashkernel(void)
(unsigned long)(total_mem >> 20));
crashk_res.start = crash_base;
crashk_res.end = crash_base + crash_size - 1;
- reserve_bootmem(crash_base, crash_size);
+ reserve_bootmem(crash_base, crash_size,
+ BOOTMEM_DEFAULT);
} else
printk(KERN_INFO "crashkernel reservation failed - "
"you have to specify a base address\n");
@@ -525,7 +530,7 @@ static void __init reserve_initrd(void)
}
if (ramdisk_end <= end_of_lowmem) {
/* All in lowmem, easy case */
- reserve_bootmem(ramdisk_image, ramdisk_size);
+ reserve_bootmem(ramdisk_image, ramdisk_size, BOOTMEM_DEFAULT);
initrd_start = ramdisk_image + PAGE_OFFSET;
initrd_end = initrd_start+ramdisk_size;
return;
@@ -536,7 +541,7 @@ static void __init reserve_initrd(void)
/* Note: this includes all the lowmem currently occupied by
the initrd, we rely on that fact to keep the data intact. */
- reserve_bootmem(ramdisk_here, ramdisk_size);
+ reserve_bootmem(ramdisk_here, ramdisk_size, BOOTMEM_DEFAULT);
initrd_start = ramdisk_here + PAGE_OFFSET;
initrd_end = initrd_start + ramdisk_size;
@@ -606,13 +611,14 @@ void __init setup_bootmem_allocator(void)
* bootmem allocator with an invalid RAM area.
*/
reserve_bootmem(__pa_symbol(_text), (PFN_PHYS(min_low_pfn) +
- bootmap_size + PAGE_SIZE-1) - __pa_symbol(_text));
+ bootmap_size + PAGE_SIZE-1) - __pa_symbol(_text),
+ BOOTMEM_DEFAULT);
/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
* enabling clean reboots, SMP operation, laptop functions.
*/
- reserve_bootmem(0, PAGE_SIZE);
+ reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
/* reserve EBDA region, it's a 4K region */
reserve_ebda_region();
@@ -622,7 +628,7 @@ void __init setup_bootmem_allocator(void)
unless you have no PS/2 mouse plugged in. */
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
boot_cpu_data.x86 == 6)
- reserve_bootmem(0xa0000 - 4096, 4096);
+ reserve_bootmem(0xa0000 - 4096, 4096, BOOTMEM_DEFAULT);
#ifdef CONFIG_SMP
/*
@@ -630,7 +636,7 @@ void __init setup_bootmem_allocator(void)
* FIXME: Don't need the extra page at 4K, but need to fix
* trampoline before removing it. (see the GDT stuff)
*/
- reserve_bootmem(PAGE_SIZE, PAGE_SIZE);
+ reserve_bootmem(PAGE_SIZE, PAGE_SIZE, BOOTMEM_DEFAULT);
#endif
#ifdef CONFIG_ACPI_SLEEP
/*
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index c8939dfddfb..c0d8208af12 100644
--- a/arch/x86/kernel/setup_64.c
+++ b/arch/x86/kernel/setup_64.c
@@ -15,7 +15,6 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
-#include <linux/a.out.h>
#include <linux/screen_info.h>
#include <linux/ioport.h>
#include <linux/delay.h>
@@ -189,7 +188,7 @@ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
e820_register_active_regions(0, start_pfn, end_pfn);
free_bootmem_with_active_regions(0, end_pfn);
- reserve_bootmem(bootmap, bootmap_size);
+ reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
}
#endif
@@ -220,28 +219,35 @@ static inline void copy_edd(void)
#ifdef CONFIG_KEXEC
static void __init reserve_crashkernel(void)
{
- unsigned long long free_mem;
+ unsigned long long total_mem;
unsigned long long crash_size, crash_base;
int ret;
- free_mem =
- ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
+ total_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
- ret = parse_crashkernel(boot_command_line, free_mem,
+ ret = parse_crashkernel(boot_command_line, total_mem,
&crash_size, &crash_base);
if (ret == 0 && crash_size) {
- if (crash_base > 0) {
- printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
- "for crashkernel (System RAM: %ldMB)\n",
- (unsigned long)(crash_size >> 20),
- (unsigned long)(crash_base >> 20),
- (unsigned long)(free_mem >> 20));
- crashk_res.start = crash_base;
- crashk_res.end = crash_base + crash_size - 1;
- reserve_bootmem(crash_base, crash_size);
- } else
+ if (crash_base <= 0) {
printk(KERN_INFO "crashkernel reservation failed - "
"you have to specify a base address\n");
+ return;
+ }
+
+ if (reserve_bootmem(crash_base, crash_size,
+ BOOTMEM_EXCLUSIVE) < 0) {
+ printk(KERN_INFO "crashkernel reservation failed - "
+ "memory is in use\n");
+ return;
+ }
+
+ printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+ "for crashkernel (System RAM: %ldMB)\n",
+ (unsigned long)(crash_size >> 20),
+ (unsigned long)(crash_base >> 20),
+ (unsigned long)(total_mem >> 20));
+ crashk_res.start = crash_base;
+ crashk_res.end = crash_base + crash_size - 1;
}
}
#else
diff --git a/arch/x86/kernel/smpboot_32.c b/arch/x86/kernel/smpboot_32.c
index 5787a0c3e29..579b9b740c7 100644
--- a/arch/x86/kernel/smpboot_32.c
+++ b/arch/x86/kernel/smpboot_32.c
@@ -202,8 +202,6 @@ valid_k7:
;
}
-extern void calibrate_delay(void);
-
static atomic_t init_deasserted;
static void __cpuinit smp_callin(void)
diff --git a/arch/x86/kernel/srat_32.c b/arch/x86/kernel/srat_32.c
index 2bf6903cb44..b72e61359c3 100644
--- a/arch/x86/kernel/srat_32.c
+++ b/arch/x86/kernel/srat_32.c
@@ -274,7 +274,7 @@ int __init get_memcfg_from_srat(void)
int tables = 0;
int i = 0;
- rsdp_address = acpi_find_rsdp();
+ rsdp_address = acpi_os_get_root_pointer();
if (!rsdp_address) {
printk("%s: System description tables not found\n",
__FUNCTION__);
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index 8344c70adf6..adff5562f5f 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -321,6 +321,8 @@ ENTRY(sys_call_table)
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
.long sys_signalfd
- .long sys_timerfd
+ .long sys_timerfd_create
.long sys_eventfd
.long sys_fallocate
+ .long sys_timerfd_settime /* 325 */
+ .long sys_timerfd_gettime
diff --git a/arch/x86/kernel/test_nx.c b/arch/x86/kernel/test_nx.c
index 36c100c323a..10b8a6f69f8 100644
--- a/arch/x86/kernel/test_nx.c
+++ b/arch/x86/kernel/test_nx.c
@@ -139,7 +139,6 @@ static int test_NX(void)
* Until then, don't run them to avoid too many people getting scared
* by the error message
*/
-#if 0
#ifdef CONFIG_DEBUG_RODATA
/* Test 3: Check if the .rodata section is executable */
@@ -152,6 +151,7 @@ static int test_NX(void)
}
#endif
+#if 0
/* Test 4: Check if the .data section of a module is executable */
if (test_address(&test_data)) {
printk(KERN_ERR "test_nx: .data section is executable\n");
diff --git a/arch/x86/kernel/test_rodata.c b/arch/x86/kernel/test_rodata.c
index 4c163772000..c29e235792a 100644
--- a/arch/x86/kernel/test_rodata.c
+++ b/arch/x86/kernel/test_rodata.c
@@ -10,8 +10,8 @@
* of the License.
*/
#include <linux/module.h>
+#include <asm/cacheflush.h>
#include <asm/sections.h>
-extern int rodata_test_data;
int rodata_test(void)
{
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c
index 0380795121a..c737849e2ef 100644
--- a/arch/x86/kernel/time_64.c
+++ b/arch/x86/kernel/time_64.c
@@ -77,7 +77,7 @@ unsigned long __init native_calculate_cpu_khz(void)
reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
}
local_irq_save(flags);
- /* start meauring cycles, incrementing from 0 */
+ /* start measuring cycles, incrementing from 0 */
wrmsrl(MSR_K7_PERFCTR0 + i, 0);
wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76);
rdtscl(tsc_start);
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c
index e6757aaa202..a40051b71d9 100644
--- a/arch/x86/kernel/topology.c
+++ b/arch/x86/kernel/topology.c
@@ -53,7 +53,7 @@ EXPORT_SYMBOL(arch_register_cpu);
void arch_unregister_cpu(int num)
{
- return unregister_cpu(&per_cpu(cpu_devices, num).cpu);
+ unregister_cpu(&per_cpu(cpu_devices, num).cpu);
}
EXPORT_SYMBOL(arch_unregister_cpu);
#else
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index 3cf72977d01..b22c01e05a1 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -1176,17 +1176,12 @@ void __init trap_init(void)
#endif
set_trap_gate(19,&simd_coprocessor_error);
+ /*
+ * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
+ * Generate a build-time error if the alignment is wrong.
+ */
+ BUILD_BUG_ON(offsetof(struct task_struct, thread.i387.fxsave) & 15);
if (cpu_has_fxsr) {
- /*
- * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
- * Generates a compile-time "error: zero width for bit-field" if
- * the alignment is wrong.
- */
- struct fxsrAlignAssert {
- int _:!(offsetof(struct task_struct,
- thread.i387.fxsave) & 15);
- };
-
printk(KERN_INFO "Enabling fast FPU save and restore... ");
set_in_cr4(X86_CR4_OSFXSR);
printk("done.\n");
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
index efc66df728b..04546668191 100644
--- a/arch/x86/kernel/traps_64.c
+++ b/arch/x86/kernel/traps_64.c
@@ -84,7 +84,7 @@ static inline void conditional_sti(struct pt_regs *regs)
static inline void preempt_conditional_sti(struct pt_regs *regs)
{
- preempt_disable();
+ inc_preempt_count();
if (regs->flags & X86_EFLAGS_IF)
local_irq_enable();
}
@@ -95,7 +95,7 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
local_irq_disable();
/* Make sure to not schedule here because we could be running
on an exception stack. */
- preempt_enable_no_resched();
+ dec_preempt_count();
}
int kstack_depth_to_print = 12;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8f94a0b89df..cf530814868 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1739,7 +1739,7 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
if (bytes == 8) {
gpa_t gpa;
struct page *page;
- char *addr;
+ char *kaddr;
u64 val;
down_read(&current->mm->mmap_sem);
@@ -1754,9 +1754,9 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
val = *(u64 *)new;
page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
- addr = kmap_atomic(page, KM_USER0);
- set_64bit((u64 *)(addr + offset_in_page(gpa)), val);
- kunmap_atomic(addr, KM_USER0);
+ kaddr = kmap_atomic(page, KM_USER0);
+ set_64bit((u64 *)(kaddr + offset_in_page(gpa)), val);
+ kunmap_atomic(kaddr, KM_USER0);
kvm_release_page_dirty(page);
emul_write:
up_read(&current->mm->mmap_sem);
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 4876182daf8..25df1c1989f 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -21,7 +21,7 @@ else
lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o
lib-y += thunk_64.o clear_page_64.o copy_page_64.o
- lib-y += bitstr_64.o bitops_64.o
+ lib-y += bitops_64.o
lib-y += memmove_64.o memset_64.o
lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
endif
diff --git a/arch/x86/lib/bitstr_64.c b/arch/x86/lib/bitstr_64.c
deleted file mode 100644
index 7445caf1b5d..00000000000
--- a/arch/x86/lib/bitstr_64.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <linux/module.h>
-#include <linux/bitops.h>
-
-/* Find string of zero bits in a bitmap */
-unsigned long
-find_next_zero_string(unsigned long *bitmap, long start, long nbits, int len)
-{
- unsigned long n, end, i;
-
- again:
- n = find_next_zero_bit(bitmap, nbits, start);
- if (n == -1)
- return -1;
-
- /* could test bitsliced, but it's hardly worth it */
- end = n+len;
- if (end > nbits)
- return -1;
- for (i = n+1; i < end; i++) {
- if (test_bit(i, bitmap)) {
- start = i+1;
- goto again;
- }
- }
- return n;
-}
-
-EXPORT_SYMBOL(find_next_zero_string);
diff --git a/arch/x86/lib/delay_32.c b/arch/x86/lib/delay_32.c
index aad9d95469d..4535e6d147a 100644
--- a/arch/x86/lib/delay_32.c
+++ b/arch/x86/lib/delay_32.c
@@ -12,8 +12,10 @@
#include <linux/module.h>
#include <linux/sched.h>
+#include <linux/timex.h>
#include <linux/preempt.h>
#include <linux/delay.h>
+#include <linux/init.h>
#include <asm/processor.h>
#include <asm/delay.h>
@@ -63,7 +65,7 @@ void use_tsc_delay(void)
delay_fn = delay_tsc;
}
-int read_current_timer(unsigned long *timer_val)
+int __devinit read_current_timer(unsigned long *timer_val)
{
if (delay_fn == delay_tsc) {
rdtscl(*timer_val);
diff --git a/arch/x86/lib/delay_64.c b/arch/x86/lib/delay_64.c
index 45cdd3fbd91..bbc61051851 100644
--- a/arch/x86/lib/delay_64.c
+++ b/arch/x86/lib/delay_64.c
@@ -10,8 +10,10 @@
#include <linux/module.h>
#include <linux/sched.h>
+#include <linux/timex.h>
#include <linux/preempt.h>
#include <linux/delay.h>
+#include <linux/init.h>
#include <asm/delay.h>
#include <asm/msr.h>
@@ -20,7 +22,7 @@
#include <asm/smp.h>
#endif
-int read_current_timer(unsigned long *timer_value)
+int __devinit read_current_timer(unsigned long *timer_value)
{
rdtscll(*timer_value);
return 0;
diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c
index dffa786f61f..3cc8eb2f36a 100644
--- a/arch/x86/mach-voyager/voyager_smp.c
+++ b/arch/x86/mach-voyager/voyager_smp.c
@@ -444,8 +444,6 @@ static __u32 __init setup_trampoline(void)
static void __init start_secondary(void *unused)
{
__u8 cpuid = hard_smp_processor_id();
- /* external functions not defined in the headers */
- extern void calibrate_delay(void);
cpu_init();
diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c
index 04b1d20e261..c394ca0720b 100644
--- a/arch/x86/mm/discontig_32.c
+++ b/arch/x86/mm/discontig_32.c
@@ -391,7 +391,8 @@ unsigned long __init setup_memory(void)
void __init numa_kva_reserve(void)
{
if (kva_pages)
- reserve_bootmem(PFN_PHYS(kva_start_pfn), PFN_PHYS(kva_pages));
+ reserve_bootmem(PFN_PHYS(kva_start_pfn), PFN_PHYS(kva_pages),
+ BOOTMEM_DEFAULT);
}
void __init zone_sizes_init(void)
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index ad8b9733d6b..fdc667422df 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -186,7 +186,7 @@ static int bad_address(void *p)
}
#endif
-void dump_pagetable(unsigned long address)
+static void dump_pagetable(unsigned long address)
{
#ifdef CONFIG_X86_32
__typeof__(pte_val(__pte(0))) page;
@@ -428,6 +428,16 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
}
#endif
+static int spurious_fault_check(unsigned long error_code, pte_t *pte)
+{
+ if ((error_code & PF_WRITE) && !pte_write(*pte))
+ return 0;
+ if ((error_code & PF_INSTR) && !pte_exec(*pte))
+ return 0;
+
+ return 1;
+}
+
/*
* Handle a spurious fault caused by a stale TLB entry. This allows
* us to lazily refresh the TLB when increasing the permissions of a
@@ -457,20 +467,21 @@ static int spurious_fault(unsigned long address,
if (!pud_present(*pud))
return 0;
+ if (pud_large(*pud))
+ return spurious_fault_check(error_code, (pte_t *) pud);
+
pmd = pmd_offset(pud, address);
if (!pmd_present(*pmd))
return 0;
+ if (pmd_large(*pmd))
+ return spurious_fault_check(error_code, (pte_t *) pmd);
+
pte = pte_offset_kernel(pmd, address);
if (!pte_present(*pte))
return 0;
- if ((error_code & PF_WRITE) && !pte_write(*pte))
- return 0;
- if ((error_code & PF_INSTR) && !pte_exec(*pte))
- return 0;
-
- return 1;
+ return spurious_fault_check(error_code, pte);
}
/*
@@ -947,11 +958,12 @@ void vmalloc_sync_all(void)
for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) {
if (!test_bit(pgd_index(address), insync)) {
const pgd_t *pgd_ref = pgd_offset_k(address);
+ unsigned long flags;
struct page *page;
if (pgd_none(*pgd_ref))
continue;
- spin_lock(&pgd_lock);
+ spin_lock_irqsave(&pgd_lock, flags);
list_for_each_entry(page, &pgd_list, lru) {
pgd_t *pgd;
pgd = (pgd_t *)page_address(page) + pgd_index(address);
@@ -960,7 +972,7 @@ void vmalloc_sync_all(void)
else
BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
}
- spin_unlock(&pgd_lock);
+ spin_unlock_irqrestore(&pgd_lock, flags);
set_bit(pgd_index(address), insync);
}
if (address == start)
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index d1bc04006d1..ee1091a4696 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -46,6 +46,8 @@
#include <asm/pgalloc.h>
#include <asm/sections.h>
#include <asm/paravirt.h>
+#include <asm/setup.h>
+#include <asm/cacheflush.h>
unsigned int __VMALLOC_RESERVE = 128 << 20;
@@ -328,44 +330,38 @@ pteval_t __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC;
void __init native_pagetable_setup_start(pgd_t *base)
{
-#ifdef CONFIG_X86_PAE
- int i;
+ unsigned long pfn, va;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
/*
- * Init entries of the first-level page table to the
- * zero page, if they haven't already been set up.
- *
- * In a normal native boot, we'll be running on a
- * pagetable rooted in swapper_pg_dir, but not in PAE
- * mode, so this will end up clobbering the mappings
- * for the lower 24Mbytes of the address space,
- * without affecting the kernel address space.
+ * Remove any mappings which extend past the end of physical
+ * memory from the boot time page table:
*/
- for (i = 0; i < USER_PTRS_PER_PGD; i++)
- set_pgd(&base[i],
- __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
-
- /* Make sure kernel address space is empty so that a pagetable
- will be allocated for it. */
- memset(&base[USER_PTRS_PER_PGD], 0,
- KERNEL_PGD_PTRS * sizeof(pgd_t));
-#else
+ for (pfn = max_low_pfn + 1; pfn < 1<<(32-PAGE_SHIFT); pfn++) {
+ va = PAGE_OFFSET + (pfn<<PAGE_SHIFT);
+ pgd = base + pgd_index(va);
+ if (!pgd_present(*pgd))
+ break;
+
+ pud = pud_offset(pgd, va);
+ pmd = pmd_offset(pud, va);
+ if (!pmd_present(*pmd))
+ break;
+
+ pte = pte_offset_kernel(pmd, va);
+ if (!pte_present(*pte))
+ break;
+
+ pte_clear(NULL, va, pte);
+ }
paravirt_alloc_pd(&init_mm, __pa(base) >> PAGE_SHIFT);
-#endif
}
void __init native_pagetable_setup_done(pgd_t *base)
{
-#ifdef CONFIG_X86_PAE
- /*
- * Add low memory identity-mappings - SMP needs it when
- * starting up on an AP from real-mode. In the non-PAE
- * case we already have these mappings through head.S.
- * All user-space mappings are explicitly cleared after
- * SMP startup.
- */
- set_pgd(&base[0], base[USER_PTRS_PER_PGD]);
-#endif
}
/*
@@ -374,9 +370,8 @@ void __init native_pagetable_setup_done(pgd_t *base)
* the boot process.
*
* If we're booting on native hardware, this will be a pagetable
- * constructed in arch/i386/kernel/head.S, and not running in PAE mode
- * (even if we'll end up running in PAE). The root of the pagetable
- * will be swapper_pg_dir.
+ * constructed in arch/x86/kernel/head_32.S. The root of the
+ * pagetable will be swapper_pg_dir.
*
* If we're booting paravirtualized under a hypervisor, then there are
* more options: we may already be running PAE, and the pagetable may
@@ -537,14 +532,6 @@ void __init paging_init(void)
load_cr3(swapper_pg_dir);
-#ifdef CONFIG_X86_PAE
- /*
- * We will bail out later - printk doesn't work right now so
- * the user would just see a hanging kernel.
- */
- if (cpu_has_pae)
- set_in_cr4(X86_CR4_PAE);
-#endif
__flush_tlb_all();
kmap_init();
@@ -675,13 +662,11 @@ void __init mem_init(void)
BUG_ON((unsigned long)high_memory > VMALLOC_START);
#endif /* double-sanity-check paranoia */
-#ifdef CONFIG_X86_PAE
- if (!cpu_has_pae)
- panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
-#endif
if (boot_cpu_data.wp_works_ok < 0)
test_wp_bit();
+ cpa_init();
+
/*
* Subtle. SMP is doing it's boot stuff late (because it has to
* fork idle threads) - but it also needs low mappings for the
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 3a98d6f724a..a4a9cccdd4f 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -45,6 +45,7 @@
#include <asm/sections.h>
#include <asm/kdebug.h>
#include <asm/numa.h>
+#include <asm/cacheflush.h>
const struct dma_mapping_ops *dma_ops;
EXPORT_SYMBOL(dma_ops);
@@ -528,13 +529,15 @@ void __init mem_init(void)
reservedpages << (PAGE_SHIFT-10),
datasize >> 10,
initsize >> 10);
+
+ cpa_init();
}
void free_init_pages(char *what, unsigned long begin, unsigned long end)
{
- unsigned long addr;
+ unsigned long addr = begin;
- if (begin >= end)
+ if (addr >= end)
return;
/*
@@ -549,7 +552,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
#else
printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
- for (addr = begin; addr < end; addr += PAGE_SIZE) {
+ for (; addr < end; addr += PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
init_page_count(virt_to_page(addr));
memset((void *)(addr & ~(PAGE_SIZE-1)),
@@ -591,10 +594,17 @@ void mark_rodata_ro(void)
if (end <= start)
return;
- set_memory_ro(start, (end - start) >> PAGE_SHIFT);
printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
(end - start) >> 10);
+ set_memory_ro(start, (end - start) >> PAGE_SHIFT);
+
+ /*
+ * The rodata section (but not the kernel text!) should also be
+ * not-executable.
+ */
+ start = ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK;
+ set_memory_nx(start, (end - start) >> PAGE_SHIFT);
rodata_test();
@@ -637,9 +647,9 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
/* Should check here against the e820 map to avoid double free */
#ifdef CONFIG_NUMA
- reserve_bootmem_node(NODE_DATA(nid), phys, len);
+ reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT);
#else
- reserve_bootmem(phys, len);
+ reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
#endif
if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
dma_reserve += len / PAGE_SIZE;
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index ee6648fe6b1..9f42d7e9c15 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -260,41 +260,48 @@ static int __init early_ioremap_debug_setup(char *str)
early_param("early_ioremap_debug", early_ioremap_debug_setup);
static __initdata int after_paging_init;
-static __initdata unsigned long bm_pte[1024]
+static __initdata pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)]
__attribute__((aligned(PAGE_SIZE)));
-static inline unsigned long * __init early_ioremap_pgd(unsigned long addr)
+static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
{
- return (unsigned long *)swapper_pg_dir + ((addr >> 22) & 1023);
+ /* Don't assume we're using swapper_pg_dir at this point */
+ pgd_t *base = __va(read_cr3());
+ pgd_t *pgd = &base[pgd_index(addr)];
+ pud_t *pud = pud_offset(pgd, addr);
+ pmd_t *pmd = pmd_offset(pud, addr);
+
+ return pmd;
}
-static inline unsigned long * __init early_ioremap_pte(unsigned long addr)
+static inline pte_t * __init early_ioremap_pte(unsigned long addr)
{
- return bm_pte + ((addr >> PAGE_SHIFT) & 1023);
+ return &bm_pte[pte_index(addr)];
}
void __init early_ioremap_init(void)
{
- unsigned long *pgd;
+ pmd_t *pmd;
if (early_ioremap_debug)
printk(KERN_INFO "early_ioremap_init()\n");
- pgd = early_ioremap_pgd(fix_to_virt(FIX_BTMAP_BEGIN));
- *pgd = __pa(bm_pte) | _PAGE_TABLE;
+ pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
memset(bm_pte, 0, sizeof(bm_pte));
+ pmd_populate_kernel(&init_mm, pmd, bm_pte);
+
/*
- * The boot-ioremap range spans multiple pgds, for which
+ * The boot-ioremap range spans multiple pmds, for which
* we are not prepared:
*/
- if (pgd != early_ioremap_pgd(fix_to_virt(FIX_BTMAP_END))) {
+ if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
WARN_ON(1);
- printk(KERN_WARNING "pgd %p != %p\n",
- pgd, early_ioremap_pgd(fix_to_virt(FIX_BTMAP_END)));
+ printk(KERN_WARNING "pmd %p != %p\n",
+ pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
- fix_to_virt(FIX_BTMAP_BEGIN));
+ fix_to_virt(FIX_BTMAP_BEGIN));
printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_END): %08lx\n",
- fix_to_virt(FIX_BTMAP_END));
+ fix_to_virt(FIX_BTMAP_END));
printk(KERN_WARNING "FIX_BTMAP_END: %d\n", FIX_BTMAP_END);
printk(KERN_WARNING "FIX_BTMAP_BEGIN: %d\n",
@@ -304,28 +311,29 @@ void __init early_ioremap_init(void)
void __init early_ioremap_clear(void)
{
- unsigned long *pgd;
+ pmd_t *pmd;
if (early_ioremap_debug)
printk(KERN_INFO "early_ioremap_clear()\n");
- pgd = early_ioremap_pgd(fix_to_virt(FIX_BTMAP_BEGIN));
- *pgd = 0;
- paravirt_release_pt(__pa(pgd) >> PAGE_SHIFT);
+ pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+ pmd_clear(pmd);
+ paravirt_release_pt(__pa(bm_pte) >> PAGE_SHIFT);
__flush_tlb_all();
}
void __init early_ioremap_reset(void)
{
enum fixed_addresses idx;
- unsigned long *pte, phys, addr;
+ unsigned long addr, phys;
+ pte_t *pte;
after_paging_init = 1;
for (idx = FIX_BTMAP_BEGIN; idx >= FIX_BTMAP_END; idx--) {
addr = fix_to_virt(idx);
pte = early_ioremap_pte(addr);
- if (*pte & _PAGE_PRESENT) {
- phys = *pte & PAGE_MASK;
+ if (pte_present(*pte)) {
+ phys = pte_val(*pte) & PAGE_MASK;
set_fixmap(idx, phys);
}
}
@@ -334,7 +342,8 @@ void __init early_ioremap_reset(void)
static void __init __early_set_fixmap(enum fixed_addresses idx,
unsigned long phys, pgprot_t flags)
{
- unsigned long *pte, addr = __fix_to_virt(idx);
+ unsigned long addr = __fix_to_virt(idx);
+ pte_t *pte;
if (idx >= __end_of_fixed_addresses) {
BUG();
@@ -342,9 +351,9 @@ static void __init __early_set_fixmap(enum fixed_addresses idx,
}
pte = early_ioremap_pte(addr);
if (pgprot_val(flags))
- *pte = (phys & PAGE_MASK) | pgprot_val(flags);
+ set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
else
- *pte = 0;
+ pte_clear(NULL, addr, pte);
__flush_tlb_one(addr);
}
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index 5a02bf4c91e..1aecc658cd7 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -238,9 +238,10 @@ void __init setup_node_bootmem(int nodeid, unsigned long start,
free_bootmem_with_active_regions(nodeid, end);
- reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size);
+ reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size,
+ BOOTMEM_DEFAULT);
reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start,
- bootmap_pages<<PAGE_SHIFT);
+ bootmap_pages<<PAGE_SHIFT, BOOTMEM_DEFAULT);
#ifdef CONFIG_ACPI_NUMA
srat_reserve_add_area(nodeid);
#endif
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c
index 398f3a578dd..75f1b109aae 100644
--- a/arch/x86/mm/pageattr-test.c
+++ b/arch/x86/mm/pageattr-test.c
@@ -5,6 +5,7 @@
* and compares page tables forwards and afterwards.
*/
#include <linux/bootmem.h>
+#include <linux/kthread.h>
#include <linux/random.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -14,8 +15,13 @@
#include <asm/pgtable.h>
#include <asm/kdebug.h>
+/*
+ * Only print the results of the first pass:
+ */
+static __read_mostly int print = 1;
+
enum {
- NTEST = 4000,
+ NTEST = 400,
#ifdef CONFIG_X86_64
LPS = (1 << PMD_SHIFT),
#elif defined(CONFIG_X86_PAE)
@@ -31,10 +37,9 @@ struct split_state {
long min_exec, max_exec;
};
-static __init int print_split(struct split_state *s)
+static int print_split(struct split_state *s)
{
long i, expected, missed = 0;
- int printed = 0;
int err = 0;
s->lpg = s->gpg = s->spg = s->exec = 0;
@@ -47,12 +52,6 @@ static __init int print_split(struct split_state *s)
pte = lookup_address(addr, &level);
if (!pte) {
- if (!printed) {
- dump_pagetable(addr);
- printk(KERN_INFO "CPA %lx no pte level %d\n",
- addr, level);
- printed = 1;
- }
missed++;
i++;
continue;
@@ -82,10 +81,13 @@ static __init int print_split(struct split_state *s)
s->max_exec = addr;
}
}
- printk(KERN_INFO
- "CPA mapping 4k %lu large %lu gb %lu x %lu[%lx-%lx] miss %lu\n",
- s->spg, s->lpg, s->gpg, s->exec,
- s->min_exec != ~0UL ? s->min_exec : 0, s->max_exec, missed);
+ if (print) {
+ printk(KERN_INFO
+ " 4k %lu large %lu gb %lu x %lu[%lx-%lx] miss %lu\n",
+ s->spg, s->lpg, s->gpg, s->exec,
+ s->min_exec != ~0UL ? s->min_exec : 0,
+ s->max_exec, missed);
+ }
expected = (s->gpg*GPS + s->lpg*LPS)/PAGE_SIZE + s->spg + missed;
if (expected != i) {
@@ -96,11 +98,11 @@ static __init int print_split(struct split_state *s)
return err;
}
-static unsigned long __initdata addr[NTEST];
-static unsigned int __initdata len[NTEST];
+static unsigned long addr[NTEST];
+static unsigned int len[NTEST];
/* Change the global bit on random pages in the direct mapping */
-static __init int exercise_pageattr(void)
+static int pageattr_test(void)
{
struct split_state sa, sb, sc;
unsigned long *bm;
@@ -110,7 +112,8 @@ static __init int exercise_pageattr(void)
int i, k;
int err;
- printk(KERN_INFO "CPA exercising pageattr\n");
+ if (print)
+ printk(KERN_INFO "CPA self-test:\n");
bm = vmalloc((max_pfn_mapped + 7) / 8);
if (!bm) {
@@ -186,7 +189,6 @@ static __init int exercise_pageattr(void)
failed += print_split(&sb);
- printk(KERN_INFO "CPA reverting everything\n");
for (i = 0; i < NTEST; i++) {
if (!addr[i])
continue;
@@ -214,12 +216,40 @@ static __init int exercise_pageattr(void)
failed += print_split(&sc);
if (failed) {
- printk(KERN_ERR "CPA selftests NOT PASSED. Please report.\n");
+ printk(KERN_ERR "NOT PASSED. Please report.\n");
WARN_ON(1);
+ return -EINVAL;
} else {
- printk(KERN_INFO "CPA selftests PASSED\n");
+ if (print)
+ printk(KERN_INFO "ok.\n");
+ }
+
+ return 0;
+}
+
+static int do_pageattr_test(void *__unused)
+{
+ while (!kthread_should_stop()) {
+ schedule_timeout_interruptible(HZ*30);
+ if (pageattr_test() < 0)
+ break;
+ if (print)
+ print--;
}
+ return 0;
+}
+
+static int start_pageattr_test(void)
+{
+ struct task_struct *p;
+
+ p = kthread_create(do_pageattr_test, NULL, "pageattr-test");
+ if (!IS_ERR(p))
+ wake_up_process(p);
+ else
+ WARN_ON(1);
return 0;
}
-module_init(exercise_pageattr);
+
+module_init(start_pageattr_test);
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index bb55a78dcd6..4119379f80f 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -8,6 +8,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/mm.h>
+#include <linux/interrupt.h>
#include <asm/e820.h>
#include <asm/processor.h>
@@ -167,8 +168,6 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address)
if (within(address, virt_to_highmap(_text), virt_to_highmap(_etext)))
pgprot_val(forbidden) |= _PAGE_NX;
-
-#ifdef CONFIG_DEBUG_RODATA
/* The .rodata section needs to be read-only */
if (within(address, (unsigned long)__start_rodata,
(unsigned long)__end_rodata))
@@ -179,7 +178,6 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address)
if (within(address, virt_to_highmap(__start_rodata),
virt_to_highmap(__end_rodata)))
pgprot_val(forbidden) |= _PAGE_RW;
-#endif
prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
@@ -194,7 +192,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address)
* or when the present bit is not set. Otherwise we would return a
* pointer to a nonexisting mapping.
*/
-pte_t *lookup_address(unsigned long address, int *level)
+pte_t *lookup_address(unsigned long address, unsigned int *level)
{
pgd_t *pgd = pgd_offset_k(address);
pud_t *pud;
@@ -237,7 +235,6 @@ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
if (!SHARED_KERNEL_PMD) {
struct page *page;
- address = __pa(address);
list_for_each_entry(page, &pgd_list, lru) {
pgd_t *pgd;
pud_t *pud;
@@ -256,21 +253,11 @@ static int
try_preserve_large_page(pte_t *kpte, unsigned long address,
struct cpa_data *cpa)
{
- unsigned long nextpage_addr, numpages, pmask, psize, flags;
+ unsigned long nextpage_addr, numpages, pmask, psize, flags, addr;
pte_t new_pte, old_pte, *tmp;
pgprot_t old_prot, new_prot;
- int level, do_split = 1;
-
- /*
- * An Athlon 64 X2 showed hard hangs if we tried to preserve
- * largepages and changed the PSE entry from RW to RO.
- *
- * As AMD CPUs have a long series of erratas in this area,
- * (and none of the known ones seem to explain this hang),
- * disable this code until the hang can be debugged:
- */
- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
- return 1;
+ int i, do_split = 1;
+ unsigned int level;
spin_lock_irqsave(&pgd_lock, flags);
/*
@@ -288,8 +275,8 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
break;
#ifdef CONFIG_X86_64
case PG_LEVEL_1G:
- psize = PMD_PAGE_SIZE;
- pmask = PMD_PAGE_MASK;
+ psize = PUD_PAGE_SIZE;
+ pmask = PUD_PAGE_MASK;
break;
#endif
default:
@@ -317,6 +304,19 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
new_prot = static_protections(new_prot, address);
/*
+ * We need to check the full range, whether
+ * static_protection() requires a different pgprot for one of
+ * the pages in the range we try to preserve:
+ */
+ addr = address + PAGE_SIZE;
+ for (i = 1; i < cpa->numpages; i++, addr += PAGE_SIZE) {
+ pgprot_t chk_prot = static_protections(new_prot, addr);
+
+ if (pgprot_val(chk_prot) != pgprot_val(new_prot))
+ goto out_unlock;
+ }
+
+ /*
* If there are no changes, return. maxpages has been updated
* above:
*/
@@ -350,23 +350,103 @@ out_unlock:
return do_split;
}
+static LIST_HEAD(page_pool);
+static unsigned long pool_size, pool_pages, pool_low;
+static unsigned long pool_used, pool_failed, pool_refill;
+
+static void cpa_fill_pool(void)
+{
+ struct page *p;
+ gfp_t gfp = GFP_KERNEL;
+
+ /* Do not allocate from interrupt context */
+ if (in_irq() || irqs_disabled())
+ return;
+ /*
+ * Check unlocked. I does not matter when we have one more
+ * page in the pool. The bit lock avoids recursive pool
+ * allocations:
+ */
+ if (pool_pages >= pool_size || test_and_set_bit_lock(0, &pool_refill))
+ return;
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ /*
+ * We could do:
+ * gfp = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
+ * but this fails on !PREEMPT kernels
+ */
+ gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
+#endif
+
+ while (pool_pages < pool_size) {
+ p = alloc_pages(gfp, 0);
+ if (!p) {
+ pool_failed++;
+ break;
+ }
+ spin_lock_irq(&pgd_lock);
+ list_add(&p->lru, &page_pool);
+ pool_pages++;
+ spin_unlock_irq(&pgd_lock);
+ }
+ clear_bit_unlock(0, &pool_refill);
+}
+
+#define SHIFT_MB (20 - PAGE_SHIFT)
+#define ROUND_MB_GB ((1 << 10) - 1)
+#define SHIFT_MB_GB 10
+#define POOL_PAGES_PER_GB 16
+
+void __init cpa_init(void)
+{
+ struct sysinfo si;
+ unsigned long gb;
+
+ si_meminfo(&si);
+ /*
+ * Calculate the number of pool pages:
+ *
+ * Convert totalram (nr of pages) to MiB and round to the next
+ * GiB. Shift MiB to Gib and multiply the result by
+ * POOL_PAGES_PER_GB:
+ */
+ gb = ((si.totalram >> SHIFT_MB) + ROUND_MB_GB) >> SHIFT_MB_GB;
+ pool_size = POOL_PAGES_PER_GB * gb;
+ pool_low = pool_size;
+
+ cpa_fill_pool();
+ printk(KERN_DEBUG
+ "CPA: page pool initialized %lu of %lu pages preallocated\n",
+ pool_pages, pool_size);
+}
+
static int split_large_page(pte_t *kpte, unsigned long address)
{
unsigned long flags, pfn, pfninc = 1;
- gfp_t gfp_flags = GFP_KERNEL;
unsigned int i, level;
pte_t *pbase, *tmp;
pgprot_t ref_prot;
struct page *base;
-#ifdef CONFIG_DEBUG_PAGEALLOC
- gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
-#endif
- base = alloc_pages(gfp_flags, 0);
- if (!base)
+ /*
+ * Get a page from the pool. The pool list is protected by the
+ * pgd_lock, which we have to take anyway for the split
+ * operation:
+ */
+ spin_lock_irqsave(&pgd_lock, flags);
+ if (list_empty(&page_pool)) {
+ spin_unlock_irqrestore(&pgd_lock, flags);
return -ENOMEM;
+ }
+
+ base = list_first_entry(&page_pool, struct page, lru);
+ list_del(&base->lru);
+ pool_pages--;
+
+ if (pool_pages < pool_low)
+ pool_low = pool_pages;
- spin_lock_irqsave(&pgd_lock, flags);
/*
* Check for races, another CPU might have split this page
* up for us already:
@@ -411,17 +491,24 @@ static int split_large_page(pte_t *kpte, unsigned long address)
base = NULL;
out_unlock:
+ /*
+ * If we dropped out via the lookup_address check under
+ * pgd_lock then stick the page back into the pool:
+ */
+ if (base) {
+ list_add(&base->lru, &page_pool);
+ pool_pages++;
+ } else
+ pool_used++;
spin_unlock_irqrestore(&pgd_lock, flags);
- if (base)
- __free_pages(base, 0);
-
return 0;
}
static int __change_page_attr(unsigned long address, struct cpa_data *cpa)
{
- int level, do_split, err;
+ int do_split, err;
+ unsigned int level;
struct page *kpte_page;
pte_t *kpte;
@@ -601,6 +688,15 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
if (!pgprot_val(mask_set) && !pgprot_val(mask_clr))
return 0;
+ /* Ensure we are PAGE_SIZE aligned */
+ if (addr & ~PAGE_MASK) {
+ addr &= PAGE_MASK;
+ /*
+ * People should not be passing in unaligned addresses:
+ */
+ WARN_ON_ONCE(1);
+ }
+
cpa.vaddr = addr;
cpa.numpages = numpages;
cpa.mask_set = mask_set;
@@ -613,7 +709,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
* Check whether we really changed something:
*/
if (!cpa.flushtlb)
- return ret;
+ goto out;
/*
* No need to flush, when we did not set any of the caching
@@ -632,6 +728,8 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
else
cpa_flush_all(cache);
+out:
+ cpa_fill_pool();
return ret;
}
@@ -772,8 +870,12 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
return;
/*
- * The return value is ignored - the calls cannot fail,
- * large pages are disabled at boot time:
+ * The return value is ignored as the calls cannot fail.
+ * Large pages are kept enabled at boot time, and are
+ * split up quickly with DEBUG_PAGEALLOC. If a splitup
+ * fails here (due to temporary memory shortage) no damage
+ * is done because we just keep the largepage intact up
+ * to the next attempt when it will likely be split up:
*/
if (enable)
__set_pages_p(page, numpages);
@@ -785,6 +887,12 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
* but that can deadlock->flush only current cpu:
*/
__flush_tlb_all();
+
+ /*
+ * Try to refill the page pool here. We can do this only after
+ * the tlb flush.
+ */
+ cpa_fill_pool();
}
#endif
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c
index c7db504be1e..73aba712520 100644
--- a/arch/x86/mm/pgtable_32.c
+++ b/arch/x86/mm/pgtable_32.c
@@ -183,7 +183,7 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
return (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
}
-struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *pte;
@@ -192,6 +192,8 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
#else
pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
#endif
+ if (pte)
+ pgtable_page_ctor(pte);
return pte;
}
@@ -272,7 +274,7 @@ static void pgd_dtor(void *pgd)
* preallocate which never got a corresponding vma will need to be
* freed manually.
*/
-static void pgd_mop_up_pmds(pgd_t *pgdp)
+static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
{
int i;
@@ -285,7 +287,7 @@ static void pgd_mop_up_pmds(pgd_t *pgdp)
pgdp[i] = native_make_pgd(0);
paravirt_release_pd(pgd_val(pgd) >> PAGE_SHIFT);
- pmd_free(pmd);
+ pmd_free(mm, pmd);
}
}
}
@@ -313,7 +315,7 @@ static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
pmd_t *pmd = pmd_alloc_one(mm, addr);
if (!pmd) {
- pgd_mop_up_pmds(pgd);
+ pgd_mop_up_pmds(mm, pgd);
return 0;
}
@@ -333,7 +335,7 @@ static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
return 1;
}
-static void pgd_mop_up_pmds(pgd_t *pgd)
+static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
{
}
#endif /* CONFIG_X86_PAE */
@@ -352,9 +354,9 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
return pgd;
}
-void pgd_free(pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
- pgd_mop_up_pmds(pgd);
+ pgd_mop_up_pmds(mm, pgd);
quicklist_free(0, pgd_dtor, pgd);
}
@@ -365,6 +367,7 @@ void check_pgt_cache(void)
void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
{
+ pgtable_page_dtor(pte);
paravirt_release_pt(page_to_pfn(pte));
tlb_remove_page(tlb, pte);
}
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index 65416f843e5..ecd91ea8a8a 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -488,7 +488,8 @@ void __init srat_reserve_add_area(int nodeid)
printk(KERN_INFO "SRAT: This will cost you %Lu MB of "
"pre-allocated memory.\n", (unsigned long long)total_mb);
reserve_bootmem_node(NODE_DATA(nodeid), nodes_add[nodeid].start,
- nodes_add[nodeid].end - nodes_add[nodeid].start);
+ nodes_add[nodeid].end - nodes_add[nodeid].start,
+ BOOTMEM_DEFAULT);
}
}
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 52deabc72a6..b7c67a187b6 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -26,16 +26,37 @@ int pcibios_last_bus = -1;
unsigned long pirq_table_addr;
struct pci_bus *pci_root_bus;
struct pci_raw_ops *raw_pci_ops;
+struct pci_raw_ops *raw_pci_ext_ops;
+
+int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 *val)
+{
+ if (reg < 256 && raw_pci_ops)
+ return raw_pci_ops->read(domain, bus, devfn, reg, len, val);
+ if (raw_pci_ext_ops)
+ return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val);
+ return -EINVAL;
+}
+
+int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 val)
+{
+ if (reg < 256 && raw_pci_ops)
+ return raw_pci_ops->write(domain, bus, devfn, reg, len, val);
+ if (raw_pci_ext_ops)
+ return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val);
+ return -EINVAL;
+}
static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
{
- return raw_pci_ops->read(pci_domain_nr(bus), bus->number,
+ return raw_pci_read(pci_domain_nr(bus), bus->number,
devfn, where, size, value);
}
static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
{
- return raw_pci_ops->write(pci_domain_nr(bus), bus->number,
+ return raw_pci_write(pci_domain_nr(bus), bus->number,
devfn, where, size, value);
}
diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c
index 431c9a51b15..42f3e4cad17 100644
--- a/arch/x86/pci/direct.c
+++ b/arch/x86/pci/direct.c
@@ -14,7 +14,7 @@
#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
(0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
-int pci_conf1_read(unsigned int seg, unsigned int bus,
+static int pci_conf1_read(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 *value)
{
unsigned long flags;
@@ -45,7 +45,7 @@ int pci_conf1_read(unsigned int seg, unsigned int bus,
return 0;
}
-int pci_conf1_write(unsigned int seg, unsigned int bus,
+static int pci_conf1_write(unsigned int seg, unsigned int bus,
unsigned int devfn, int reg, int len, u32 value)
{
unsigned long flags;
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 74d30ff33c4..a5ef5f55137 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -215,7 +215,8 @@ static int quirk_aspm_offset[MAX_PCIEROOT << 3];
static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
{
- return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
+ return raw_pci_read(pci_domain_nr(bus), bus->number,
+ devfn, where, size, value);
}
/*
@@ -231,7 +232,8 @@ static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int wh
if ((offset) && (where == offset))
value = value & 0xfffffffc;
- return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
+ return raw_pci_write(pci_domain_nr(bus), bus->number,
+ devfn, where, size, value);
}
static struct pci_ops quirk_pcie_aspm_ops = {
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 42ba0e2da1a..103b9dff121 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -72,7 +72,7 @@ pcibios_align_resource(void *data, struct resource *res,
}
}
}
-
+EXPORT_SYMBOL(pcibios_align_resource);
/*
* Handle resources of PCI devices. If the world were perfect, we could
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index 5565d7016b7..e041ced0ce1 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -22,7 +22,7 @@ static void __devinit pcibios_fixup_peer_bridges(void)
if (pci_find_bus(0, n))
continue;
for (devfn = 0; devfn < 256; devfn += 8) {
- if (!raw_pci_ops->read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
+ if (!raw_pci_read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
l != 0x0000 && l != 0xffff) {
DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l);
printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 4df637e34f8..8d54df4dfaa 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -22,46 +22,13 @@
#define MMCONFIG_APER_MIN (2 * 1024*1024)
#define MMCONFIG_APER_MAX (256 * 1024*1024)
-DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
-
/* Indicate if the mmcfg resources have been placed into the resource table. */
static int __initdata pci_mmcfg_resources_inserted;
-/* K8 systems have some devices (typically in the builtin northbridge)
- that are only accessible using type1
- Normally this can be expressed in the MCFG by not listing them
- and assigning suitable _SEGs, but this isn't implemented in some BIOS.
- Instead try to discover all devices on bus 0 that are unreachable using MM
- and fallback for them. */
-static void __init unreachable_devices(void)
-{
- int i, bus;
- /* Use the max bus number from ACPI here? */
- for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
- for (i = 0; i < 32; i++) {
- unsigned int devfn = PCI_DEVFN(i, 0);
- u32 val1, val2;
-
- pci_conf1_read(0, bus, devfn, 0, 4, &val1);
- if (val1 == 0xffffffff)
- continue;
-
- if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
- raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
- if (val1 == val2)
- continue;
- }
- set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
- printk(KERN_NOTICE "PCI: No mmconfig possible on device"
- " %02x:%02x\n", bus, i);
- }
- }
-}
-
static const char __init *pci_mmcfg_e7520(void)
{
u32 win;
- pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
+ pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
win = win & 0xf000;
if(win == 0x0000 || win == 0xf000)
@@ -86,7 +53,7 @@ static const char __init *pci_mmcfg_intel_945(void)
pci_mmcfg_config_num = 1;
- pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
+ pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
/* Enable bit */
if (!(pciexbar & 1))
@@ -151,7 +118,7 @@ static int __init pci_mmcfg_check_hostbridge(void)
int i;
const char *name;
- pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
+ pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
vendor = l & 0xffff;
device = (l >> 16) & 0xffff;
@@ -270,8 +237,6 @@ void __init pci_mmcfg_init(int type)
return;
if (pci_mmcfg_arch_init()) {
- if (type == 1)
- unreachable_devices();
if (known_bridge)
pci_mmcfg_insert_resources(IORESOURCE_BUSY);
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c
index 1bf5816d34c..081816ada05 100644
--- a/arch/x86/pci/mmconfig_32.c
+++ b/arch/x86/pci/mmconfig_32.c
@@ -30,10 +30,6 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
struct acpi_mcfg_allocation *cfg;
int cfg_num;
- if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
- test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots))
- return 0;
-
for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
cfg = &pci_mmcfg_config[cfg_num];
if (cfg->pci_segment == seg &&
@@ -68,13 +64,13 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
u32 base;
if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
- *value = -1;
+err: *value = -1;
return -EINVAL;
}
base = get_base_addr(seg, bus, devfn);
if (!base)
- return pci_conf1_read(seg,bus,devfn,reg,len,value);
+ goto err;
spin_lock_irqsave(&pci_config_lock, flags);
@@ -107,7 +103,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
base = get_base_addr(seg, bus, devfn);
if (!base)
- return pci_conf1_write(seg,bus,devfn,reg,len,value);
+ return -EINVAL;
spin_lock_irqsave(&pci_config_lock, flags);
@@ -134,15 +130,9 @@ static struct pci_raw_ops pci_mmcfg = {
.write = pci_mmcfg_write,
};
-int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
- unsigned int devfn)
-{
- return get_base_addr(seg, bus, devfn) != 0;
-}
-
int __init pci_mmcfg_arch_init(void)
{
- printk(KERN_INFO "PCI: Using MMCONFIG\n");
- raw_pci_ops = &pci_mmcfg;
+ printk(KERN_INFO "PCI: Using MMCONFIG for extended config space\n");
+ raw_pci_ext_ops = &pci_mmcfg;
return 1;
}
diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c
index 4095e4d66a1..9207fd49233 100644
--- a/arch/x86/pci/mmconfig_64.c
+++ b/arch/x86/pci/mmconfig_64.c
@@ -40,9 +40,7 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
{
char __iomem *addr;
- if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
- test_bit(32*bus + PCI_SLOT(devfn), pci_mmcfg_fallback_slots))
- return NULL;
+
addr = get_virt(seg, bus);
if (!addr)
return NULL;
@@ -56,13 +54,13 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
- *value = -1;
+err: *value = -1;
return -EINVAL;
}
addr = pci_dev_base(seg, bus, devfn);
if (!addr)
- return pci_conf1_read(seg,bus,devfn,reg,len,value);
+ goto err;
switch (len) {
case 1:
@@ -90,7 +88,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
addr = pci_dev_base(seg, bus, devfn);
if (!addr)
- return pci_conf1_write(seg,bus,devfn,reg,len,value);
+ return -EINVAL;
switch (len) {
case 1:
@@ -126,12 +124,6 @@ static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
return addr;
}
-int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
- unsigned int devfn)
-{
- return pci_dev_base(seg, bus, devfn) != NULL;
-}
-
int __init pci_mmcfg_arch_init(void)
{
int i;
@@ -152,6 +144,6 @@ int __init pci_mmcfg_arch_init(void)
return 0;
}
}
- raw_pci_ops = &pci_mmcfg;
+ raw_pci_ext_ops = &pci_mmcfg;
return 1;
}
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
index ac56d3916c5..3431518d921 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/pci/pci.h
@@ -85,10 +85,17 @@ extern spinlock_t pci_config_lock;
extern int (*pcibios_enable_irq)(struct pci_dev *dev);
extern void (*pcibios_disable_irq)(struct pci_dev *dev);
-extern int pci_conf1_write(unsigned int seg, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 value);
-extern int pci_conf1_read(unsigned int seg, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 *value);
+struct pci_raw_ops {
+ int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 *val);
+ int (*write)(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 val);
+};
+
+extern struct pci_raw_ops *raw_pci_ops;
+extern struct pci_raw_ops *raw_pci_ext_ops;
+
+extern struct pci_raw_ops pci_direct_conf1;
extern int pci_direct_probe(void);
extern void pci_direct_init(int type);
@@ -98,13 +105,6 @@ extern void pcibios_sort(void);
/* pci-mmconfig.c */
-/* Verify the first 16 busses. We assume that systems with more busses
- get MCFG right. */
-#define PCI_MMCFG_MAX_CHECK_BUS 16
-extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
-
-extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
- unsigned int devfn);
extern int __init pci_mmcfg_arch_init(void);
/*
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c
index 8ecb1c72259..c2df4e97eed 100644
--- a/arch/x86/pci/visws.c
+++ b/arch/x86/pci/visws.c
@@ -13,9 +13,6 @@
#include "pci.h"
-
-extern struct pci_raw_ops pci_direct_conf1;
-
static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
static void pci_visws_disable_irq(struct pci_dev *dev) { }
diff --git a/arch/x86/power/Makefile b/arch/x86/power/Makefile
index d764ec95006..9ff4d5b55ad 100644
--- a/arch/x86/power/Makefile
+++ b/arch/x86/power/Makefile
@@ -1,2 +1,2 @@
-obj-$(CONFIG_PM) += cpu.o
-obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o
+obj-$(CONFIG_PM_SLEEP) += cpu_$(BITS).o
+obj-$(CONFIG_HIBERNATION) += hibernate_$(BITS).o hibernate_asm_$(BITS).o
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu_32.c
index efcf620d143..7f9c6da04a4 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu_32.c
@@ -40,7 +40,7 @@ static void __save_processor_state(struct saved_context *ctxt)
savesegment(ss, ctxt->ss);
/*
- * control registers
+ * control registers
*/
ctxt->cr0 = read_cr0();
ctxt->cr2 = read_cr2();
diff --git a/arch/x86/kernel/suspend_64.c b/arch/x86/power/cpu_64.c
index 7ac7130022f..66bdfb591fd 100644
--- a/arch/x86/kernel/suspend_64.c
+++ b/arch/x86/power/cpu_64.c
@@ -1,8 +1,9 @@
/*
- * Suspend support specific for i386.
+ * Suspend and hibernation support for x86-64
*
* Distribute under GPLv2
*
+ * Copyright (c) 2007 Rafael J. Wysocki <rjw@sisk.pl>
* Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
* Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
*/
@@ -14,9 +15,6 @@
#include <asm/pgtable.h>
#include <asm/mtrr.h>
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
static void fix_processor_context(void);
struct saved_context saved_context;
@@ -63,7 +61,7 @@ static void __save_processor_state(struct saved_context *ctxt)
mtrr_save_fixed_ranges(NULL);
/*
- * control registers
+ * control registers
*/
rdmsrl(MSR_EFER, ctxt->efer);
ctxt->cr0 = read_cr0();
@@ -166,155 +164,3 @@ static void fix_processor_context(void)
loaddebug(&current->thread, 7);
}
}
-
-#ifdef CONFIG_HIBERNATION
-/* Defined in arch/x86_64/kernel/suspend_asm.S */
-extern int restore_image(void);
-
-/*
- * Address to jump to in the last phase of restore in order to get to the image
- * kernel's text (this value is passed in the image header).
- */
-unsigned long restore_jump_address;
-
-/*
- * Value of the cr3 register from before the hibernation (this value is passed
- * in the image header).
- */
-unsigned long restore_cr3;
-
-pgd_t *temp_level4_pgt;
-
-void *relocated_restore_code;
-
-static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
-{
- long i, j;
-
- i = pud_index(address);
- pud = pud + i;
- for (; i < PTRS_PER_PUD; pud++, i++) {
- unsigned long paddr;
- pmd_t *pmd;
-
- paddr = address + i*PUD_SIZE;
- if (paddr >= end)
- break;
-
- pmd = (pmd_t *)get_safe_page(GFP_ATOMIC);
- if (!pmd)
- return -ENOMEM;
- set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
- for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) {
- unsigned long pe;
-
- if (paddr >= end)
- break;
- pe = __PAGE_KERNEL_LARGE_EXEC | paddr;
- pe &= __supported_pte_mask;
- set_pmd(pmd, __pmd(pe));
- }
- }
- return 0;
-}
-
-static int set_up_temporary_mappings(void)
-{
- unsigned long start, end, next;
- int error;
-
- temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC);
- if (!temp_level4_pgt)
- return -ENOMEM;
-
- /* It is safe to reuse the original kernel mapping */
- set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map),
- init_level4_pgt[pgd_index(__START_KERNEL_map)]);
-
- /* Set up the direct mapping from scratch */
- start = (unsigned long)pfn_to_kaddr(0);
- end = (unsigned long)pfn_to_kaddr(end_pfn);
-
- for (; start < end; start = next) {
- pud_t *pud = (pud_t *)get_safe_page(GFP_ATOMIC);
- if (!pud)
- return -ENOMEM;
- next = start + PGDIR_SIZE;
- if (next > end)
- next = end;
- if ((error = res_phys_pud_init(pud, __pa(start), __pa(next))))
- return error;
- set_pgd(temp_level4_pgt + pgd_index(start),
- mk_kernel_pgd(__pa(pud)));
- }
- return 0;
-}
-
-int swsusp_arch_resume(void)
-{
- int error;
-
- /* We have got enough memory and from now on we cannot recover */
- if ((error = set_up_temporary_mappings()))
- return error;
-
- relocated_restore_code = (void *)get_safe_page(GFP_ATOMIC);
- if (!relocated_restore_code)
- return -ENOMEM;
- memcpy(relocated_restore_code, &core_restore_code,
- &restore_registers - &core_restore_code);
-
- restore_image();
- return 0;
-}
-
-/*
- * pfn_is_nosave - check if given pfn is in the 'nosave' section
- */
-
-int pfn_is_nosave(unsigned long pfn)
-{
- unsigned long nosave_begin_pfn = __pa_symbol(&__nosave_begin) >> PAGE_SHIFT;
- unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT;
- return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
-}
-
-struct restore_data_record {
- unsigned long jump_address;
- unsigned long cr3;
- unsigned long magic;
-};
-
-#define RESTORE_MAGIC 0x0123456789ABCDEFUL
-
-/**
- * arch_hibernation_header_save - populate the architecture specific part
- * of a hibernation image header
- * @addr: address to save the data at
- */
-int arch_hibernation_header_save(void *addr, unsigned int max_size)
-{
- struct restore_data_record *rdr = addr;
-
- if (max_size < sizeof(struct restore_data_record))
- return -EOVERFLOW;
- rdr->jump_address = restore_jump_address;
- rdr->cr3 = restore_cr3;
- rdr->magic = RESTORE_MAGIC;
- return 0;
-}
-
-/**
- * arch_hibernation_header_restore - read the architecture specific data
- * from the hibernation image header
- * @addr: address to read the data from
- */
-int arch_hibernation_header_restore(void *addr)
-{
- struct restore_data_record *rdr = addr;
-
- restore_jump_address = rdr->jump_address;
- restore_cr3 = rdr->cr3;
- return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL;
-}
-#endif /* CONFIG_HIBERNATION */
diff --git a/arch/x86/power/suspend.c b/arch/x86/power/hibernate_32.c
index a0020b913f3..f2b6e3f11bf 100644
--- a/arch/x86/power/suspend.c
+++ b/arch/x86/power/hibernate_32.c
@@ -1,5 +1,5 @@
/*
- * Suspend support specific for i386 - temporary page tables
+ * Hibernation support specific for i386 - temporary page tables
*
* Distribute under GPLv2
*
@@ -13,7 +13,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
-/* Defined in arch/i386/power/swsusp.S */
+/* Defined in hibernate_asm_32.S */
extern int restore_image(void);
/* References to section boundaries */
@@ -23,7 +23,7 @@ extern const void __nosave_begin, __nosave_end;
pgd_t *resume_pg_dir;
/* The following three functions are based on the analogous code in
- * arch/i386/mm/init.c
+ * arch/x86/mm/init_32.c
*/
/*
diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c
new file mode 100644
index 00000000000..b542355e0e3
--- /dev/null
+++ b/arch/x86/power/hibernate_64.c
@@ -0,0 +1,169 @@
+/*
+ * Hibernation support for x86-64
+ *
+ * Distribute under GPLv2
+ *
+ * Copyright (c) 2007 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
+ * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
+ */
+
+#include <linux/smp.h>
+#include <linux/suspend.h>
+#include <asm/proto.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mtrr.h>
+
+/* References to section boundaries */
+extern const void __nosave_begin, __nosave_end;
+
+/* Defined in hibernate_asm_64.S */
+extern int restore_image(void);
+
+/*
+ * Address to jump to in the last phase of restore in order to get to the image
+ * kernel's text (this value is passed in the image header).
+ */
+unsigned long restore_jump_address;
+
+/*
+ * Value of the cr3 register from before the hibernation (this value is passed
+ * in the image header).
+ */
+unsigned long restore_cr3;
+
+pgd_t *temp_level4_pgt;
+
+void *relocated_restore_code;
+
+static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
+{
+ long i, j;
+
+ i = pud_index(address);
+ pud = pud + i;
+ for (; i < PTRS_PER_PUD; pud++, i++) {
+ unsigned long paddr;
+ pmd_t *pmd;
+
+ paddr = address + i*PUD_SIZE;
+ if (paddr >= end)
+ break;
+
+ pmd = (pmd_t *)get_safe_page(GFP_ATOMIC);
+ if (!pmd)
+ return -ENOMEM;
+ set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
+ for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) {
+ unsigned long pe;
+
+ if (paddr >= end)
+ break;
+ pe = __PAGE_KERNEL_LARGE_EXEC | paddr;
+ pe &= __supported_pte_mask;
+ set_pmd(pmd, __pmd(pe));
+ }
+ }
+ return 0;
+}
+
+static int set_up_temporary_mappings(void)
+{
+ unsigned long start, end, next;
+ int error;
+
+ temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC);
+ if (!temp_level4_pgt)
+ return -ENOMEM;
+
+ /* It is safe to reuse the original kernel mapping */
+ set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map),
+ init_level4_pgt[pgd_index(__START_KERNEL_map)]);
+
+ /* Set up the direct mapping from scratch */
+ start = (unsigned long)pfn_to_kaddr(0);
+ end = (unsigned long)pfn_to_kaddr(end_pfn);
+
+ for (; start < end; start = next) {
+ pud_t *pud = (pud_t *)get_safe_page(GFP_ATOMIC);
+ if (!pud)
+ return -ENOMEM;
+ next = start + PGDIR_SIZE;
+ if (next > end)
+ next = end;
+ if ((error = res_phys_pud_init(pud, __pa(start), __pa(next))))
+ return error;
+ set_pgd(temp_level4_pgt + pgd_index(start),
+ mk_kernel_pgd(__pa(pud)));
+ }
+ return 0;
+}
+
+int swsusp_arch_resume(void)
+{
+ int error;
+
+ /* We have got enough memory and from now on we cannot recover */
+ if ((error = set_up_temporary_mappings()))
+ return error;
+
+ relocated_restore_code = (void *)get_safe_page(GFP_ATOMIC);
+ if (!relocated_restore_code)
+ return -ENOMEM;
+ memcpy(relocated_restore_code, &core_restore_code,
+ &restore_registers - &core_restore_code);
+
+ restore_image();
+ return 0;
+}
+
+/*
+ * pfn_is_nosave - check if given pfn is in the 'nosave' section
+ */
+
+int pfn_is_nosave(unsigned long pfn)
+{
+ unsigned long nosave_begin_pfn = __pa_symbol(&__nosave_begin) >> PAGE_SHIFT;
+ unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT;
+ return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
+}
+
+struct restore_data_record {
+ unsigned long jump_address;
+ unsigned long cr3;
+ unsigned long magic;
+};
+
+#define RESTORE_MAGIC 0x0123456789ABCDEFUL
+
+/**
+ * arch_hibernation_header_save - populate the architecture specific part
+ * of a hibernation image header
+ * @addr: address to save the data at
+ */
+int arch_hibernation_header_save(void *addr, unsigned int max_size)
+{
+ struct restore_data_record *rdr = addr;
+
+ if (max_size < sizeof(struct restore_data_record))
+ return -EOVERFLOW;
+ rdr->jump_address = restore_jump_address;
+ rdr->cr3 = restore_cr3;
+ rdr->magic = RESTORE_MAGIC;
+ return 0;
+}
+
+/**
+ * arch_hibernation_header_restore - read the architecture specific data
+ * from the hibernation image header
+ * @addr: address to read the data from
+ */
+int arch_hibernation_header_restore(void *addr)
+{
+ struct restore_data_record *rdr = addr;
+
+ restore_jump_address = rdr->jump_address;
+ restore_cr3 = rdr->cr3;
+ return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL;
+}
diff --git a/arch/x86/power/swsusp.S b/arch/x86/power/hibernate_asm_32.S
index 53662e05b39..b95aa6cfe3c 100644
--- a/arch/x86/power/swsusp.S
+++ b/arch/x86/power/hibernate_asm_32.S
@@ -1,7 +1,6 @@
.text
-/* Originally gcc generated, modified by hand
- *
+/*
* This may not use any stack, nor any variable that is not "NoSave":
*
* Its rewriting one kernel image with another. What is stack in "old"
diff --git a/arch/x86/kernel/suspend_asm_64.S b/arch/x86/power/hibernate_asm_64.S
index aeb9a4d7681..1deb3244b99 100644
--- a/arch/x86/kernel/suspend_asm_64.S
+++ b/arch/x86/power/hibernate_asm_64.S
@@ -1,7 +1,12 @@
-/* Copyright 2004,2005 Pavel Machek <pavel@suse.cz>, Andi Kleen <ak@suse.de>, Rafael J. Wysocki <rjw@sisk.pl>
+/*
+ * Hibernation support for x86-64
*
* Distribute under GPLv2.
*
+ * Copyright 2007 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright 2005 Andi Kleen <ak@suse.de>
+ * Copyright 2004 Pavel Machek <pavel@suse.cz>
+ *
* swsusp_arch_resume must not use any stack or any nonlocal variables while
* copying pages:
*
@@ -9,7 +14,7 @@
* image could very well be data page in "new" image, and overwriting
* your own stack under you is bad idea.
*/
-
+
.text
#include <linux/linkage.h>
#include <asm/segment.h>
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
index d28dda57470..f385a4b4a48 100644
--- a/arch/x86/vdso/Makefile
+++ b/arch/x86/vdso/Makefile
@@ -7,7 +7,7 @@ VDSO32-$(CONFIG_X86_32) := y
VDSO32-$(CONFIG_COMPAT) := y
vdso-install-$(VDSO64-y) += vdso.so
-vdso-install-$(VDSO32-y) += $(vdso32-y:=.so)
+vdso-install-$(VDSO32-y) += $(vdso32-images)
# files to link into the vdso
@@ -63,6 +63,8 @@ vdso32.so-$(CONFIG_X86_32) += int80
vdso32.so-$(CONFIG_COMPAT) += syscall
vdso32.so-$(VDSO32-y) += sysenter
+vdso32-images = $(vdso32.so-y:%=vdso32-%.so)
+
CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1
@@ -71,21 +73,21 @@ VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1
override obj-dirs = $(dir $(obj)) $(obj)/vdso32/
targets += vdso32/vdso32.lds
-targets += $(vdso32.so-y:%=vdso32-%.so.dbg) $(vdso32.so-y:%=vdso32-%.so)
+targets += $(vdso32-images) $(vdso32-images:=.dbg)
targets += vdso32/note.o $(vdso32.so-y:%=vdso32/%.o)
-extra-y += $(vdso32.so-y:%=vdso32-%.so)
+extra-y += $(vdso32-images)
-$(obj)/vdso32.o: $(vdso32.so-y:%=$(obj)/vdso32-%.so)
+$(obj)/vdso32.o: $(vdso32-images:%=$(obj)/%)
KBUILD_AFLAGS_32 := $(filter-out -m64,$(KBUILD_AFLAGS))
-$(vdso32.so-y:%=$(obj)/vdso32-%.so.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_32)
-$(vdso32.so-y:%=$(obj)/vdso32-%.so.dbg): asflags-$(CONFIG_X86_64) += -m32
+$(vdso32-images:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_32)
+$(vdso32-images:%=$(obj)/%.dbg): asflags-$(CONFIG_X86_64) += -m32
-$(vdso32.so-y:%=$(obj)/vdso32-%.so.dbg): $(obj)/vdso32-%.so.dbg: FORCE \
- $(obj)/vdso32/vdso32.lds \
- $(obj)/vdso32/note.o \
- $(obj)/vdso32/%.o
+$(vdso32-images:%=$(obj)/%.dbg): $(obj)/vdso32-%.so.dbg: FORCE \
+ $(obj)/vdso32/vdso32.lds \
+ $(obj)/vdso32/note.o \
+ $(obj)/vdso32/%.o
$(call if_changed,vdso)
# Make vdso32-*-syms.lds from each image, and then make sure they match.
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index de647bc6e74..49e5358f481 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -798,6 +798,10 @@ static __init void xen_pagetable_setup_start(pgd_t *base)
* added to the table can be prepared properly for Xen.
*/
xen_write_cr3(__pa(base));
+
+ /* Unpin initial Xen pagetable */
+ pin_pagetable_pfn(MMUEXT_UNPIN_TABLE,
+ PFN_DOWN(__pa(xen_start_info->pt_base)));
}
static __init void xen_pagetable_setup_done(pgd_t *base)
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 45aa771e73a..0144395448a 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -58,7 +58,7 @@
xmaddr_t arbitrary_virt_to_machine(unsigned long address)
{
- int level;
+ unsigned int level;
pte_t *pte = lookup_address(address, &level);
unsigned offset = address & PAGE_MASK;
@@ -71,7 +71,7 @@ void make_lowmem_page_readonly(void *vaddr)
{
pte_t *pte, ptev;
unsigned long address = (unsigned long)vaddr;
- int level;
+ unsigned int level;
pte = lookup_address(address, &level);
BUG_ON(pte == NULL);
@@ -86,7 +86,7 @@ void make_lowmem_page_readwrite(void *vaddr)
{
pte_t *pte, ptev;
unsigned long address = (unsigned long)vaddr;
- int level;
+ unsigned int level;
pte = lookup_address(address, &level);
BUG_ON(pte == NULL);
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index b3721fd6877..c39e1a5aa24 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -217,17 +217,17 @@ unsigned long long xen_sched_clock(void)
/* Get the CPU speed from Xen */
unsigned long xen_cpu_khz(void)
{
- u64 cpu_khz = 1000000ULL << 32;
+ u64 xen_khz = 1000000ULL << 32;
const struct vcpu_time_info *info =
&HYPERVISOR_shared_info->vcpu_info[0].time;
- do_div(cpu_khz, info->tsc_to_system_mul);
+ do_div(xen_khz, info->tsc_to_system_mul);
if (info->tsc_shift < 0)
- cpu_khz <<= -info->tsc_shift;
+ xen_khz <<= -info->tsc_shift;
else
- cpu_khz >>= info->tsc_shift;
+ xen_khz >>= info->tsc_shift;
- return cpu_khz;
+ return xen_khz;
}
/*
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 5d5546ce88f..9fc8551a1cf 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -14,6 +14,7 @@ config ZONE_DMA
config XTENSA
bool
default y
+ select HAVE_IDE
help
Xtensa processors are 32-bit RISC machines designed by Tensilica
primarily for embedded systems. These processors are both
@@ -49,6 +50,10 @@ config ARCH_HAS_ILOG2_U64
config NO_IOPORT
def_bool y
+config HZ
+ int
+ default 100
+
source "init/Kconfig"
menu "Processor type and features"
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 2e8d398cf19..b80f2cb1b4f 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -469,7 +469,7 @@ c_stop(struct seq_file *f, void *v)
{
}
-struct seq_operations cpuinfo_op =
+const struct seq_operations cpuinfo_op =
{
start: c_start,
next: c_next,
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index 60d29fe0b1b..8df1e842f6d 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -204,7 +204,7 @@ again:
}
#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
-void __devinit calibrate_delay(void)
+void __cpuinit calibrate_delay(void)
{
loops_per_jiffy = CCOUNT_PER_JIFFY;
printk("Calibrating delay loop (skipped)... "