summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/acpi-hotkey.txt38
-rw-r--r--Documentation/arm/Samsung-S3C24XX/DMA.txt46
-rw-r--r--Documentation/arm/Samsung-S3C24XX/Overview.txt21
-rw-r--r--Documentation/feature-removal-schedule.txt30
-rw-r--r--Documentation/kernel-parameters.txt11
-rw-r--r--Documentation/pci.txt4
-rw-r--r--Documentation/powerpc/booting-without-of.txt14
-rw-r--r--Documentation/sony-laptop.txt106
-rw-r--r--MAINTAINERS13
-rw-r--r--arch/arm/Kconfig40
-rw-r--r--arch/arm/Makefile18
-rw-r--r--arch/arm/boot/.gitignore2
-rw-r--r--arch/arm/boot/compressed/.gitignore1
-rw-r--r--arch/arm/common/dmabounce.c87
-rw-r--r--arch/arm/common/gic.c109
-rw-r--r--arch/arm/configs/at91sam9263ek_defconfig1184
-rw-r--r--arch/arm/configs/ateb9200_defconfig2
-rw-r--r--arch/arm/configs/csb337_defconfig8
-rw-r--r--arch/arm/configs/csb637_defconfig6
-rw-r--r--arch/arm/configs/kafa_defconfig2
-rw-r--r--arch/arm/configs/ns9xxx_defconfig621
-rw-r--r--arch/arm/configs/s3c2410_defconfig142
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/calls.S1
-rw-r--r--arch/arm/kernel/crunch.c1
-rw-r--r--arch/arm/kernel/ecard.c2
-rw-r--r--arch/arm/kernel/entry-armv.S1
-rw-r--r--arch/arm/kernel/machine_kexec.c78
-rw-r--r--arch/arm/kernel/process.c8
-rw-r--r--arch/arm/kernel/relocate_kernel.S74
-rw-r--r--arch/arm/kernel/setup.c3
-rw-r--r--arch/arm/kernel/time.c4
-rw-r--r--arch/arm/kernel/traps.c17
-rw-r--r--arch/arm/mach-at91/Kconfig (renamed from arch/arm/mach-at91rm9200/Kconfig)39
-rw-r--r--arch/arm/mach-at91/Makefile (renamed from arch/arm/mach-at91rm9200/Makefile)4
-rw-r--r--arch/arm/mach-at91/Makefile.boot (renamed from arch/arm/mach-at91rm9200/Makefile.boot)0
-rw-r--r--arch/arm/mach-at91/at91rm9200.c (renamed from arch/arm/mach-at91rm9200/at91rm9200.c)39
-rw-r--r--arch/arm/mach-at91/at91rm9200_devices.c (renamed from arch/arm/mach-at91rm9200/at91rm9200_devices.c)10
-rw-r--r--arch/arm/mach-at91/at91rm9200_time.c (renamed from arch/arm/mach-at91rm9200/at91rm9200_time.c)2
-rw-r--r--arch/arm/mach-at91/at91sam9260.c (renamed from arch/arm/mach-at91rm9200/at91sam9260.c)90
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c (renamed from arch/arm/mach-at91rm9200/at91sam9260_devices.c)16
-rw-r--r--arch/arm/mach-at91/at91sam9261.c (renamed from arch/arm/mach-at91rm9200/at91sam9261.c)23
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c (renamed from arch/arm/mach-at91rm9200/at91sam9261_devices.c)10
-rw-r--r--arch/arm/mach-at91/at91sam9263.c313
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c818
-rw-r--r--arch/arm/mach-at91/at91sam926x_time.c (renamed from arch/arm/mach-at91rm9200/at91sam926x_time.c)5
-rw-r--r--arch/arm/mach-at91/board-1arm.c (renamed from arch/arm/mach-at91rm9200/board-1arm.c)2
-rw-r--r--arch/arm/mach-at91/board-carmeva.c (renamed from arch/arm/mach-at91rm9200/board-carmeva.c)4
-rw-r--r--arch/arm/mach-at91/board-csb337.c (renamed from arch/arm/mach-at91rm9200/board-csb337.c)43
-rw-r--r--arch/arm/mach-at91/board-csb637.c (renamed from arch/arm/mach-at91rm9200/board-csb637.c)41
-rw-r--r--arch/arm/mach-at91/board-dk.c (renamed from arch/arm/mach-at91rm9200/board-dk.c)4
-rw-r--r--arch/arm/mach-at91/board-eb9200.c (renamed from arch/arm/mach-at91rm9200/board-eb9200.c)4
-rw-r--r--arch/arm/mach-at91/board-ek.c (renamed from arch/arm/mach-at91rm9200/board-ek.c)4
-rw-r--r--arch/arm/mach-at91/board-kafa.c (renamed from arch/arm/mach-at91rm9200/board-kafa.c)2
-rw-r--r--arch/arm/mach-at91/board-kb9202.c (renamed from arch/arm/mach-at91rm9200/board-kb9202.c)4
-rw-r--r--arch/arm/mach-at91/board-sam9260ek.c (renamed from arch/arm/mach-at91rm9200/board-sam9260ek.c)6
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c (renamed from arch/arm/mach-at91rm9200/board-sam9261ek.c)4
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c176
-rw-r--r--arch/arm/mach-at91/clock.c (renamed from arch/arm/mach-at91rm9200/clock.c)64
-rw-r--r--arch/arm/mach-at91/clock.h (renamed from arch/arm/mach-at91rm9200/clock.h)2
-rw-r--r--arch/arm/mach-at91/generic.h (renamed from arch/arm/mach-at91rm9200/generic.h)4
-rw-r--r--arch/arm/mach-at91/gpio.c (renamed from arch/arm/mach-at91rm9200/gpio.c)2
-rw-r--r--arch/arm/mach-at91/irq.c (renamed from arch/arm/mach-at91rm9200/irq.c)2
-rw-r--r--arch/arm/mach-at91/leds.c (renamed from arch/arm/mach-at91rm9200/leds.c)4
-rw-r--r--arch/arm/mach-at91/pm.c (renamed from arch/arm/mach-at91rm9200/pm.c)4
-rw-r--r--arch/arm/mach-ep93xx/Kconfig25
-rw-r--r--arch/arm/mach-ep93xx/Makefile1
-rw-r--r--arch/arm/mach-ep93xx/clock.c6
-rw-r--r--arch/arm/mach-ep93xx/core.c115
-rw-r--r--arch/arm/mach-ep93xx/micro9.c157
-rw-r--r--arch/arm/mach-iop13xx/irq.c3
-rw-r--r--arch/arm/mach-iop32x/irq.c2
-rw-r--r--arch/arm/mach-iop32x/n2100.c14
-rw-r--r--arch/arm/mach-iop33x/irq.c2
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig12
-rw-r--r--arch/arm/mach-ixp4xx/Makefile2
-rw-r--r--arch/arm/mach-ixp4xx/avila-pci.c78
-rw-r--r--arch/arm/mach-ixp4xx/avila-setup.c192
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-pci.c2
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c20
-rw-r--r--arch/arm/mach-ns9xxx/Kconfig21
-rw-r--r--arch/arm/mach-ns9xxx/Makefile5
-rw-r--r--arch/arm/mach-ns9xxx/Makefile.boot2
-rw-r--r--arch/arm/mach-ns9xxx/board-a9m9750dev.c199
-rw-r--r--arch/arm/mach-ns9xxx/board-a9m9750dev.h15
-rw-r--r--arch/arm/mach-ns9xxx/generic.c42
-rw-r--r--arch/arm/mach-ns9xxx/generic.h19
-rw-r--r--arch/arm/mach-ns9xxx/irq.c94
-rw-r--r--arch/arm/mach-ns9xxx/mach-cc9p9360dev.c41
-rw-r--r--arch/arm/mach-ns9xxx/time.c88
-rw-r--r--arch/arm/mach-pxa/generic.c24
-rw-r--r--arch/arm/mach-realview/Kconfig11
-rw-r--r--arch/arm/mach-realview/platsmp.c4
-rw-r--r--arch/arm/mach-realview/realview_eb.c38
-rw-r--r--arch/arm/mach-s3c2400/Kconfig13
-rw-r--r--arch/arm/mach-s3c2400/Makefile15
-rw-r--r--arch/arm/mach-s3c2400/gpio.c (renamed from arch/arm/mach-s3c2410/s3c2400-gpio.c)2
-rw-r--r--arch/arm/mach-s3c2410/Kconfig338
-rw-r--r--arch/arm/mach-s3c2410/Makefile103
-rw-r--r--arch/arm/mach-s3c2410/bast-irq.c2
-rw-r--r--arch/arm/mach-s3c2410/bast.h2
-rw-r--r--arch/arm/mach-s3c2410/clock.c565
-rw-r--r--arch/arm/mach-s3c2410/dma.c1546
-rw-r--r--arch/arm/mach-s3c2410/gpio.c165
-rw-r--r--arch/arm/mach-s3c2410/irq.c775
-rw-r--r--arch/arm/mach-s3c2410/mach-amlm5900.c14
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c6
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c64
-rw-r--r--arch/arm/mach-s3c2410/mach-n30.c9
-rw-r--r--arch/arm/mach-s3c2410/mach-otom.c8
-rw-r--r--arch/arm/mach-s3c2410/mach-qt2410.c448
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c8
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c6
-rw-r--r--arch/arm/mach-s3c2410/pm.c653
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-clock.c276
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-dma.c161
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-gpio.c71
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-irq.c48
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-pm.c156
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-sleep.S68
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.c10
-rw-r--r--arch/arm/mach-s3c2410/sleep.S151
-rw-r--r--arch/arm/mach-s3c2410/usb-simtec.c2
-rw-r--r--arch/arm/mach-s3c2412/Kconfig58
-rw-r--r--arch/arm/mach-s3c2412/Makefile21
-rw-r--r--arch/arm/mach-s3c2412/clock.c (renamed from arch/arm/mach-s3c2410/s3c2412-clock.c)8
-rw-r--r--arch/arm/mach-s3c2412/dma.c (renamed from arch/arm/mach-s3c2410/s3c2412-dma.c)7
-rw-r--r--arch/arm/mach-s3c2412/irq.c (renamed from arch/arm/mach-s3c2410/s3c2412-irq.c)8
-rw-r--r--arch/arm/mach-s3c2412/mach-smdk2413.c (renamed from arch/arm/mach-s3c2410/mach-smdk2413.c)68
-rw-r--r--arch/arm/mach-s3c2412/mach-vstms.c (renamed from arch/arm/mach-s3c2410/mach-vstms.c)13
-rw-r--r--arch/arm/mach-s3c2412/pm.c (renamed from arch/arm/mach-s3c2410/s3c2412-pm.c)8
-rw-r--r--arch/arm/mach-s3c2412/s3c2412.c (renamed from arch/arm/mach-s3c2410/s3c2412.c)12
-rw-r--r--arch/arm/mach-s3c2440/Kconfig71
-rw-r--r--arch/arm/mach-s3c2440/Makefile23
-rw-r--r--arch/arm/mach-s3c2440/clock.c (renamed from arch/arm/mach-s3c2410/s3c2440-clock.c)6
-rw-r--r--arch/arm/mach-s3c2440/dma.c (renamed from arch/arm/mach-s3c2410/s3c2440-dma.c)51
-rw-r--r--arch/arm/mach-s3c2440/dsc.c (renamed from arch/arm/mach-s3c2410/s3c2440-dsc.c)6
-rw-r--r--arch/arm/mach-s3c2440/irq.c (renamed from arch/arm/mach-s3c2410/s3c2440-irq.c)8
-rw-r--r--arch/arm/mach-s3c2440/mach-anubis.c (renamed from arch/arm/mach-s3c2410/mach-anubis.c)8
-rw-r--r--arch/arm/mach-s3c2440/mach-nexcoder.c (renamed from arch/arm/mach-s3c2410/mach-nexcoder.c)12
-rw-r--r--arch/arm/mach-s3c2440/mach-osiris.c (renamed from arch/arm/mach-s3c2410/mach-osiris.c)8
-rw-r--r--arch/arm/mach-s3c2440/mach-rx3715.c (renamed from arch/arm/mach-s3c2410/mach-rx3715.c)11
-rw-r--r--arch/arm/mach-s3c2440/mach-smdk2440.c (renamed from arch/arm/mach-s3c2410/mach-smdk2440.c)17
-rw-r--r--arch/arm/mach-s3c2440/s3c2440.c (renamed from arch/arm/mach-s3c2410/s3c2440.c)8
-rw-r--r--arch/arm/mach-s3c2442/Kconfig27
-rw-r--r--arch/arm/mach-s3c2442/Makefile16
-rw-r--r--arch/arm/mach-s3c2442/clock.c (renamed from arch/arm/mach-s3c2410/s3c2442-clock.c)6
-rw-r--r--arch/arm/mach-s3c2442/s3c2442.c (renamed from arch/arm/mach-s3c2410/s3c2442.c)6
-rw-r--r--arch/arm/mach-s3c2443/Kconfig29
-rw-r--r--arch/arm/mach-s3c2443/Makefile20
-rw-r--r--arch/arm/mach-s3c2443/clock.c1007
-rw-r--r--arch/arm/mach-s3c2443/dma.c180
-rw-r--r--arch/arm/mach-s3c2443/irq.c290
-rw-r--r--arch/arm/mach-s3c2443/mach-smdk2443.c137
-rw-r--r--arch/arm/mach-s3c2443/s3c2443.c97
-rw-r--r--arch/arm/mm/Kconfig11
-rw-r--r--arch/arm/mm/Makefile2
-rw-r--r--arch/arm/mm/cache-l2x0.c104
-rw-r--r--arch/arm/mm/consistent.c17
-rw-r--r--arch/arm/mm/context.c12
-rw-r--r--arch/arm/mm/fault-armv.c2
-rw-r--r--arch/arm/mm/mmu.c3
-rw-r--r--arch/arm/mm/proc-v6.S22
-rw-r--r--arch/arm/mm/proc-xsc3.S151
-rw-r--r--arch/arm/mm/tlb-v6.S4
-rw-r--r--arch/arm/oprofile/Kconfig19
-rw-r--r--arch/arm/oprofile/Makefile4
-rw-r--r--arch/arm/oprofile/common.c8
-rw-r--r--arch/arm/oprofile/op_arm_model.h3
-rw-r--r--arch/arm/oprofile/op_model_arm11_core.c162
-rw-r--r--arch/arm/oprofile/op_model_arm11_core.h45
-rw-r--r--arch/arm/oprofile/op_model_mpcore.c296
-rw-r--r--arch/arm/oprofile/op_model_mpcore.h61
-rw-r--r--arch/arm/oprofile/op_model_v6.c67
-rw-r--r--arch/arm/plat-iop/Makefile30
-rw-r--r--arch/arm/plat-iop/cp6.c50
-rw-r--r--arch/arm/plat-iop/io.c58
-rw-r--r--arch/arm/plat-iop/pci.c6
-rw-r--r--arch/arm/plat-s3c24xx/Kconfig99
-rw-r--r--arch/arm/plat-s3c24xx/Makefile30
-rw-r--r--arch/arm/plat-s3c24xx/clock.c449
-rw-r--r--arch/arm/plat-s3c24xx/common-smdk.c (renamed from arch/arm/mach-s3c2410/common-smdk.c)8
-rw-r--r--arch/arm/plat-s3c24xx/cpu.c (renamed from arch/arm/mach-s3c2410/cpu.c)29
-rw-r--r--arch/arm/plat-s3c24xx/devs.c (renamed from arch/arm/mach-s3c2410/devs.c)21
-rw-r--r--arch/arm/plat-s3c24xx/dma.c1499
-rw-r--r--arch/arm/plat-s3c24xx/gpio.c188
-rw-r--r--arch/arm/plat-s3c24xx/irq.c801
-rw-r--r--arch/arm/plat-s3c24xx/pm-simtec.c (renamed from arch/arm/mach-s3c2410/pm-simtec.c)4
-rw-r--r--arch/arm/plat-s3c24xx/pm.c659
-rw-r--r--arch/arm/plat-s3c24xx/s3c244x-irq.c (renamed from arch/arm/mach-s3c2410/s3c244x-irq.c)8
-rw-r--r--arch/arm/plat-s3c24xx/s3c244x.c (renamed from arch/arm/mach-s3c2410/s3c244x.c)16
-rw-r--r--arch/arm/plat-s3c24xx/s3c244x.h (renamed from arch/arm/mach-s3c2410/s3c244x.h)2
-rw-r--r--arch/arm/plat-s3c24xx/sleep.S157
-rw-r--r--arch/arm/plat-s3c24xx/time.c (renamed from arch/arm/mach-s3c2410/time.c)6
-rw-r--r--arch/avr32/mach-at32ap/clock.c2
-rw-r--r--arch/avr32/mach-at32ap/clock.h2
-rw-r--r--arch/i386/kernel/acpi/boot.c5
-rw-r--r--arch/i386/pci/common.c88
-rw-r--r--arch/ia64/kernel/acpi.c4
-rw-r--r--arch/powerpc/Kconfig9
-rw-r--r--arch/powerpc/boot/dts/kuroboxHD.dts1
-rw-r--r--arch/powerpc/boot/dts/kuroboxHG.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc7448hpc2.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8272ads.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8313erdb.dts62
-rw-r--r--arch/powerpc/boot/dts/mpc832x_mds.dts (renamed from arch/powerpc/boot/dts/mpc8323emds.dts)120
-rw-r--r--arch/powerpc/boot/dts/mpc8349emitx.dts60
-rw-r--r--arch/powerpc/boot/dts/mpc8349emitxgp.dts39
-rw-r--r--arch/powerpc/boot/dts/mpc834x_mds.dts164
-rw-r--r--arch/powerpc/boot/dts/mpc836x_mds.dts (renamed from arch/powerpc/boot/dts/mpc8360emds.dts)124
-rw-r--r--arch/powerpc/boot/dts/mpc8540ads.dts142
-rw-r--r--arch/powerpc/boot/dts/mpc8541cds.dts108
-rw-r--r--arch/powerpc/boot/dts/mpc8548cds.dts129
-rw-r--r--arch/powerpc/boot/dts/mpc8555cds.dts108
-rw-r--r--arch/powerpc/boot/dts/mpc8560ads.dts158
-rw-r--r--arch/powerpc/boot/dts/mpc8568mds.dts96
-rw-r--r--arch/powerpc/boot/dts/mpc8641_hpcn.dts194
-rw-r--r--arch/powerpc/boot/dts/mpc866ads.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc885ads.dts1
-rw-r--r--arch/powerpc/configs/cell_defconfig1
-rw-r--r--arch/powerpc/configs/mpc832x_mds_defconfig (renamed from arch/powerpc/configs/mpc832xemds_defconfig)0
-rw-r--r--arch/powerpc/configs/mpc836x_mds_defconfig (renamed from arch/powerpc/configs/mpc8360emds_defconfig)29
-rw-r--r--arch/powerpc/configs/mpc8568mds_defconfig32
-rw-r--r--arch/powerpc/configs/ppc64_defconfig4
-rw-r--r--arch/powerpc/configs/pseries_defconfig4
-rw-r--r--arch/powerpc/kernel/prom.c1
-rw-r--r--arch/powerpc/kernel/prom_parse.c40
-rw-r--r--arch/powerpc/mm/pgtable_64.c2
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig8
-rw-r--r--arch/powerpc/platforms/83xx/Makefile2
-rw-r--r--arch/powerpc/platforms/83xx/mpc8313_rdb.c11
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c65
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.c23
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_mds.c27
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_mds.c (renamed from arch/powerpc/platforms/83xx/mpc8360e_pb.c)97
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig8
-rw-r--r--arch/powerpc/platforms/85xx/Makefile2
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c14
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.c15
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c (renamed from arch/powerpc/platforms/85xx/mpc8568_mds.c)46
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c9
-rw-r--r--arch/powerpc/platforms/celleb/Makefile3
-rw-r--r--arch/powerpc/platforms/celleb/setup.c2
-rw-r--r--arch/powerpc/platforms/ps3/Kconfig10
-rw-r--r--arch/powerpc/platforms/ps3/setup.c27
-rw-r--r--arch/powerpc/platforms/pseries/Makefile2
-rw-r--r--arch/powerpc/platforms/pseries/power.c87
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h7
-rw-r--r--arch/powerpc/platforms/pseries/setup.c30
-rw-r--r--arch/powerpc/sysdev/Makefile1
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c19
-rw-r--r--arch/powerpc/sysdev/mpic.c2
-rw-r--r--arch/powerpc/sysdev/pmi.c305
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_fast.c163
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_slow.c137
-rw-r--r--arch/x86_64/kernel/early-quirks.c4
-rw-r--r--drivers/acpi/Kconfig10
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/ac.c9
-rw-r--r--drivers/acpi/acpi_memhotplug.c9
-rw-r--r--drivers/acpi/asus_acpi.c20
-rw-r--r--drivers/acpi/battery.c24
-rw-r--r--drivers/acpi/bay.c107
-rw-r--r--drivers/acpi/bus.c30
-rw-r--r--drivers/acpi/button.c7
-rw-r--r--drivers/acpi/cm_sbs.c2
-rw-r--r--drivers/acpi/container.c9
-rw-r--r--drivers/acpi/debug.c2
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c12
-rw-r--r--drivers/acpi/dock.c8
-rw-r--r--drivers/acpi/ec.c9
-rw-r--r--drivers/acpi/event.c2
-rw-r--r--drivers/acpi/events/evgpe.c11
-rw-r--r--drivers/acpi/events/evmisc.c11
-rw-r--r--drivers/acpi/executer/exdump.c2
-rw-r--r--drivers/acpi/executer/exmutex.c36
-rw-r--r--drivers/acpi/fan.c9
-rw-r--r--drivers/acpi/glue.c62
-rw-r--r--drivers/acpi/hardware/hwsleep.c13
-rw-r--r--drivers/acpi/hotkey.c1042
-rw-r--r--drivers/acpi/i2c_ec.c5
-rw-r--r--drivers/acpi/ibm_acpi.c18
-rw-r--r--drivers/acpi/numa.c18
-rw-r--r--drivers/acpi/osl.c35
-rw-r--r--drivers/acpi/pci_bind.c2
-rw-r--r--drivers/acpi/pci_irq.c2
-rw-r--r--drivers/acpi/pci_link.c5
-rw-r--r--drivers/acpi/pci_root.c5
-rw-r--r--drivers/acpi/power.c156
-rw-r--r--drivers/acpi/processor_core.c13
-rw-r--r--drivers/acpi/processor_idle.c11
-rw-r--r--drivers/acpi/processor_perflib.c3
-rw-r--r--drivers/acpi/processor_thermal.c3
-rw-r--r--drivers/acpi/processor_throttling.c3
-rw-r--r--drivers/acpi/sbs.c25
-rw-r--r--drivers/acpi/scan.c3
-rw-r--r--drivers/acpi/sleep/main.c3
-rw-r--r--drivers/acpi/system.c3
-rw-r--r--drivers/acpi/tables.c41
-rw-r--r--drivers/acpi/tables/tbxface.c9
-rw-r--r--drivers/acpi/thermal.c37
-rw-r--r--drivers/acpi/toshiba_acpi.c6
-rw-r--r--drivers/acpi/utilities/utdelete.c1
-rw-r--r--drivers/acpi/utils.c2
-rw-r--r--drivers/acpi/video.c9
-rw-r--r--drivers/ata/Kconfig13
-rw-r--r--drivers/ata/Makefile2
-rw-r--r--drivers/ata/libata-acpi.c698
-rw-r--r--drivers/ata/libata-core.c14
-rw-r--r--drivers/ata/libata.h15
-rw-r--r--drivers/atm/he.c2
-rw-r--r--drivers/atm/idt77252.c8
-rw-r--r--drivers/atm/nicstarmac.c4
-rw-r--r--drivers/base/bus.c22
-rw-r--r--drivers/base/class.c3
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c2
-rw-r--r--drivers/i2c/busses/i2c-pxa.c241
-rw-r--r--drivers/ide/Kconfig8
-rw-r--r--drivers/ide/Makefile1
-rw-r--r--drivers/ide/arm/icside.c25
-rw-r--r--drivers/ide/arm/rapide.c2
-rw-r--r--drivers/ide/cris/ide-cris.c34
-rw-r--r--drivers/ide/h8300/ide-h8300.c4
-rw-r--r--drivers/ide/ide-cd.c44
-rw-r--r--drivers/ide/ide-disk.c14
-rw-r--r--drivers/ide/ide-dma.c105
-rw-r--r--drivers/ide/ide-floppy.c29
-rw-r--r--drivers/ide/ide-io.c15
-rw-r--r--drivers/ide/ide-iops.c34
-rw-r--r--drivers/ide/ide-lib.c20
-rw-r--r--drivers/ide/ide-probe.c4
-rw-r--r--drivers/ide/ide-tape.c12
-rw-r--r--drivers/ide/ide.c24
-rw-r--r--drivers/ide/legacy/buddha.c2
-rw-r--r--drivers/ide/legacy/gayle.c2
-rw-r--r--drivers/ide/legacy/ht6560b.c14
-rw-r--r--drivers/ide/legacy/macide.c2
-rw-r--r--drivers/ide/legacy/q40ide.c2
-rw-r--r--drivers/ide/mips/au1xxx-ide.c41
-rw-r--r--drivers/ide/mips/swarm.c2
-rw-r--r--drivers/ide/pci/aec62xx.c32
-rw-r--r--drivers/ide/pci/alim15x3.c15
-rw-r--r--drivers/ide/pci/amd74xx.c5
-rw-r--r--drivers/ide/pci/atiixp.c41
-rw-r--r--drivers/ide/pci/cmd64x.c47
-rw-r--r--drivers/ide/pci/cs5520.c5
-rw-r--r--drivers/ide/pci/cs5530.c41
-rw-r--r--drivers/ide/pci/cs5535.c19
-rw-r--r--drivers/ide/pci/cy82c693.c33
-rw-r--r--drivers/ide/pci/hpt34x.c42
-rw-r--r--drivers/ide/pci/hpt366.c24
-rw-r--r--drivers/ide/pci/it8213.c14
-rw-r--r--drivers/ide/pci/it821x.c14
-rw-r--r--drivers/ide/pci/jmicron.c14
-rw-r--r--drivers/ide/pci/ns87415.c13
-rw-r--r--drivers/ide/pci/opti621.c63
-rw-r--r--drivers/ide/pci/pdc202xx_new.c28
-rw-r--r--drivers/ide/pci/pdc202xx_old.c104
-rw-r--r--drivers/ide/pci/piix.c119
-rw-r--r--drivers/ide/pci/sc1200.c11
-rw-r--r--drivers/ide/pci/serverworks.c59
-rw-r--r--drivers/ide/pci/sgiioc4.c125
-rw-r--r--drivers/ide/pci/siimage.c113
-rw-r--r--drivers/ide/pci/sis5513.c59
-rw-r--r--drivers/ide/pci/sl82c105.c39
-rw-r--r--drivers/ide/pci/slc90e66.c22
-rw-r--r--drivers/ide/pci/tc86c001.c46
-rw-r--r--drivers/ide/pci/triflex.c24
-rw-r--r--drivers/ide/pci/trm290.c42
-rw-r--r--drivers/ide/pci/via82cxxx.c5
-rw-r--r--drivers/ide/ppc/pmac.c16
-rw-r--r--drivers/ide/ppc/scc_pata.c831
-rw-r--r--drivers/ieee1394/ieee1394-ioctl.h2
-rw-r--r--drivers/ieee1394/ieee1394_core.c43
-rw-r--r--drivers/ieee1394/ieee1394_core.h3
-rw-r--r--drivers/ieee1394/nodemgr.c3
-rw-r--r--drivers/ieee1394/raw1394.c20
-rw-r--r--drivers/ieee1394/raw1394.h10
-rw-r--r--drivers/infiniband/core/Makefile2
-rw-r--r--drivers/infiniband/core/cma.c359
-rw-r--r--drivers/infiniband/core/fmr_pool.c4
-rw-r--r--drivers/infiniband/core/iwcm.c47
-rw-r--r--drivers/infiniband/core/multicast.c837
-rw-r--r--drivers/infiniband/core/sa.h66
-rw-r--r--drivers/infiniband/core/sa_query.c30
-rw-r--r--drivers/infiniband/core/sysfs.c2
-rw-r--r--drivers/infiniband/core/ucma.c204
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_dbg.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_hal.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_hal.h1
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_resource.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_resource.h1
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_wr.h1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch.h1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.h1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cq.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_ev.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_mem.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.h1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_qp.c3
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_user.h1
-rw-r--r--drivers/infiniband/hw/ehca/Kconfig8
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h19
-rw-r--r--drivers/infiniband/hw/ehca/ehca_eq.c1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_hca.c3
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c307
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.h1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c32
-rw-r--r--drivers/infiniband/hw/ehca/ipz_pt_fn.h11
-rw-r--r--drivers/infiniband/hw/ipath/ipath_dma.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c5
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c195
-rw-r--r--drivers/misc/Kconfig15
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/asus-laptop.c5
-rw-r--r--drivers/misc/sony-laptop.c562
-rw-r--r--drivers/mmc/at91_mci.c46
-rw-r--r--drivers/net/Kconfig14
-rw-r--r--drivers/net/arcnet/arc-rawmode.c4
-rw-r--r--drivers/net/arcnet/arcnet.c2
-rw-r--r--drivers/net/arcnet/com20020-pci.c3
-rw-r--r--drivers/net/arcnet/com20020.c2
-rw-r--r--drivers/net/atl1/atl1_hw.c37
-rw-r--r--drivers/net/atl1/atl1_main.c5
-rw-r--r--drivers/net/b44.c19
-rw-r--r--drivers/net/cxgb3/cxgb3_defs.h1
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.c1
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.h1
-rw-r--r--drivers/net/cxgb3/l2t.c1
-rw-r--r--drivers/net/cxgb3/l2t.h1
-rw-r--r--drivers/net/cxgb3/t3cdev.h1
-rw-r--r--drivers/net/e1000/e1000.h1
-rw-r--r--drivers/net/e1000/e1000_ethtool.c2
-rw-r--r--drivers/net/e1000/e1000_main.c70
-rw-r--r--drivers/net/ehea/ehea.h2
-rw-r--r--drivers/net/ehea/ehea_main.c8
-rw-r--r--drivers/net/ehea/ehea_phyp.c10
-rw-r--r--drivers/net/ehea/ehea_phyp.h3
-rw-r--r--drivers/net/ehea/ehea_qmr.c42
-rw-r--r--drivers/net/ehea/ehea_qmr.h5
-rw-r--r--drivers/net/gianfar.c85
-rw-r--r--drivers/net/gianfar_sysfs.c108
-rw-r--r--drivers/net/ioc3-eth.c16
-rw-r--r--drivers/net/macb.c24
-rw-r--r--drivers/net/meth.c26
-rw-r--r--drivers/net/netxen/netxen_nic.h9
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c9
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c2
-rw-r--r--drivers/net/netxen/netxen_nic_init.c12
-rw-r--r--drivers/net/netxen/netxen_nic_main.c3
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c2
-rw-r--r--drivers/net/pcmcia/3c574_cs.c2
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c2
-rw-r--r--drivers/net/phy/marvell.c156
-rw-r--r--drivers/net/phy/phy_device.c4
-rw-r--r--drivers/net/sk98lin/skge.c3
-rw-r--r--drivers/net/sky2.c125
-rw-r--r--drivers/net/sky2.h3
-rw-r--r--drivers/net/wan/Kconfig2
-rw-r--r--drivers/net/wan/pc300too.c2
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h1
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_dma.c171
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c25
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.c28
-rw-r--r--drivers/net/wireless/ipw2100.c16
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c44
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c12
-rw-r--r--drivers/pci/pci-driver.c1
-rw-r--r--drivers/pci/pci-sysfs.c11
-rw-r--r--drivers/pci/pci.c12
-rw-r--r--drivers/pci/setup-bus.c27
-rw-r--r--drivers/pci/setup-irq.c18
-rw-r--r--drivers/pcmcia/at91_cf.c2
-rw-r--r--drivers/pcmcia/soc_common.c8
-rw-r--r--drivers/pnp/pnpacpi/Kconfig16
-rw-r--r--drivers/ps3/Makefile1
-rw-r--r--drivers/ps3/sys-manager.c604
-rw-r--r--drivers/ps3/vuart.c398
-rw-r--r--drivers/ps3/vuart.h59
-rw-r--r--drivers/scsi/ide-scsi.c8
-rw-r--r--drivers/scsi/sd.c11
-rw-r--r--drivers/serial/Kconfig3
-rw-r--r--drivers/serial/atmel_serial.c3
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c2
-rw-r--r--drivers/serial/imx.c14
-rw-r--r--drivers/serial/mpc52xx_uart.c4
-rw-r--r--drivers/serial/serial_cs.c5
-rw-r--r--drivers/usb/Makefile1
-rw-r--r--drivers/usb/atm/ueagle-atm.c1
-rw-r--r--drivers/usb/class/cdc-acm.c33
-rw-r--r--drivers/usb/core/devices.c9
-rw-r--r--drivers/usb/core/devio.c4
-rw-r--r--drivers/usb/core/driver.c1
-rw-r--r--drivers/usb/core/endpoint.c2
-rw-r--r--drivers/usb/core/generic.c2
-rw-r--r--drivers/usb/core/hub.c31
-rw-r--r--drivers/usb/core/message.c22
-rw-r--r--drivers/usb/core/otg_whitelist.h2
-rw-r--r--drivers/usb/core/sysfs.c2
-rw-r--r--drivers/usb/gadget/at91_udc.c19
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c16
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.h15
-rw-r--r--drivers/usb/gadget/serial.c1
-rw-r--r--drivers/usb/host/ehci-hcd.c36
-rw-r--r--drivers/usb/host/ehci-hub.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c2
-rw-r--r--drivers/usb/host/ohci-at91.c50
-rw-r--r--drivers/usb/host/ohci-hcd.c18
-rw-r--r--drivers/usb/input/hid-core.c8
-rw-r--r--drivers/usb/misc/Kconfig11
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/appledisplay.c4
-rw-r--r--drivers/usb/misc/berry_charge.c140
-rw-r--r--drivers/usb/net/Kconfig11
-rw-r--r--drivers/usb/net/asix.c2
-rw-r--r--drivers/usb/net/cdc_subset.c21
-rw-r--r--drivers/usb/net/usbnet.c29
-rw-r--r--drivers/usb/serial/airprime.c35
-rw-r--r--drivers/usb/serial/cp2101.c1
-rw-r--r--drivers/usb/serial/generic.c102
-rw-r--r--drivers/usb/serial/option.c4
-rw-r--r--drivers/usb/serial/pl2303.c1
-rw-r--r--drivers/usb/serial/pl2303.h5
-rw-r--r--drivers/usb/storage/scsiglue.c6
-rw-r--r--drivers/usb/storage/unusual_devs.h26
-rw-r--r--drivers/usb/usb-skeleton.c10
-rw-r--r--fs/Kconfig26
-rw-r--r--fs/Makefile1
-rw-r--r--fs/debugfs/file.c12
-rw-r--r--fs/debugfs/inode.c82
-rw-r--r--fs/jffs/Makefile11
-rw-r--r--fs/jffs/inode-v23.c1847
-rw-r--r--fs/jffs/intrep.c3449
-rw-r--r--fs/jffs/intrep.h58
-rw-r--r--fs/jffs/jffs_fm.c798
-rw-r--r--fs/jffs/jffs_fm.h149
-rw-r--r--fs/jffs/jffs_proc.c261
-rw-r--r--fs/jffs/jffs_proc.h28
-rw-r--r--fs/partitions/check.c9
-rw-r--r--fs/sysfs/file.c2
-rw-r--r--include/acpi/acinterp.h3
-rw-r--r--include/acpi/acobject.h2
-rw-r--r--include/acpi/acpi_drivers.h40
-rw-r--r--include/acpi/acpiosxf.h6
-rw-r--r--include/asm-arm/.gitignore2
-rw-r--r--include/asm-arm/arch-at91/at91_aic.h (renamed from include/asm-arm/arch-at91rm9200/at91_aic.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_dbgu.h (renamed from include/asm-arm/arch-at91rm9200/at91_dbgu.h)16
-rw-r--r--include/asm-arm/arch-at91/at91_ecc.h (renamed from include/asm-arm/arch-at91rm9200/at91_ecc.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_lcdc.h (renamed from include/asm-arm/arch-at91rm9200/at91_lcdc.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_mci.h (renamed from include/asm-arm/arch-at91rm9200/at91_mci.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_pio.h (renamed from include/asm-arm/arch-at91rm9200/at91_pio.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_pit.h (renamed from include/asm-arm/arch-at91rm9200/at91_pit.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_pmc.h (renamed from include/asm-arm/arch-at91rm9200/at91_pmc.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_rstc.h (renamed from include/asm-arm/arch-at91rm9200/at91_rstc.h)5
-rw-r--r--include/asm-arm/arch-at91/at91_rtc.h (renamed from include/asm-arm/arch-at91rm9200/at91_rtc.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_rtt.h (renamed from include/asm-arm/arch-at91rm9200/at91_rtt.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_shdwc.h (renamed from include/asm-arm/arch-at91rm9200/at91_shdwc.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_spi.h (renamed from include/asm-arm/arch-at91rm9200/at91_spi.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_ssc.h (renamed from include/asm-arm/arch-at91rm9200/at91_ssc.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_st.h (renamed from include/asm-arm/arch-at91rm9200/at91_st.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_tc.h (renamed from include/asm-arm/arch-at91rm9200/at91_tc.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_twi.h (renamed from include/asm-arm/arch-at91rm9200/at91_twi.h)2
-rw-r--r--include/asm-arm/arch-at91/at91_wdt.h (renamed from include/asm-arm/arch-at91rm9200/at91_wdt.h)2
-rw-r--r--include/asm-arm/arch-at91/at91rm9200.h (renamed from include/asm-arm/arch-at91rm9200/at91rm9200.h)2
-rw-r--r--include/asm-arm/arch-at91/at91rm9200_emac.h (renamed from include/asm-arm/arch-at91rm9200/at91rm9200_emac.h)2
-rw-r--r--include/asm-arm/arch-at91/at91rm9200_mc.h (renamed from include/asm-arm/arch-at91rm9200/at91rm9200_mc.h)2
-rw-r--r--include/asm-arm/arch-at91/at91sam9260.h (renamed from include/asm-arm/arch-at91rm9200/at91sam9260.h)6
-rw-r--r--include/asm-arm/arch-at91/at91sam9260_matrix.h (renamed from include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h)4
-rw-r--r--include/asm-arm/arch-at91/at91sam9261.h (renamed from include/asm-arm/arch-at91rm9200/at91sam9261.h)2
-rw-r--r--include/asm-arm/arch-at91/at91sam9261_matrix.h (renamed from include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h)2
-rw-r--r--include/asm-arm/arch-at91/at91sam9263.h131
-rw-r--r--include/asm-arm/arch-at91/at91sam9263_matrix.h129
-rw-r--r--include/asm-arm/arch-at91/at91sam926x_mc.h (renamed from include/asm-arm/arch-at91rm9200/at91sam926x_mc.h)9
-rw-r--r--include/asm-arm/arch-at91/board.h (renamed from include/asm-arm/arch-at91rm9200/board.h)9
-rw-r--r--include/asm-arm/arch-at91/cpu.h (renamed from include/asm-arm/arch-at91rm9200/cpu.h)26
-rw-r--r--include/asm-arm/arch-at91/debug-macro.S39
-rw-r--r--include/asm-arm/arch-at91/dma.h (renamed from include/asm-arm/arch-at91rm9200/dma.h)2
-rw-r--r--include/asm-arm/arch-at91/entry-macro.S26
-rw-r--r--include/asm-arm/arch-at91/gpio.h (renamed from include/asm-arm/arch-at91rm9200/gpio.h)61
-rw-r--r--include/asm-arm/arch-at91/hardware.h (renamed from include/asm-arm/arch-at91rm9200/hardware.h)12
-rw-r--r--include/asm-arm/arch-at91/io.h (renamed from include/asm-arm/arch-at91rm9200/io.h)2
-rw-r--r--include/asm-arm/arch-at91/irqs.h (renamed from include/asm-arm/arch-at91rm9200/irqs.h)6
-rw-r--r--include/asm-arm/arch-at91/memory.h (renamed from include/asm-arm/arch-at91rm9200/memory.h)2
-rw-r--r--include/asm-arm/arch-at91/system.h (renamed from include/asm-arm/arch-at91rm9200/system.h)2
-rw-r--r--include/asm-arm/arch-at91/timex.h (renamed from include/asm-arm/arch-at91rm9200/timex.h)7
-rw-r--r--include/asm-arm/arch-at91/uncompress.h (renamed from include/asm-arm/arch-at91rm9200/uncompress.h)2
-rw-r--r--include/asm-arm/arch-at91/vmalloc.h (renamed from include/asm-arm/arch-at91rm9200/vmalloc.h)2
-rw-r--r--include/asm-arm/arch-at91rm9200/at91_pdc.h36
-rw-r--r--include/asm-arm/arch-at91rm9200/debug-macro.S39
-rw-r--r--include/asm-arm/arch-at91rm9200/entry-macro.S26
-rw-r--r--include/asm-arm/arch-ep93xx/ep93xx-regs.h5
-rw-r--r--include/asm-arm/arch-ep93xx/irqs.h8
-rw-r--r--include/asm-arm/arch-ep93xx/platform.h1
-rw-r--r--include/asm-arm/arch-imx/entry-macro.S18
-rw-r--r--include/asm-arm/arch-iop32x/io.h10
-rw-r--r--include/asm-arm/arch-iop33x/io.h9
-rw-r--r--include/asm-arm/arch-ixp4xx/avila.h39
-rw-r--r--include/asm-arm/arch-ixp4xx/hardware.h1
-rw-r--r--include/asm-arm/arch-ixp4xx/irqs.h9
-rw-r--r--include/asm-arm/arch-ixp4xx/udc.h22
-rw-r--r--include/asm-arm/arch-ns9xxx/board.h18
-rw-r--r--include/asm-arm/arch-ns9xxx/clock.h37
-rw-r--r--include/asm-arm/arch-ns9xxx/debug-macro.S22
-rw-r--r--include/asm-arm/arch-ns9xxx/dma.h14
-rw-r--r--include/asm-arm/arch-ns9xxx/entry-macro.S22
-rw-r--r--include/asm-arm/arch-ns9xxx/hardware.h67
-rw-r--r--include/asm-arm/arch-ns9xxx/io.h20
-rw-r--r--include/asm-arm/arch-ns9xxx/irqs.h85
-rw-r--r--include/asm-arm/arch-ns9xxx/memory.h27
-rw-r--r--include/asm-arm/arch-ns9xxx/processor.h18
-rw-r--r--include/asm-arm/arch-ns9xxx/regs-bbu.h21
-rw-r--r--include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h24
-rw-r--r--include/asm-arm/arch-ns9xxx/regs-mem.h135
-rw-r--r--include/asm-arm/arch-ns9xxx/regs-sys.h157
-rw-r--r--include/asm-arm/arch-ns9xxx/system.h34
-rw-r--r--include/asm-arm/arch-ns9xxx/timex.h20
-rw-r--r--include/asm-arm/arch-ns9xxx/uncompress.h35
-rw-r--r--include/asm-arm/arch-ns9xxx/vmalloc.h16
-rw-r--r--include/asm-arm/arch-pxa/pxa-regs.h24
-rw-r--r--include/asm-arm/arch-pxa/udc.h30
-rw-r--r--include/asm-arm/arch-realview/hardware.h2
-rw-r--r--include/asm-arm/arch-realview/irqs.h17
-rw-r--r--include/asm-arm/arch-realview/platform.h18
-rw-r--r--include/asm-arm/arch-realview/scu.h8
-rw-r--r--include/asm-arm/arch-s3c2410/dma.h36
-rw-r--r--include/asm-arm/arch-s3c2410/irqs.h74
-rw-r--r--include/asm-arm/arch-s3c2410/regs-adc.h2
-rw-r--r--include/asm-arm/arch-s3c2410/regs-gpio.h32
-rw-r--r--include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h194
-rw-r--r--include/asm-arm/arch-s3c2410/regs-serial.h13
-rw-r--r--include/asm-arm/arch-s3c2410/reset.h22
-rw-r--r--include/asm-arm/arch-s3c2410/system.h15
-rw-r--r--include/asm-arm/arch-s3c2410/udc.h36
-rw-r--r--include/asm-arm/cacheflush.h49
-rw-r--r--include/asm-arm/checksum.h56
-rw-r--r--include/asm-arm/device.h10
-rw-r--r--include/asm-arm/dma-mapping.h18
-rw-r--r--include/asm-arm/domain.h1
-rw-r--r--include/asm-arm/hardware/arm_scu.h2
-rw-r--r--include/asm-arm/hardware/cache-l2x0.h56
-rw-r--r--include/asm-arm/hardware/gic.h5
-rw-r--r--include/asm-arm/hardware/iop3xx.h15
-rw-r--r--include/asm-arm/hardware/sa1111.h93
-rw-r--r--include/asm-arm/kexec.h30
-rw-r--r--include/asm-arm/pgtable.h54
-rw-r--r--include/asm-arm/plat-s3c24xx/clock.h (renamed from arch/arm/mach-s3c2410/clock.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/common-smdk.h (renamed from arch/arm/mach-s3c2410/common-smdk.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/cpu.h (renamed from arch/arm/mach-s3c2410/cpu.h)3
-rw-r--r--include/asm-arm/plat-s3c24xx/devs.h (renamed from arch/arm/mach-s3c2410/devs.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/dma.h (renamed from arch/arm/mach-s3c2410/dma.h)34
-rw-r--r--include/asm-arm/plat-s3c24xx/irq.h (renamed from arch/arm/mach-s3c2410/irq.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/pm.h (renamed from arch/arm/mach-s3c2410/pm.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2400.h (renamed from arch/arm/mach-s3c2410/s3c2400.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2410.h (renamed from arch/arm/mach-s3c2410/s3c2410.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2412.h (renamed from arch/arm/mach-s3c2410/s3c2412.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2440.h (renamed from arch/arm/mach-s3c2410/s3c2440.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2442.h (renamed from arch/arm/mach-s3c2410/s3c2442.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2443.h32
-rw-r--r--include/asm-arm/system.h62
-rw-r--r--include/asm-arm/tlbflush.h50
-rw-r--r--include/asm-arm/unistd.h1
-rw-r--r--include/asm-avr32/arch-at32ap/at91_pdc.h36
-rw-r--r--include/asm-i386/acpi.h1
-rw-r--r--include/asm-powerpc/atomic.h40
-rw-r--r--include/asm-powerpc/dcr-native.h4
-rw-r--r--include/asm-powerpc/pmi.h67
-rw-r--r--include/asm-powerpc/prom.h2
-rw-r--r--include/asm-powerpc/ps3.h27
-rw-r--r--include/asm-powerpc/ucc_slow.h8
-rw-r--r--include/linux/acpi.h8
-rw-r--r--include/linux/atmel_pdc.h36
-rw-r--r--include/linux/debugfs.h10
-rw-r--r--include/linux/device.h1
-rw-r--r--include/linux/ide.h28
-rw-r--r--include/linux/jffs.h224
-rw-r--r--include/linux/kexec.h1
-rw-r--r--include/linux/kmod.h2
-rw-r--r--include/linux/libata.h5
-rw-r--r--include/linux/module.h53
-rw-r--r--include/linux/moduleparam.h12
-rw-r--r--include/linux/pci.h3
-rw-r--r--include/linux/pci_ids.h1
-rw-r--r--include/linux/usb.h2
-rw-r--r--include/linux/usb/cdc.h7
-rw-r--r--include/linux/usb/ch9.h20
-rw-r--r--include/linux/usb/serial.h6
-rw-r--r--include/linux/usb_usual.h4
-rw-r--r--include/linux/usbdevice_fs.h4
-rw-r--r--include/pcmcia/ciscode.h1
-rw-r--r--include/rdma/ib_addr.h6
-rw-r--r--include/rdma/ib_sa.h159
-rw-r--r--include/rdma/rdma_cm.h21
-rw-r--r--include/rdma/rdma_cm_ib.h4
-rw-r--r--include/rdma/rdma_user_cm.h13
-rw-r--r--include/scsi/scsi_device.h1
-rw-r--r--kernel/kmod.c120
-rw-r--r--kernel/module.c47
-rw-r--r--kernel/params.c29
-rw-r--r--lib/kobject.c3
-rw-r--r--net/core/net-sysfs.c4
-rw-r--r--net/ieee80211/ieee80211_tx.c3
-rw-r--r--sound/arm/aaci.c315
-rw-r--r--sound/arm/aaci.h41
708 files changed, 25843 insertions, 17837 deletions
diff --git a/Documentation/acpi-hotkey.txt b/Documentation/acpi-hotkey.txt
deleted file mode 100644
index 38040fa3764..00000000000
--- a/Documentation/acpi-hotkey.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-driver/acpi/hotkey.c implement:
-1. /proc/acpi/hotkey/event_config
-(event based hotkey or event config interface):
-a. add a event based hotkey(event) :
-echo "0:bus::action:method:num:num" > event_config
-
-b. delete a event based hotkey(event):
-echo "1:::::num:num" > event_config
-
-c. modify a event based hotkey(event):
-echo "2:bus::action:method:num:num" > event_config
-
-2. /proc/acpi/hotkey/poll_config
-(polling based hotkey or event config interface):
-a.add a polling based hotkey(event) :
-echo "0:bus:method:action:method:num" > poll_config
-this adding command will create a proc file
-/proc/acpi/hotkey/method, which is used to get
-result of polling.
-
-b.delete a polling based hotkey(event):
-echo "1:::::num" > event_config
-
-c.modify a polling based hotkey(event):
-echo "2:bus:method:action:method:num" > poll_config
-
-3./proc/acpi/hotkey/action
-(interface to call aml method associated with a
-specific hotkey(event))
-echo "event_num:event_type:event_argument" >
- /proc/acpi/hotkey/action.
-The result of the execution of this aml method is
-attached to /proc/acpi/hotkey/poll_method, which is dynamically
-created. Please use command "cat /proc/acpi/hotkey/polling_method"
-to retrieve it.
-
-Note: Use cmdline "acpi_generic_hotkey" to over-ride
-platform-specific with generic driver.
diff --git a/Documentation/arm/Samsung-S3C24XX/DMA.txt b/Documentation/arm/Samsung-S3C24XX/DMA.txt
new file mode 100644
index 00000000000..37f4edcc5d8
--- /dev/null
+++ b/Documentation/arm/Samsung-S3C24XX/DMA.txt
@@ -0,0 +1,46 @@
+ S3C2410 DMA
+ ===========
+
+Introduction
+------------
+
+ The kernel provides an interface to manage DMA transfers
+ using the DMA channels in the cpu, so that the central
+ duty of managing channel mappings, and programming the
+ channel generators is in one place.
+
+
+DMA Channel Ordering
+--------------------
+
+ Many of the range do not have connections for the DMA
+ channels to all sources, which means that some devices
+ have a restricted number of channels that can be used.
+
+ To allow flexibilty for each cpu type and board, the
+ dma code can be given an dma ordering structure which
+ allows the order of channel search to be specified, as
+ well as allowing the prohibition of certain claims.
+
+ struct s3c24xx_dma_order has a list of channels, and
+ each channel within has a slot for a list of dma
+ channel numbers. The slots are searched in order, for
+ the presence of a dma channel number with DMA_CH_VALID
+ orred in.
+
+ If the order has the flag DMA_CH_NEVER set, then after
+ checking the channel list, the system will return no
+ found channel, thus denying the request.
+
+ A board support file can call s3c24xx_dma_order_set()
+ to register an complete ordering set. The routine will
+ copy the data, so the original can be discared with
+ __initdata.
+
+
+Authour
+-------
+
+Ben Dooks,
+Copyright (c) 2007 Ben Dooks, Simtec Electronics
+Licensed under the GPL v2
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
index 28d014714ab..c31b76fa66c 100644
--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
@@ -8,13 +8,10 @@ Introduction
The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
- S3C2440 and S3C2442 devices are supported.
+ S3C2412, S3C2413, S3C2440 and S3C2442 devices are supported.
Support for the S3C2400 series is in progress.
- Support for the S3C2412 and S3C2413 CPUs is being merged.
-
-
Configuration
-------------
@@ -26,6 +23,22 @@ Configuration
please check the machine specific documentation.
+Layout
+------
+
+ The core support files are located in the platform code contained in
+ arch/arm/plat-s3c24xx with headers in include/asm-arm/plat-s3c24xx.
+ This directory should be kept to items shared between the platform
+ code (arch/arm/plat-s3c24xx) and the arch/arm/mach-s3c24* code.
+
+ Each cpu has a directory with the support files for it, and the
+ machines that carry the device. For example S3C2410 is contained
+ in arch/arm/mach-s3c2410 and S3C2440 in arch/arm/mach-s3c2440
+
+ Register, kernel and platform data definitions are held in the
+ include/asm-arm/arch-s3c2410 directory.
+
+
Machines
--------
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index c585aa8d62b..6a451f47d40 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -253,29 +253,6 @@ Who: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
---------------------------
-<<<<<<< test:Documentation/feature-removal-schedule.txt
-What: ACPI hotkey driver (CONFIG_ACPI_HOTKEY)
-When: 2.6.21
-Why: hotkey.c was an attempt to consolidate multiple drivers that use
- ACPI to implement hotkeys. However, hotkeys are not documented
- in the ACPI specification, so the drivers used undocumented
- vendor-specific hooks and turned out to be more different than
- the same.
-
- Further, the keys and the features supplied by each platform
- are different, so there will always be a need for
- platform-specific drivers.
-
- So the new plan is to delete hotkey.c and instead, work on the
- platform specific drivers to try to make them look the same
- to the user when they supply the same features.
-
- hotkey.c has always depended on CONFIG_EXPERIMENTAL
-
-Who: Len Brown <len.brown@intel.com>
-
----------------------------
-
What: /sys/firmware/acpi/namespace
When: 2.6.21
Why: The ACPI namespace is effectively the symbol list for
@@ -306,13 +283,6 @@ Who: Len Brown <len.brown@intel.com>
---------------------------
-What: JFFS (version 1)
-When: 2.6.21
-Why: Unmaintained for years, superceded by JFFS2 for years.
-Who: Jeff Garzik <jeff@garzik.org>
-
----------------------------
-
What: sk98lin network driver
When: July 2007
Why: In kernel tree version of driver is unmaintained. Sk98lin driver
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f6a3961da34..c479d30eeaa 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -48,6 +48,7 @@ parameter is applicable:
ISAPNP ISA PnP code is enabled.
ISDN Appropriate ISDN support is enabled.
JOY Appropriate joystick support is enabled.
+ LIBATA Libata driver is enabled
LP Printer support is enabled.
LOOP Loopback device support is enabled.
M68k M68k architecture is enabled.
@@ -1045,6 +1046,10 @@ and is between 256 and 4096 characters. It is defined in the file
emulation library even if a 387 maths coprocessor
is present.
+ noacpi [LIBATA] Disables use of ACPI in libata suspend/resume
+ when set.
+ Format: <int>
+
noaliencache [MM, NUMA] Disables the allcoation of alien caches in
the slab allocator. Saves per-node memory, but will
impact performance on real NUMA hardware.
@@ -1282,6 +1287,12 @@ and is between 256 and 4096 characters. It is defined in the file
This sorting is done to get a device
order compatible with older (<= 2.4) kernels.
nobfsort Don't sort PCI devices into breadth-first order.
+ cbiosize=nn[KMG] The fixed amount of bus space which is
+ reserved for the CardBus bridge's IO window.
+ The default value is 256 bytes.
+ cbmemsize=nn[KMG] The fixed amount of bus space which is
+ reserved for the CardBus bridge's memory
+ window. The default value is 64 megabytes.
pcmv= [HW,PCMCIA] BadgePAD 4
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index fd5028eca13..cdf2f3c0ab1 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -205,8 +205,8 @@ Tips on when/where to use the above attributes:
exclusively called by the probe() routine, can be marked __devinit.
Ditto for remove() and __devexit.
- o If mydriver_probe() is marked with __devinit(), then all address
- references to mydriver_probe must use __devexit_p(mydriver_probe)
+ o If mydriver_remove() is marked with __devexit(), then all address
+ references to mydriver_remove must use __devexit_p(mydriver_remove)
(in the struct pci_driver declaration for example).
__devexit_p() will generate the function name _or_ NULL if the
function will be discarded. For an example, see drivers/net/tg3.c.
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 3b514672b80..b41397d6430 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -497,7 +497,7 @@ looks like in practice.
| |- device_type = "cpu"
| |- reg = <0>
| |- clock-frequency = <5f5e1000>
- | |- linux,boot-cpu
+ | |- 64-bit
| |- linux,phandle = <2>
|
o memory@0
@@ -509,7 +509,6 @@ looks like in practice.
o chosen
|- name = "chosen"
|- bootargs = "root=/dev/sda2"
- |- linux,platform = <00000600>
|- linux,phandle = <4>
This tree is almost a minimal tree. It pretty much contains the
@@ -519,7 +518,7 @@ physical memory layout. It also includes misc information passed
through /chosen, like in this example, the platform type (mandatory)
and the kernel command line arguments (optional).
-The /cpus/PowerPC,970@0/linux,boot-cpu property is an example of a
+The /cpus/PowerPC,970@0/64-bit property is an example of a
property without a value. All other properties have a value. The
significance of the #address-cells and #size-cells properties will be
explained in chapter IV which defines precisely the required nodes and
@@ -733,8 +732,7 @@ address which can extend beyond that limit.
that typically get driven by the same platform code in the
kernel, you would use a different "model" property but put a
value in "compatible". The kernel doesn't directly use that
- value (see /chosen/linux,platform for how the kernel chooses a
- platform type) but it is generally useful.
+ value but it is generally useful.
The root node is also generally where you add additional properties
specific to your board like the serial number if any, that sort of
@@ -778,7 +776,6 @@ address which can extend beyond that limit.
bytes
- d-cache-size : one cell, size of L1 data cache in bytes
- i-cache-size : one cell, size of L1 instruction cache in bytes
- - linux, boot-cpu : Should be defined if this cpu is the boot cpu.
Recommended properties:
@@ -843,11 +840,6 @@ address which can extend beyond that limit.
the prom_init() trampoline when booting with an OF client interface,
but that you have to provide yourself when using the flattened format.
- Required properties:
-
- - linux,platform : This is your platform number as assigned by the
- architecture maintainers
-
Recommended properties:
- bootargs : This zero-terminated string is passed as the kernel
diff --git a/Documentation/sony-laptop.txt b/Documentation/sony-laptop.txt
new file mode 100644
index 00000000000..dfd26df056f
--- /dev/null
+++ b/Documentation/sony-laptop.txt
@@ -0,0 +1,106 @@
+Sony Notebook Control Driver (SNC) Readme
+-----------------------------------------
+ Copyright (C) 2004- 2005 Stelian Pop <stelian@popies.net>
+ Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
+
+This mini-driver drives the SNC device present in the ACPI BIOS of
+the Sony Vaio laptops.
+
+It gives access to some extra laptop functionalities. In its current
+form, this driver let the user set or query the screen brightness
+through the backlight subsystem and remove/apply power to some devices.
+
+Backlight control:
+------------------
+If your laptop model supports it, you will find sysfs files in the
+/sys/class/backlight/sony/
+directory. You will be able to query and set the current screen
+brightness:
+ brightness get/set screen brightness (an iteger
+ between 0 and 7)
+ actual_brightness reading from this file will query the HW
+ to get real brightness value
+ max_brightness the maximum brightness value
+
+
+Platform specific:
+------------------
+Loading the sony-laptop module will create a
+/sys/devices/platform/sony-laptop/
+directory populated with some files.
+
+You then read/write integer values from/to those files by using
+standard UNIX tools.
+
+The files are:
+ brightness_default screen brightness which will be set
+ when the laptop will be rebooted
+ cdpower power on/off the internal CD drive
+ audiopower power on/off the internal sound card
+ lanpower power on/off the internal ethernet card
+ (only in debug mode)
+
+Note that some files may be missing if they are not supported
+by your particular laptop model.
+
+Example usage:
+ # echo "1" > /sys/devices/platform/sony-laptop/brightness_default
+sets the lowest screen brightness for the next and later reboots,
+ # echo "8" > /sys/devices/platform/sony-laptop/brightness_default
+sets the highest screen brightness for the next and later reboots,
+ # cat /sys/devices/platform/sony-laptop/brightness_default
+retrieves the value.
+
+ # echo "0" > /sys/devices/platform/sony-laptop/audiopower
+powers off the sound card,
+ # echo "1" > /sys/devices/platform/sony-laptop/audiopower
+powers on the sound card.
+
+Development:
+------------
+
+If you want to help with the development of this driver (and
+you are not afraid of any side effects doing strange things with
+your ACPI BIOS could have on your laptop), load the driver and
+pass the option 'debug=1'.
+
+REPEAT: DON'T DO THIS IF YOU DON'T LIKE RISKY BUSINESS.
+
+In your kernel logs you will find the list of all ACPI methods
+the SNC device has on your laptop. You can see the GCDP/GCDP methods
+used to pwer on/off the CD drive, but there are others.
+
+I HAVE NO IDEA WHAT THOSE METHODS DO.
+
+The sony-laptop driver creates, for some of those methods (the most
+current ones found on several Vaio models), an entry under
+/sys/devices/platform/sony-laptop, just like the 'cdpower' one.
+You can create other entries corresponding to your own laptop methods by
+further editing the source (see the 'sony_acpi_values' table, and add a new
+entry to this table with your get/set method names using the
+HANDLE_NAMES macro).
+
+Your mission, should you accept it, is to try finding out what
+those entries are for, by reading/writing random values from/to those
+files and find out what is the impact on your laptop.
+
+Should you find anything interesting, please report it back to me,
+I will not disavow all knowledge of your actions :)
+
+Bugs/Limitations:
+-----------------
+
+* This driver is not based on official documentation from Sony
+ (because there is none), so there is no guarantee this driver
+ will work at all, or do the right thing. Although this hasn't
+ happened to me, this driver could do very bad things to your
+ laptop, including permanent damage.
+
+* The sony-laptop and sonypi drivers do not interact at all. In the
+ future, sonypi could use sony-laptop to do (part of) its business.
+
+* spicctrl, which is the userspace tool used to communicate with the
+ sonypi driver (through /dev/sonypi) does not try to use the
+ sony-laptop driver. In the future, spicctrl could try sonypi first,
+ and if it isn't present, try sony-laptop instead.
+
diff --git a/MAINTAINERS b/MAINTAINERS
index b0fd71b3f66..270c6b006b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -247,6 +247,13 @@ L: linux-acpi@vger.kernel.org
W: http://acpi.sourceforge.net/
S: Supported
+ACPI VIDEO DRIVER
+P: Luming Yu
+M: luming.yu@intel.com
+L: linux-acpi@vger.kernel.org
+W: http://acpi.sourceforge.net/
+S: Supported
+
AD1816 SOUND DRIVER
P: Thorsten Knabe
M: Thorsten Knabe <linux@thorsten-knabe.de>
@@ -2623,8 +2630,8 @@ T: git kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
S: Maintained
PCNET32 NETWORK DRIVER
-P: Thomas Bogendörfer
-M: tsbogend@alpha.franken.de
+P: Don Fry
+M: pcnet32@verizon.net
L: netdev@vger.kernel.org
S: Maintained
@@ -3061,6 +3068,8 @@ S: Maintained
SONY VAIO CONTROL DEVICE DRIVER
P: Stelian Pop
M: stelian@popies.net
+P: Mattia Dongili
+M: malattia@linux.it
W: http://popies.net/sonypi/
S: Maintained
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 77d062eaf08..4409561ea32 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -245,6 +245,8 @@ config ARCH_IOP33X
config ARCH_IOP13XX
bool "IOP13xx-based"
+ depends on MMU
+ select PLAT_IOP
select PCI
help
Support for Intel's IOP13XX (XScale) family of processors.
@@ -283,6 +285,14 @@ config ARCH_L7200
If you have any questions or comments about the Linux kernel port
to this board, send e-mail to <sjhill@cotw.com>.
+config ARCH_NS9XXX
+ bool "NetSilicon NS9xxx"
+ help
+ Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
+ System.
+
+ <http://www.digi.com/products/microprocessors/index.jsp>
+
config ARCH_PNX4008
bool "Philips Nexperia PNX4008 Mobile"
help
@@ -292,6 +302,7 @@ config ARCH_PXA
bool "PXA2xx-based"
depends on MMU
select ARCH_MTD_XIP
+ select GENERIC_TIME
help
Support for Intel's PXA2XX processor line.
@@ -316,7 +327,7 @@ config ARCH_SA1100
Support for StrongARM 11x0 based boards.
config ARCH_S3C2410
- bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442"
+ bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
help
Samsung S3C2410X CPU based systems, such as the Simtec Electronics
BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -376,7 +387,16 @@ source "arch/arm/mach-omap1/Kconfig"
source "arch/arm/mach-omap2/Kconfig"
+source "arch/arm/plat-s3c24xx/Kconfig"
+
+if ARCH_S3C2410
+source "arch/arm/mach-s3c2400/Kconfig"
source "arch/arm/mach-s3c2410/Kconfig"
+source "arch/arm/mach-s3c2412/Kconfig"
+source "arch/arm/mach-s3c2440/Kconfig"
+source "arch/arm/mach-s3c2442/Kconfig"
+source "arch/arm/mach-s3c2443/Kconfig"
+endif
source "arch/arm/mach-lh7a40x/Kconfig"
@@ -390,10 +410,12 @@ source "arch/arm/mach-aaec2000/Kconfig"
source "arch/arm/mach-realview/Kconfig"
-source "arch/arm/mach-at91rm9200/Kconfig"
+source "arch/arm/mach-at91/Kconfig"
source "arch/arm/mach-netx/Kconfig"
+source "arch/arm/mach-ns9xxx/Kconfig"
+
# Definitions to make life easier
config ARCH_ACORN
bool
@@ -751,6 +773,20 @@ config XIP_PHYS_ADDR
be linked for and stored to. This address is dependent on your
own flash usage.
+config KEXEC
+ bool "Kexec system call (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ kexec is a system call that implements the ability to shutdown your
+ current kernel, and to start another kernel. It is like a reboot
+ but it is indepedent of the system firmware. And like a reboot
+ you can start any kernel with it, not just Linux.
+
+ It is an ongoing process to be certain the hardware in a machine
+ is properly shutdown, so do not be surprised if this code does not
+ initially work for you. It may help to enable device hotplugging
+ support.
+
endmenu
if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 000f1100b55..1320418b5d6 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -124,10 +124,12 @@ endif
machine-$(CONFIG_ARCH_H720X) := h720x
machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
machine-$(CONFIG_ARCH_REALVIEW) := realview
- machine-$(CONFIG_ARCH_AT91) := at91rm9200
- machine-$(CONFIG_ARCH_EP93XX) := ep93xx
- machine-$(CONFIG_ARCH_PNX4008) := pnx4008
- machine-$(CONFIG_ARCH_NETX) := netx
+ machine-$(CONFIG_ARCH_AT91) := at91rm9200
+ machine-$(CONFIG_ARCH_EP93XX) := ep93xx
+ machine-$(CONFIG_ARCH_PNX4008) := pnx4008
+ machine-$(CONFIG_ARCH_NETX) := netx
+ machine-$(CONFIG_ARCH_NS9XXX) := ns9xxx
+ textofs-$(CONFIG_ARCH_NS9XXX) := 0x00108000
ifeq ($(CONFIG_ARCH_EBSA110),y)
# This is what happens if you forget the IOCS16 line.
@@ -149,7 +151,7 @@ MACHINE := arch/arm/mach-$(machine-y)/
else
MACHINE :=
endif
-
+
export TEXT_OFFSET GZFLAGS MMUEXT
# Do we have FASTFPE?
@@ -161,6 +163,11 @@ endif
# If we have a machine-specific directory, then include it in the build.
core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y += $(MACHINE)
+core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2400/
+core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2412/
+core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2440/
+core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2442/
+core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2443/
core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
core-$(CONFIG_VFP) += arch/arm/vfp/
@@ -168,6 +175,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/
# If we have a common platform directory, then include it in the build.
core-$(CONFIG_PLAT_IOP) += arch/arm/plat-iop/
core-$(CONFIG_ARCH_OMAP) += arch/arm/plat-omap/
+core-$(CONFIG_PLAT_S3C24XX) += arch/arm/plat-s3c24xx/
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/
diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
new file mode 100644
index 00000000000..171a0853caf
--- /dev/null
+++ b/arch/arm/boot/.gitignore
@@ -0,0 +1,2 @@
+Image
+zImage
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
new file mode 100644
index 00000000000..aefee20cbf9
--- /dev/null
+++ b/arch/arm/boot/compressed/.gitignore
@@ -0,0 +1 @@
+piggy.gz
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 2e635b814c1..6fbe7722aa4 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -32,7 +32,6 @@
#include <asm/cacheflush.h>
-#undef DEBUG
#undef STATS
#ifdef STATS
@@ -66,14 +65,13 @@ struct dmabounce_pool {
};
struct dmabounce_device_info {
- struct list_head node;
-
struct device *dev;
struct list_head safe_buffers;
#ifdef STATS
unsigned long total_allocs;
unsigned long map_op_count;
unsigned long bounce_count;
+ int attr_res;
#endif
struct dmabounce_pool small;
struct dmabounce_pool large;
@@ -81,33 +79,23 @@ struct dmabounce_device_info {
rwlock_t lock;
};
-static LIST_HEAD(dmabounce_devs);
-
#ifdef STATS
-static void print_alloc_stats(struct dmabounce_device_info *device_info)
+static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- printk(KERN_INFO
- "%s: dmabounce: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n",
- device_info->dev->bus_id,
- device_info->small.allocs, device_info->large.allocs,
+ struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
+ return sprintf(buf, "%lu %lu %lu %lu %lu %lu\n",
+ device_info->small.allocs,
+ device_info->large.allocs,
device_info->total_allocs - device_info->small.allocs -
device_info->large.allocs,
- device_info->total_allocs);
+ device_info->total_allocs,
+ device_info->map_op_count,
+ device_info->bounce_count);
}
-#endif
-
-/* find the given device in the dmabounce device list */
-static inline struct dmabounce_device_info *
-find_dmabounce_dev(struct device *dev)
-{
- struct dmabounce_device_info *d;
- list_for_each_entry(d, &dmabounce_devs, node)
- if (d->dev == dev)
- return d;
-
- return NULL;
-}
+static DEVICE_ATTR(dmabounce_stats, 0400, dmabounce_show, NULL);
+#endif
/* allocate a 'safe' buffer and keep track of it */
@@ -162,8 +150,6 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
if (pool)
pool->allocs++;
device_info->total_allocs++;
- if (device_info->total_allocs % 1000 == 0)
- print_alloc_stats(device_info);
#endif
write_lock_irqsave(&device_info->lock, flags);
@@ -218,20 +204,11 @@ free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *
/* ************************************************** */
-#ifdef STATS
-static void print_map_stats(struct dmabounce_device_info *device_info)
-{
- dev_info(device_info->dev,
- "dmabounce: map_op_count=%lu, bounce_count=%lu\n",
- device_info->map_op_count, device_info->bounce_count);
-}
-#endif
-
static inline dma_addr_t
map_single(struct device *dev, void *ptr, size_t size,
enum dma_data_direction dir)
{
- struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+ struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
dma_addr_t dma_addr;
int needs_bounce = 0;
@@ -281,10 +258,14 @@ map_single(struct device *dev, void *ptr, size_t size,
ptr = buf->safe;
dma_addr = buf->safe_dma_addr;
+ } else {
+ /*
+ * We don't need to sync the DMA buffer since
+ * it was allocated via the coherent allocators.
+ */
+ consistent_sync(ptr, size, dir);
}
- consistent_sync(ptr, size, dir);
-
return dma_addr;
}
@@ -292,7 +273,7 @@ static inline void
unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
- struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+ struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
struct safe_buffer *buf = NULL;
/*
@@ -317,12 +298,12 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
DO_STATS ( device_info->bounce_count++ );
if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
- unsigned long ptr;
+ void *ptr = buf->ptr;
dev_dbg(dev,
"%s: copy back safe %p to unsafe %p size %d\n",
- __func__, buf->safe, buf->ptr, size);
- memcpy(buf->ptr, buf->safe, size);
+ __func__, buf->safe, ptr, size);
+ memcpy(ptr, buf->safe, size);
/*
* DMA buffers must have the same cache properties
@@ -332,8 +313,8 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
* bidirectional case because we know the cache
* lines will be coherent with the data written.
*/
- ptr = (unsigned long)buf->ptr;
dmac_clean_range(ptr, ptr + size);
+ outer_clean_range(__pa(ptr), __pa(ptr) + size);
}
free_safe_buffer(device_info, buf);
}
@@ -343,7 +324,7 @@ static inline void
sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
- struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+ struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
struct safe_buffer *buf = NULL;
if (device_info)
@@ -397,7 +378,10 @@ sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
default:
BUG();
}
- consistent_sync(buf->safe, size, dir);
+ /*
+ * No need to sync the safe buffer - it was allocated
+ * via the coherent allocators.
+ */
} else {
consistent_sync(dma_to_virt(dev, dma_addr), size, dir);
}
@@ -604,9 +588,10 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
device_info->total_allocs = 0;
device_info->map_op_count = 0;
device_info->bounce_count = 0;
+ device_info->attr_res = device_create_file(dev, &dev_attr_dmabounce_stats);
#endif
- list_add(&device_info->node, &dmabounce_devs);
+ dev->archdata.dmabounce = device_info;
printk(KERN_INFO "dmabounce: registered device %s on %s bus\n",
dev->bus_id, dev->bus->name);
@@ -623,7 +608,9 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
void
dmabounce_unregister_dev(struct device *dev)
{
- struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+ struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
+
+ dev->archdata.dmabounce = NULL;
if (!device_info) {
printk(KERN_WARNING
@@ -645,12 +632,10 @@ dmabounce_unregister_dev(struct device *dev)
dma_pool_destroy(device_info->large.pool);
#ifdef STATS
- print_alloc_stats(device_info);
- print_map_stats(device_info);
+ if (device_info->attr_res == 0)
+ device_remove_file(dev, &dev_attr_dmabounce_stats);
#endif
- list_del(&device_info->node);
-
kfree(device_info);
printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n",
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 09b9d1b6844..4deece5fbdf 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -14,7 +14,9 @@
*
* o There is one CPU Interface per CPU, which sends interrupts sent
* by the Distributor, and interrupts generated locally, to the
- * associated CPU.
+ * associated CPU. The base address of the CPU interface is usually
+ * aliased so that the same address points to different chips depending
+ * on the CPU it is accessed from.
*
* Note that IRQs 0-31 are special - they are local to each CPU.
* As such, the enable set/clear, pending set/clear and active bit
@@ -31,10 +33,38 @@
#include <asm/mach/irq.h>
#include <asm/hardware/gic.h>
-static void __iomem *gic_dist_base;
-static void __iomem *gic_cpu_base;
static DEFINE_SPINLOCK(irq_controller_lock);
+struct gic_chip_data {
+ unsigned int irq_offset;
+ void __iomem *dist_base;
+ void __iomem *cpu_base;
+};
+
+#ifndef MAX_GIC_NR
+#define MAX_GIC_NR 1
+#endif
+
+static struct gic_chip_data gic_data[MAX_GIC_NR];
+
+static inline void __iomem *gic_dist_base(unsigned int irq)
+{
+ struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+ return gic_data->dist_base;
+}
+
+static inline void __iomem *gic_cpu_base(unsigned int irq)
+{
+ struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+ return gic_data->cpu_base;
+}
+
+static inline unsigned int gic_irq(unsigned int irq)
+{
+ struct gic_chip_data *gic_data = get_irq_chip_data(irq);
+ return irq - gic_data->irq_offset;
+}
+
/*
* Routines to acknowledge, disable and enable interrupts
*
@@ -55,8 +85,8 @@ static void gic_ack_irq(unsigned int irq)
u32 mask = 1 << (irq % 32);
spin_lock(&irq_controller_lock);
- writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
- writel(irq, gic_cpu_base + GIC_CPU_EOI);
+ writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
+ writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI);
spin_unlock(&irq_controller_lock);
}
@@ -65,7 +95,7 @@ static void gic_mask_irq(unsigned int irq)
u32 mask = 1 << (irq % 32);
spin_lock(&irq_controller_lock);
- writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4);
+ writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
spin_unlock(&irq_controller_lock);
}
@@ -74,14 +104,14 @@ static void gic_unmask_irq(unsigned int irq)
u32 mask = 1 << (irq % 32);
spin_lock(&irq_controller_lock);
- writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4);
+ writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_SET + (gic_irq(irq) / 32) * 4);
spin_unlock(&irq_controller_lock);
}
#ifdef CONFIG_SMP
static void gic_set_cpu(unsigned int irq, cpumask_t mask_val)
{
- void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3);
+ void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
unsigned int shift = (irq % 4) * 8;
unsigned int cpu = first_cpu(mask_val);
u32 val;
@@ -95,6 +125,37 @@ static void gic_set_cpu(unsigned int irq, cpumask_t mask_val)
}
#endif
+static void fastcall gic_handle_cascade_irq(unsigned int irq,
+ struct irq_desc *desc)
+{
+ struct gic_chip_data *chip_data = get_irq_data(irq);
+ struct irq_chip *chip = get_irq_chip(irq);
+ unsigned int cascade_irq;
+ unsigned long status;
+
+ /* primary controller ack'ing */
+ chip->ack(irq);
+
+ spin_lock(&irq_controller_lock);
+ status = readl(chip_data->cpu_base + GIC_CPU_INTACK);
+ spin_unlock(&irq_controller_lock);
+
+ cascade_irq = (status & 0x3ff);
+ if (cascade_irq > 1020)
+ goto out;
+ if (cascade_irq < 32 || cascade_irq >= NR_IRQS) {
+ do_bad_IRQ(cascade_irq, desc);
+ goto out;
+ }
+
+ cascade_irq += chip_data->irq_offset;
+ generic_handle_irq(cascade_irq);
+
+ out:
+ /* primary controller unmasking */
+ chip->unmask(irq);
+}
+
static struct irq_chip gic_chip = {
.name = "GIC",
.ack = gic_ack_irq,
@@ -105,15 +166,29 @@ static struct irq_chip gic_chip = {
#endif
};
-void __init gic_dist_init(void __iomem *base)
+void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
+{
+ if (gic_nr >= MAX_GIC_NR)
+ BUG();
+ if (set_irq_data(irq, &gic_data[gic_nr]) != 0)
+ BUG();
+ set_irq_chained_handler(irq, gic_handle_cascade_irq);
+}
+
+void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
+ unsigned int irq_start)
{
unsigned int max_irq, i;
u32 cpumask = 1 << smp_processor_id();
+ if (gic_nr >= MAX_GIC_NR)
+ BUG();
+
cpumask |= cpumask << 8;
cpumask |= cpumask << 16;
- gic_dist_base = base;
+ gic_data[gic_nr].dist_base = base;
+ gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
writel(0, base + GIC_DIST_CTRL);
@@ -158,8 +233,9 @@ void __init gic_dist_init(void __iomem *base)
/*
* Setup the Linux IRQ subsystem.
*/
- for (i = 29; i < max_irq; i++) {
+ for (i = irq_start; i < gic_data[gic_nr].irq_offset + max_irq; i++) {
set_irq_chip(i, &gic_chip);
+ set_irq_chip_data(i, &gic_data[gic_nr]);
set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
@@ -167,9 +243,13 @@ void __init gic_dist_init(void __iomem *base)
writel(1, base + GIC_DIST_CTRL);
}
-void __cpuinit gic_cpu_init(void __iomem *base)
+void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
{
- gic_cpu_base = base;
+ if (gic_nr >= MAX_GIC_NR)
+ BUG();
+
+ gic_data[gic_nr].cpu_base = base;
+
writel(0xf0, base + GIC_CPU_PRIMASK);
writel(1, base + GIC_CPU_CTRL);
}
@@ -179,6 +259,7 @@ void gic_raise_softirq(cpumask_t cpumask, unsigned int irq)
{
unsigned long map = *cpus_addr(cpumask);
- writel(map << 16 | irq, gic_dist_base + GIC_DIST_SOFTINT);
+ /* this always happens on GIC0 */
+ writel(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
}
#endif
diff --git a/arch/arm/configs/at91sam9263ek_defconfig b/arch/arm/configs/at91sam9263ek_defconfig
new file mode 100644
index 00000000000..c72ab82873d
--- /dev/null
+++ b/arch/arm/configs/at91sam9263ek_defconfig
@@ -0,0 +1,1184 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20-rc1
+# Mon Jan 8 16:06:54 2007
+#
+CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+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"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+CONFIG_ARCH_AT91=y
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Atmel AT91 System-on-Chip
+#
+# CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_AT91SAM9260 is not set
+# CONFIG_ARCH_AT91SAM9261 is not set
+CONFIG_ARCH_AT91SAM9263=y
+
+#
+# AT91SAM9263 Board Type
+#
+CONFIG_MACH_AT91SAM9263EK=y
+
+#
+# AT91 Board Options
+#
+CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set
+
+#
+# AT91 Feature Selections
+#
+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE 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_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP 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_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# 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 is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET 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
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# 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
+
+#
+# QoS and/or fair queueing
+#
+# 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_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
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE 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_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_DATAFLASH=y
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# 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
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_AT91=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# 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=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=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=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# 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_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_TSDEV=y
+CONFIG_INPUT_TSDEV_SCREEN_X=240
+CONFIG_INPUT_TSDEV_SCREEN_Y=320
+CONFIG_INPUT_EVDEV=y
+# 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_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
+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=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# 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_AT91=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 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_SENSORS_MAX6875 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
+#
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_ATMEL=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+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_MULTITHREAD_PROBE is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_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'
+#
+
+#
+# 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_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_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID 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_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK 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_MII is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# 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_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_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_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+CONFIG_USB_GADGET_AT91=y
+CONFIG_USB_AT91=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ETH is not set
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_AT91=m
+# CONFIG_MMC_TIFM_SD is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP 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_FAT_FS=y
+# CONFIG_MSDOS_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
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=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_RAMFS=y
+# 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_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+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
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 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_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# 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_9P_FS is not set
+
+#
+# Partition Types
+#
+# 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=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII 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
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# 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 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+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=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig
index 3de5c643848..baa97698c74 100644
--- a/arch/arm/configs/ateb9200_defconfig
+++ b/arch/arm/configs/ateb9200_defconfig
@@ -1066,7 +1066,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_RS5C372 is not set
# CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_AT91=y
+CONFIG_RTC_DRV_AT91RM9200=y
# CONFIG_RTC_DRV_TEST is not set
#
diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig
index 2cadd51506b..88e5d28aeec 100644
--- a/arch/arm/configs/csb337_defconfig
+++ b/arch/arm/configs/csb337_defconfig
@@ -355,10 +355,12 @@ CONFIG_MTD_CFI_UTIL=y
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_PLATRAM is not set
-CONFIG_MTD_CSB337=y
#
# Self-contained MTD device drivers
@@ -986,7 +988,7 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_RS5C372 is not set
# CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_AT91=y
+CONFIG_RTC_DRV_AT91RM9200=y
# CONFIG_RTC_DRV_TEST is not set
# CONFIG_RTC_DRV_V3020 is not set
diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig
index 94908c1df4c..669f035896f 100644
--- a/arch/arm/configs/csb637_defconfig
+++ b/arch/arm/configs/csb637_defconfig
@@ -355,10 +355,12 @@ CONFIG_MTD_CFI_UTIL=y
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_PLATRAM is not set
-CONFIG_MTD_CSB637=y
#
# Self-contained MTD device drivers
diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig
index a4cdafc1548..a0f48d54fbc 100644
--- a/arch/arm/configs/kafa_defconfig
+++ b/arch/arm/configs/kafa_defconfig
@@ -718,7 +718,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_RS5C372 is not set
# CONFIG_RTC_DRV_M48T86 is not set
-CONFIG_RTC_DRV_AT91=y
+CONFIG_RTC_DRV_AT91RM9200=y
# CONFIG_RTC_DRV_TEST is not set
#
diff --git a/arch/arm/configs/ns9xxx_defconfig b/arch/arm/configs/ns9xxx_defconfig
new file mode 100644
index 00000000000..0e5794c6a48
--- /dev/null
+++ b/arch/arm/configs/ns9xxx_defconfig
@@ -0,0 +1,621 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+# Thu Feb 15 20:51:47 2007
+#
+CONFIG_ARM=y
+# CONFIG_GENERIC_TIME is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_UTS_NS is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+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_ALL is not set
+# 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_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+CONFIG_ARCH_NS9XXX=y
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# NS9xxx Implementations
+#
+CONFIG_MACH_CC9P9360DEV=y
+CONFIG_PROCESSOR_NS9360=y
+CONFIG_BOARD_A9M9750DEV=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE 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_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP 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_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# 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
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW 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 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 is not set
+# 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 is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
+# USB support
+#
+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'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP 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_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 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_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# 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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# 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=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_ICEDCC=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 3b31a33d008..df19e363203 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc4
-# Fri Nov 3 17:41:31 2006
+# Linux kernel version: 2.6.20
+# Thu Feb 15 11:26:24 2007
#
CONFIG_ARM=y
# CONFIG_GENERIC_TIME is not set
@@ -11,6 +11,8 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_VECTORS_BASE=0xffff0000
@@ -37,13 +39,14 @@ CONFIG_SYSVIPC=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -76,7 +79,9 @@ CONFIG_KMOD=y
# Block layer
#
CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -110,6 +115,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_IOP32X is not set
# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IOP13XX is not set
# CONFIG_ARCH_IXP4XX is not set
# CONFIG_ARCH_IXP2000 is not set
# CONFIG_ARCH_IXP23XX is not set
@@ -122,54 +128,73 @@ CONFIG_ARCH_S3C2410=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
+CONFIG_PLAT_S3C24XX=y
+CONFIG_CPU_S3C244X=y
+CONFIG_PM_SIMTEC=y
+# CONFIG_S3C2410_BOOT_WATCHDOG is not set
+# CONFIG_S3C2410_BOOT_ERROR_RESET is not set
+# CONFIG_S3C2410_PM_DEBUG is not set
+# CONFIG_S3C2410_PM_CHECK is not set
+CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
+CONFIG_S3C2410_DMA=y
+# CONFIG_S3C2410_DMA_DEBUG is not set
+CONFIG_MACH_SMDK=y
#
-# S3C24XX Implementations
+# S3C2400 Machines
#
-# CONFIG_MACH_AML_M5900 is not set
-CONFIG_MACH_ANUBIS=y
-CONFIG_MACH_OSIRIS=y
-CONFIG_ARCH_BAST=y
-CONFIG_BAST_PC104_IRQ=y
+CONFIG_CPU_S3C2410=y
+CONFIG_CPU_S3C2410_DMA=y
+CONFIG_S3C2410_PM=y
+CONFIG_S3C2410_GPIO=y
+CONFIG_S3C2410_CLOCK=y
+
+#
+# S3C2410 Machines
+#
+CONFIG_ARCH_SMDK2410=y
CONFIG_ARCH_H1940=y
+CONFIG_PM_H1940=y
CONFIG_MACH_N30=y
-CONFIG_MACH_SMDK=y
-CONFIG_ARCH_SMDK2410=y
-CONFIG_ARCH_S3C2440=y
-CONFIG_SMDK2440_CPU2440=y
-CONFIG_SMDK2440_CPU2442=y
-CONFIG_MACH_S3C2413=y
-CONFIG_MACH_SMDK2413=y
-CONFIG_MACH_VR1000=y
-CONFIG_MACH_RX3715=y
+CONFIG_ARCH_BAST=y
CONFIG_MACH_OTOM=y
-CONFIG_MACH_NEXCODER_2440=y
-CONFIG_MACH_VSTMS=y
-CONFIG_S3C2410_CLOCK=y
-CONFIG_S3C2410_PM=y
-CONFIG_CPU_S3C2410_DMA=y
-CONFIG_CPU_S3C2410=y
-CONFIG_S3C2412_PM=y
+CONFIG_MACH_AML_M5900=y
+CONFIG_BAST_PC104_IRQ=y
+CONFIG_MACH_VR1000=y
CONFIG_CPU_S3C2412=y
-CONFIG_CPU_S3C244X=y
+CONFIG_S3C2412_DMA=y
+CONFIG_S3C2412_PM=y
+
+#
+# S3C2412 Machines
+#
+CONFIG_MACH_SMDK2413=y
+CONFIG_MACH_S3C2413=y
+CONFIG_MACH_VSTMS=y
CONFIG_CPU_S3C2440=y
+CONFIG_S3C2440_DMA=y
+
+#
+# S3C2440 Machines
+#
+CONFIG_MACH_ANUBIS=y
+CONFIG_MACH_OSIRIS=y
+CONFIG_MACH_RX3715=y
+CONFIG_ARCH_S3C2440=y
+CONFIG_MACH_NEXCODER_2440=y
+CONFIG_SMDK2440_CPU2440=y
CONFIG_CPU_S3C2442=y
#
-# S3C2410 Boot
+# S3C2442 Machines
#
-# CONFIG_S3C2410_BOOT_WATCHDOG is not set
-# CONFIG_S3C2410_BOOT_ERROR_RESET is not set
+CONFIG_SMDK2440_CPU2442=y
+CONFIG_CPU_S3C2443=y
#
-# S3C2410 Setup
+# S3C2443 Machines
#
-CONFIG_S3C2410_DMA=y
-# CONFIG_S3C2410_DMA_DEBUG is not set
-# CONFIG_S3C2410_PM_DEBUG is not set
-# CONFIG_S3C2410_PM_CHECK is not set
-CONFIG_PM_SIMTEC=y
-CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
+CONFIG_MACH_SMDK2443=y
#
# Processor Type
@@ -196,6 +221,7 @@ CONFIG_CPU_CP15_MMU=y
# CONFIG_CPU_DCACHE_DISABLE is not set
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
#
# Bus support
@@ -303,6 +329,7 @@ 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
@@ -385,6 +412,7 @@ CONFIG_MTD_CMDLINE_PARTS=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
@@ -531,6 +559,11 @@ CONFIG_BLK_DEV_IDE_BAST=y
# CONFIG_SCSI_NETLINK is not set
#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
@@ -682,7 +715,7 @@ CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_DIGIEPCA is not set
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
-# CONFIG_ISI is not set
+# CONFIG_MOXA_SMARTIO_NEW is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_N_HDLC is not set
# CONFIG_RISCOM8 is not set
@@ -700,13 +733,14 @@ CONFIG_SERIAL_8250_NR_UARTS=8
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_RSA is not set
# CONFIG_SERIAL_8250_FOURPORT is not set
# CONFIG_SERIAL_8250_ACCENT is not set
# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set
# CONFIG_SERIAL_8250_HUB6 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
@@ -755,10 +789,6 @@ CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
#
@@ -863,6 +893,7 @@ CONFIG_SENSORS_LM85=m
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
@@ -870,6 +901,7 @@ CONFIG_SENSORS_LM85=m
# 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
@@ -952,6 +984,11 @@ CONFIG_FONT_8x16=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1028,6 +1065,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
@@ -1179,9 +1217,6 @@ 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_WRITEBUFFER=y
@@ -1191,7 +1226,7 @@ CONFIG_JFFS2_FS_WRITEBUFFER=y
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
@@ -1285,6 +1320,11 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -1296,6 +1336,8 @@ CONFIG_NLS_DEFAULT="iso8859-1"
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=y
CONFIG_LOG_BUF_SHIFT=16
CONFIG_DETECT_SOFTLOCKUP=y
@@ -1311,12 +1353,10 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FRAME_POINTER=y
CONFIG_FORCED_INLINING=y
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_ERRORS is not set
@@ -1339,6 +1379,7 @@ CONFIG_DEBUG_S3C2410_UART=0
#
# Library routines
#
+CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
@@ -1346,3 +1387,4 @@ CONFIG_CRC32=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 1b935fb94b8..bb28087bf81 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o
obj-$(CONFIG_PCI) += bios32.o isa.o
obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index f7598cbc7ec..ae89cdd82b1 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -356,6 +356,7 @@
CALL(sys_move_pages)
/* 345 */ CALL(sys_getcpu)
CALL(sys_ni_syscall) /* eventually epoll_pwait */
+ CALL(sys_kexec_load)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
diff --git a/arch/arm/kernel/crunch.c b/arch/arm/kernel/crunch.c
index cec83783206..627d79414c9 100644
--- a/arch/arm/kernel/crunch.c
+++ b/arch/arm/kernel/crunch.c
@@ -75,6 +75,7 @@ static struct notifier_block crunch_notifier_block = {
static int __init crunch_init(void)
{
thread_register_notifier(&crunch_notifier_block);
+ elf_hwcap |= HWCAP_CRUNCH;
return 0;
}
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 71257e3d513..f1c0fb97417 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -1009,7 +1009,7 @@ ecard_probe(int slot, card_type_t type)
ec->fiqmask = 4;
}
- for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++)
+ for (i = 0; i < ARRAY_SIZE(blacklist); i++)
if (blacklist[i].manufacturer == ec->cid.manufacturer &&
blacklist[i].product == ec->cid.product) {
ec->card_desc = blacklist[i].type;
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 8517c3c3eb3..cc10a093a54 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -99,7 +99,6 @@ common_invalid:
@ cpsr_<exception>, "old_r0"
mov r0, sp
- and r2, r6, #0x1f
b bad_mode
/*
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
new file mode 100644
index 00000000000..863c66454f2
--- /dev/null
+++ b/arch/arm/kernel/machine_kexec.c
@@ -0,0 +1,78 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ */
+
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+#include <asm/mach-types.h>
+
+const extern unsigned char relocate_new_kernel[];
+const extern unsigned int relocate_new_kernel_size;
+
+extern void setup_mm_for_reboot(char mode);
+
+extern unsigned long kexec_start_address;
+extern unsigned long kexec_indirection_page;
+extern unsigned long kexec_mach_type;
+
+/*
+ * Provide a dummy crash_notes definition while crash dump arrives to arm.
+ * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
+ */
+
+int machine_kexec_prepare(struct kimage *image)
+{
+ return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+}
+
+void machine_shutdown(void)
+{
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+}
+
+void machine_kexec(struct kimage *image)
+{
+ unsigned long page_list;
+ unsigned long reboot_code_buffer_phys;
+ void *reboot_code_buffer;
+
+
+ page_list = image->head & PAGE_MASK;
+
+ /* we need both effective and real address here */
+ reboot_code_buffer_phys =
+ page_to_pfn(image->control_code_page) << PAGE_SHIFT;
+ reboot_code_buffer = page_address(image->control_code_page);
+
+ /* Prepare parameters for reboot_code_buffer*/
+ kexec_start_address = image->start;
+ kexec_indirection_page = page_list;
+ kexec_mach_type = machine_arch_type;
+
+ /* copy our kernel relocation code to the control code page */
+ memcpy(reboot_code_buffer,
+ relocate_new_kernel, relocate_new_kernel_size);
+
+
+ flush_icache_range((unsigned long) reboot_code_buffer,
+ (unsigned long) reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
+ printk(KERN_INFO "Bye!\n");
+
+ cpu_proc_fin();
+ setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
+ cpu_reset(reboot_code_buffer_phys);
+}
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index a9e8f7e55fd..782af3cb213 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -36,7 +36,13 @@
#include <asm/uaccess.h>
#include <asm/mach/time.h>
-extern const char *processor_modes[];
+static const char *processor_modes[] = {
+ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
+ "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
+ "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
+ "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
+};
+
extern void setup_mm_for_reboot(char mode);
static volatile int hlt_counter;
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
new file mode 100644
index 00000000000..7baadae7cb2
--- /dev/null
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -0,0 +1,74 @@
+/*
+ * relocate_kernel.S - put the kernel image in place to boot
+ */
+
+#include <asm/kexec.h>
+
+ .globl relocate_new_kernel
+relocate_new_kernel:
+
+ ldr r0,kexec_indirection_page
+ ldr r1,kexec_start_address
+
+
+0: /* top, read another word for the indirection page */
+ ldr r3, [r0],#4
+
+ /* Is it a destination page. Put destination address to r4 */
+ tst r3,#1,0
+ beq 1f
+ bic r4,r3,#1
+ b 0b
+1:
+ /* Is it an indirection page */
+ tst r3,#2,0
+ beq 1f
+ bic r0,r3,#2
+ b 0b
+1:
+
+ /* are we done ? */
+ tst r3,#4,0
+ beq 1f
+ b 2f
+
+1:
+ /* is it source ? */
+ tst r3,#8,0
+ beq 0b
+ bic r3,r3,#8
+ mov r6,#1024
+9:
+ ldr r5,[r3],#4
+ str r5,[r4],#4
+ subs r6,r6,#1
+ bne 9b
+ b 0b
+
+2:
+ /* Jump to relocated kernel */
+ mov lr,r1
+ mov r0,#0
+ ldr r1,kexec_mach_type
+ mov r2,#0
+ mov pc,lr
+
+ .globl kexec_start_address
+kexec_start_address:
+ .long 0x0
+
+ .globl kexec_indirection_page
+kexec_indirection_page:
+ .long 0x0
+
+ .globl kexec_mach_type
+kexec_mach_type:
+ .long 0x0
+
+relocate_new_kernel_end:
+
+ .globl relocate_new_kernel_size
+relocate_new_kernel_size:
+ .long relocate_new_kernel_end - relocate_new_kernel
+
+
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index ed522151878..03e37af315d 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -88,6 +88,9 @@ struct cpu_user_fns cpu_user;
#ifdef MULTI_CACHE
struct cpu_cache_fns cpu_cache;
#endif
+#ifdef CONFIG_OUTER_CACHE
+struct outer_cache_fns outer_cache;
+#endif
struct stack {
u32 irq[3];
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index ee47c532e21..f61decb89ba 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -40,12 +40,14 @@
*/
struct sys_timer *system_timer;
+#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
/* this needs a better home */
DEFINE_SPINLOCK(rtc_lock);
-#ifdef CONFIG_SA1100_RTC_MODULE
+#ifdef CONFIG_RTC_DRV_CMOS_MODULE
EXPORT_SYMBOL(rtc_lock);
#endif
+#endif /* pc-style 'CMOS' RTC support */
/* change this if you have some constant time drift */
#define USECS_PER_JIFFY (1000000/HZ)
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 908915675ed..24095601359 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -32,13 +32,6 @@
#include "ptrace.h"
#include "signal.h"
-const char *processor_modes[]=
-{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
- "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
- "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
- "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
-};
-
static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
#ifdef CONFIG_DEBUG_USER
@@ -289,7 +282,10 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
regs->ARM_pc -= correction;
pc = (void __user *)instruction_pointer(regs);
- if (thumb_mode(regs)) {
+
+ if (processor_mode(regs) == SVC_MODE) {
+ instr = *(u32 *) pc;
+ } else if (thumb_mode(regs)) {
get_user(instr, (u16 __user *)pc);
} else {
get_user(instr, (u32 __user *)pc);
@@ -337,12 +333,11 @@ asmlinkage void do_unexp_fiq (struct pt_regs *regs)
* It never returns, and never tries to sync. We hope that we can at least
* dump out some state information...
*/
-asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
+asmlinkage void bad_mode(struct pt_regs *regs, int reason)
{
console_verbose();
- printk(KERN_CRIT "Bad mode in %s handler detected: mode %s\n",
- handler[reason], processor_modes[proc_mode]);
+ printk(KERN_CRIT "Bad mode in %s handler detected\n", handler[reason]);
die("Oops - bad mode", regs, 0);
local_irq_disable();
diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91/Kconfig
index 9f11db8af23..bf0d96272e3 100644
--- a/arch/arm/mach-at91rm9200/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -9,11 +9,14 @@ config ARCH_AT91RM9200
bool "AT91RM9200"
config ARCH_AT91SAM9260
- bool "AT91SAM9260"
+ bool "AT91SAM9260 or AT91SAM9XE"
config ARCH_AT91SAM9261
bool "AT91SAM9261"
+config ARCH_AT91SAM9263
+ bool "AT91SAM9263"
+
endchoice
# ----------------------------------------------------------
@@ -90,13 +93,22 @@ endif
if ARCH_AT91SAM9260
-comment "AT91SAM9260 Board Type"
+comment "AT91SAM9260 Variants"
+
+config ARCH_AT91SAM9260_SAM9XE
+ bool "AT91SAM9XE"
+ depends on ARCH_AT91SAM9260
+ help
+ Select this if you are using Atmel's AT91SAM9XE System-on-Chip.
+ They are basicaly AT91SAM9260s with various sizes of embedded Flash.
+
+comment "AT91SAM9260 / AT91SAM9XE Board Type"
config MACH_AT91SAM9260EK
- bool "Atmel AT91SAM9260-EK Evaluation Kit"
+ bool "Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit"
depends on ARCH_AT91SAM9260
help
- Select this if you are using Atmel's AT91SAM9260-EK Evaluation Kit.
+ Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit
<http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
endif
@@ -118,17 +130,32 @@ endif
# ----------------------------------------------------------
+if ARCH_AT91SAM9263
+
+comment "AT91SAM9263 Board Type"
+
+config MACH_AT91SAM9263EK
+ bool "Atmel AT91SAM9263-EK Evaluation Kit"
+ depends on ARCH_AT91SAM9263
+ help
+ Select this if you are using Atmel's AT91SAM9263-EK Evaluation Kit.
+ <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4057>
+
+endif
+
+# ----------------------------------------------------------
+
comment "AT91 Board Options"
config MTD_AT91_DATAFLASH_CARD
bool "Enable DataFlash Card support"
- depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK)
+ depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK)
help
Enable support for the DataFlash card.
config MTD_NAND_AT91_BUSWIDTH_16
bool "Enable 16-bit data bus interface to NAND flash"
- depends on (MACH_AT91SAM9261EK || MACH_AT91SAM9260EK)
+ depends on (MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK)
help
On AT91SAM926x boards both types of NAND flash can be present
(8 and 16 bit data bus width).
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91/Makefile
index cf777007847..05de6cdc88f 100644
--- a/arch/arm/mach-at91rm9200/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o
obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o
+obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o
# AT91RM9200 board-specific support
obj-$(CONFIG_MACH_ONEARM) += board-1arm.o
@@ -31,6 +32,9 @@ obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
# AT91SAM9261 board-specific support
obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
+# AT91SAM9263 board-specific support
+obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o
+
# LEDs support
led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o
led-$(CONFIG_MACH_AT91RM9200EK) += leds.o
diff --git a/arch/arm/mach-at91rm9200/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
index e667dcc7cd3..e667dcc7cd3 100644
--- a/arch/arm/mach-at91rm9200/Makefile.boot
+++ b/arch/arm/mach-at91/Makefile.boot
diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index a92e9a495b0..2ddcdd69df7 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-at91rm9200/at91rm9200.c
+ * arch/arm/mach-at91/at91rm9200.c
*
* Copyright (C) 2005 SAN People
*
@@ -117,6 +117,36 @@ static struct clk pioD_clk = {
.pmc_mask = 1 << AT91RM9200_ID_PIOD,
.type = CLK_TYPE_PERIPHERAL,
};
+static struct clk tc0_clk = {
+ .name = "tc0_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+ .name = "tc1_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+ .name = "tc2_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc3_clk = {
+ .name = "tc3_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC3,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc4_clk = {
+ .name = "tc4_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC4,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc5_clk = {
+ .name = "tc5_clk",
+ .pmc_mask = 1 << AT91RM9200_ID_TC5,
+ .type = CLK_TYPE_PERIPHERAL,
+};
static struct clk *periph_clocks[] __initdata = {
&pioA_clk,
@@ -132,7 +162,12 @@ static struct clk *periph_clocks[] __initdata = {
&twi_clk,
&spi_clk,
// ssc 0 .. ssc2
- // tc0 .. tc5
+ &tc0_clk,
+ &tc1_clk,
+ &tc2_clk,
+ &tc3_clk,
+ &tc4_clk,
+ &tc5_clk,
&ohci_clk,
&ether_clk,
// irq0 .. irq6
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 57fac7203fe..2624a4f22d6 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-at91rm9200/at91rm9200_devices.c
+ * arch/arm/mach-at91/at91rm9200_devices.c
*
* Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
* Copyright (C) 2005 David Brownell
@@ -315,7 +315,7 @@ static struct platform_device at91rm9200_mmc_device = {
.num_resources = ARRAY_SIZE(mmc_resources),
};
-void __init at91_add_device_mmc(struct at91_mmc_data *data)
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
{
if (!data)
return;
@@ -361,7 +361,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
platform_device_register(&at91rm9200_mmc_device);
}
#else
-void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
#endif
@@ -594,6 +594,10 @@ u8 at91_leds_timer;
void __init at91_init_leds(u8 cpu_led, u8 timer_led)
{
+ /* Enable GPIO to access the LEDs */
+ at91_set_gpio_output(cpu_led, 1);
+ at91_set_gpio_output(timer_led, 1);
+
at91_leds_cpu = cpu_led;
at91_leds_timer = timer_led;
}
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index b999e192a7e..949199a244c 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/at91rm9200_time.c
+ * linux/arch/arm/mach-at91/at91rm9200_time.c
*
* Copyright (C) 2003 SAN People
* Copyright (C) 2003 ATMEL
diff --git a/arch/arm/mach-at91rm9200/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index b14871adc30..6ea41d8266c 100644
--- a/arch/arm/mach-at91rm9200/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-at91rm9200/at91sam9260.c
+ * arch/arm/mach-at91/at91sam9260.c
*
* Copyright (C) 2006 SAN People
*
@@ -14,6 +14,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <asm/arch/cpu.h>
#include <asm/arch/at91sam9260.h>
#include <asm/arch/at91_pmc.h>
#include <asm/arch/at91_rstc.h>
@@ -27,7 +28,11 @@ static struct map_desc at91sam9260_io_desc[] __initdata = {
.pfn = __phys_to_pfn(AT91_BASE_SYS),
.length = SZ_16K,
.type = MT_DEVICE,
- }, {
+ }
+};
+
+static struct map_desc at91sam9260_sram_desc[] __initdata = {
+ {
.virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE,
.pfn = __phys_to_pfn(AT91SAM9260_SRAM0_BASE),
.length = AT91SAM9260_SRAM0_SIZE,
@@ -37,7 +42,14 @@ static struct map_desc at91sam9260_io_desc[] __initdata = {
.pfn = __phys_to_pfn(AT91SAM9260_SRAM1_BASE),
.length = AT91SAM9260_SRAM1_SIZE,
.type = MT_DEVICE,
- },
+ }
+};
+
+static struct map_desc at91sam9xe_sram_desc[] __initdata = {
+ {
+ .pfn = __phys_to_pfn(AT91SAM9XE_SRAM_BASE),
+ .type = MT_DEVICE,
+ }
};
/* --------------------------------------------------------------------
@@ -107,13 +119,28 @@ static struct clk spi1_clk = {
.pmc_mask = 1 << AT91SAM9260_ID_SPI1,
.type = CLK_TYPE_PERIPHERAL,
};
+static struct clk tc0_clk = {
+ .name = "tc0_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+ .name = "tc1_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+ .name = "tc2_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
static struct clk ohci_clk = {
.name = "ohci_clk",
.pmc_mask = 1 << AT91SAM9260_ID_UHP,
.type = CLK_TYPE_PERIPHERAL,
};
-static struct clk ether_clk = {
- .name = "ether_clk",
+static struct clk macb_clk = {
+ .name = "macb_clk",
.pmc_mask = 1 << AT91SAM9260_ID_EMAC,
.type = CLK_TYPE_PERIPHERAL,
};
@@ -137,6 +164,21 @@ static struct clk usart5_clk = {
.pmc_mask = 1 << AT91SAM9260_ID_US5,
.type = CLK_TYPE_PERIPHERAL,
};
+static struct clk tc3_clk = {
+ .name = "tc3_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC3,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc4_clk = {
+ .name = "tc4_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC4,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc5_clk = {
+ .name = "tc5_clk",
+ .pmc_mask = 1 << AT91SAM9260_ID_TC5,
+ .type = CLK_TYPE_PERIPHERAL,
+};
static struct clk *periph_clocks[] __initdata = {
&pioA_clk,
@@ -152,14 +194,18 @@ static struct clk *periph_clocks[] __initdata = {
&spi0_clk,
&spi1_clk,
// ssc
- // tc0 .. tc2
+ &tc0_clk,
+ &tc1_clk,
+ &tc2_clk,
&ohci_clk,
- &ether_clk,
+ &macb_clk,
&isi_clk,
&usart3_clk,
&usart4_clk,
&usart5_clk,
- // tc3 .. tc5
+ &tc3_clk,
+ &tc4_clk,
+ &tc5_clk,
// irq0 .. irq2
};
@@ -213,7 +259,7 @@ static struct at91_gpio_bank at91sam9260_gpio[] = {
static void at91sam9260_reset(void)
{
- at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
}
@@ -221,11 +267,37 @@ static void at91sam9260_reset(void)
* AT91SAM9260 processor initialization
* -------------------------------------------------------------------- */
+static void __init at91sam9xe_initialize(void)
+{
+ unsigned long cidr, sram_size;
+
+ cidr = at91_sys_read(AT91_DBGU_CIDR);
+
+ switch (cidr & AT91_CIDR_SRAMSIZ) {
+ case AT91_CIDR_SRAMSIZ_32K:
+ sram_size = 2 * SZ_16K;
+ break;
+ case AT91_CIDR_SRAMSIZ_16K:
+ default:
+ sram_size = SZ_16K;
+ }
+
+ at91sam9xe_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size;
+ at91sam9xe_sram_desc->length = sram_size;
+
+ iotable_init(at91sam9xe_sram_desc, ARRAY_SIZE(at91sam9xe_sram_desc));
+}
+
void __init at91sam9260_initialize(unsigned long main_clock)
{
/* Map peripherals */
iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
+ if (cpu_is_at91sam9xe())
+ at91sam9xe_initialize();
+ else
+ iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
+
at91_arch_reset = at91sam9260_reset;
at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
| (1 << AT91SAM9260_ID_IRQ2);
diff --git a/arch/arm/mach-at91rm9200/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index f42d3a40ec3..f7d342ccbeb 100644
--- a/arch/arm/mach-at91rm9200/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-at91rm9200/at91sam9260_devices.c
+ * arch/arm/mach-at91/at91sam9260_devices.c
*
* Copyright (C) 2006 Atmel
*
@@ -128,7 +128,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
static u64 eth_dmamask = 0xffffffffUL;
-static struct eth_platform_data eth_data;
+static struct at91_eth_data eth_data;
static struct resource eth_resources[] = {
[0] = {
@@ -155,7 +155,7 @@ static struct platform_device at91sam9260_eth_device = {
.num_resources = ARRAY_SIZE(eth_resources),
};
-void __init at91_add_device_eth(struct eth_platform_data *data)
+void __init at91_add_device_eth(struct at91_eth_data *data)
{
if (!data)
return;
@@ -192,7 +192,7 @@ void __init at91_add_device_eth(struct eth_platform_data *data)
platform_device_register(&at91sam9260_eth_device);
}
#else
-void __init at91_add_device_eth(struct eth_platform_data *data) {}
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
#endif
@@ -229,7 +229,7 @@ static struct platform_device at91sam9260_mmc_device = {
.num_resources = ARRAY_SIZE(mmc_resources),
};
-void __init at91_add_device_mmc(struct at91_mmc_data *data)
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
{
if (!data)
return;
@@ -275,7 +275,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
platform_device_register(&at91sam9260_mmc_device);
}
#else
-void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
#endif
@@ -515,6 +515,10 @@ u8 at91_leds_timer;
void __init at91_init_leds(u8 cpu_led, u8 timer_led)
{
+ /* Enable GPIO to access the LEDs */
+ at91_set_gpio_output(cpu_led, 1);
+ at91_set_gpio_output(timer_led, 1);
+
at91_leds_cpu = cpu_led;
at91_leds_timer = timer_led;
}
diff --git a/arch/arm/mach-at91rm9200/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index d242bb885c6..784d1e682d6 100644
--- a/arch/arm/mach-at91rm9200/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-at91rm9200/at91sam9261.c
+ * arch/arm/mach-at91/at91sam9261.c
*
* Copyright (C) 2005 SAN People
*
@@ -97,6 +97,21 @@ static struct clk spi1_clk = {
.pmc_mask = 1 << AT91SAM9261_ID_SPI1,
.type = CLK_TYPE_PERIPHERAL,
};
+static struct clk tc0_clk = {
+ .name = "tc0_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_TC0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc1_clk = {
+ .name = "tc1_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_TC1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tc2_clk = {
+ .name = "tc2_clk",
+ .pmc_mask = 1 << AT91SAM9261_ID_TC2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
static struct clk ohci_clk = {
.name = "ohci_clk",
.pmc_mask = 1 << AT91SAM9261_ID_UHP,
@@ -121,7 +136,9 @@ static struct clk *periph_clocks[] __initdata = {
&spi0_clk,
&spi1_clk,
// ssc 0 .. ssc2
- // tc0 .. tc2
+ &tc0_clk,
+ &tc1_clk,
+ &tc2_clk,
&ohci_clk,
&lcdc_clk,
// irq0 .. irq2
@@ -208,7 +225,7 @@ static struct at91_gpio_bank at91sam9261_gpio[] = {
static void at91sam9261_reset(void)
{
- at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
}
diff --git a/arch/arm/mach-at91rm9200/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index ed1d79081b3..e1504766fd6 100644
--- a/arch/arm/mach-at91rm9200/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-at91rm9200/at91sam9261_devices.c
+ * arch/arm/mach-at91/at91sam9261_devices.c
*
* Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
* Copyright (C) 2005 David Brownell
@@ -159,7 +159,7 @@ static struct platform_device at91sam9261_mmc_device = {
.num_resources = ARRAY_SIZE(mmc_resources),
};
-void __init at91_add_device_mmc(struct at91_mmc_data *data)
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
{
if (!data)
return;
@@ -192,7 +192,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
platform_device_register(&at91sam9261_mmc_device);
}
#else
-void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
#endif
@@ -513,6 +513,10 @@ u8 at91_leds_timer;
void __init at91_init_leds(u8 cpu_led, u8 timer_led)
{
+ /* Enable GPIO to access the LEDs */
+ at91_set_gpio_output(cpu_led, 1);
+ at91_set_gpio_output(timer_led, 1);
+
at91_leds_cpu = cpu_led;
at91_leds_timer = timer_led;
}
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
new file mode 100644
index 00000000000..6aa342e8f1b
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -0,0 +1,313 @@
+/*
+ * arch/arm/mach-at91/at91sam9263.c
+ *
+ * Copyright (C) 2007 Atmel 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.
+ *
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/at91sam9263.h>
+#include <asm/arch/at91_pmc.h>
+#include <asm/arch/at91_rstc.h>
+
+#include "generic.h"
+#include "clock.h"
+
+static struct map_desc at91sam9263_io_desc[] __initdata = {
+ {
+ .virtual = AT91_VA_BASE_SYS,
+ .pfn = __phys_to_pfn(AT91_BASE_SYS),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE,
+ .pfn = __phys_to_pfn(AT91SAM9263_SRAM0_BASE),
+ .length = AT91SAM9263_SRAM0_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE - AT91SAM9263_SRAM1_SIZE,
+ .pfn = __phys_to_pfn(AT91SAM9263_SRAM1_BASE),
+ .length = AT91SAM9263_SRAM1_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+/* --------------------------------------------------------------------
+ * Clocks
+ * -------------------------------------------------------------------- */
+
+/*
+ * The peripheral clocks.
+ */
+static struct clk pioA_clk = {
+ .name = "pioA_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_PIOA,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioB_clk = {
+ .name = "pioB_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_PIOB,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk pioCDE_clk = {
+ .name = "pioCDE_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_PIOCDE,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart0_clk = {
+ .name = "usart0_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_US0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart1_clk = {
+ .name = "usart1_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_US1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk usart2_clk = {
+ .name = "usart2_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_US2,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc0_clk = {
+ .name = "mci0_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_MCI0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk mmc1_clk = {
+ .name = "mci1_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_MCI1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk twi_clk = {
+ .name = "twi_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_TWI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi0_clk = {
+ .name = "spi0_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_SPI0,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk spi1_clk = {
+ .name = "spi1_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_SPI1,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk tcb_clk = {
+ .name = "tcb_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_TCB,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk macb_clk = {
+ .name = "macb_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_EMAC,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk udc_clk = {
+ .name = "udc_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_UDP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk isi_clk = {
+ .name = "isi_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_ISI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk lcdc_clk = {
+ .name = "lcdc_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_ISI,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+static struct clk ohci_clk = {
+ .name = "ohci_clk",
+ .pmc_mask = 1 << AT91SAM9263_ID_UHP,
+ .type = CLK_TYPE_PERIPHERAL,
+};
+
+static struct clk *periph_clocks[] __initdata = {
+ &pioA_clk,
+ &pioB_clk,
+ &pioCDE_clk,
+ &usart0_clk,
+ &usart1_clk,
+ &usart2_clk,
+ &mmc0_clk,
+ &mmc1_clk,
+ // can
+ &twi_clk,
+ &spi0_clk,
+ &spi1_clk,
+ // ssc0 .. ssc1
+ // ac97
+ &tcb_clk,
+ // pwmc
+ &macb_clk,
+ // 2dge
+ &udc_clk,
+ &isi_clk,
+ &lcdc_clk,
+ // dma
+ &ohci_clk,
+ // irq0 .. irq1
+};
+
+/*
+ * The four programmable clocks.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+ .name = "pck0",
+ .pmc_mask = AT91_PMC_PCK0,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 0,
+};
+static struct clk pck1 = {
+ .name = "pck1",
+ .pmc_mask = AT91_PMC_PCK1,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 1,
+};
+static struct clk pck2 = {
+ .name = "pck2",
+ .pmc_mask = AT91_PMC_PCK2,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 2,
+};
+static struct clk pck3 = {
+ .name = "pck3",
+ .pmc_mask = AT91_PMC_PCK3,
+ .type = CLK_TYPE_PROGRAMMABLE,
+ .id = 3,
+};
+
+static void __init at91sam9263_register_clocks(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
+ clk_register(periph_clocks[i]);
+
+ clk_register(&pck0);
+ clk_register(&pck1);
+ clk_register(&pck2);
+ clk_register(&pck3);
+}
+
+/* --------------------------------------------------------------------
+ * GPIO
+ * -------------------------------------------------------------------- */
+
+static struct at91_gpio_bank at91sam9263_gpio[] = {
+ {
+ .id = AT91SAM9263_ID_PIOA,
+ .offset = AT91_PIOA,
+ .clock = &pioA_clk,
+ }, {
+ .id = AT91SAM9263_ID_PIOB,
+ .offset = AT91_PIOB,
+ .clock = &pioB_clk,
+ }, {
+ .id = AT91SAM9263_ID_PIOCDE,
+ .offset = AT91_PIOC,
+ .clock = &pioCDE_clk,
+ }, {
+ .id = AT91SAM9263_ID_PIOCDE,
+ .offset = AT91_PIOD,
+ .clock = &pioCDE_clk,
+ }, {
+ .id = AT91SAM9263_ID_PIOCDE,
+ .offset = AT91_PIOE,
+ .clock = &pioCDE_clk,
+ }
+};
+
+static void at91sam9263_reset(void)
+{
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
+}
+
+
+/* --------------------------------------------------------------------
+ * AT91SAM9263 processor initialization
+ * -------------------------------------------------------------------- */
+
+void __init at91sam9263_initialize(unsigned long main_clock)
+{
+ /* Map peripherals */
+ iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
+
+ at91_arch_reset = at91sam9263_reset;
+ at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
+
+ /* Init clock subsystem */
+ at91_clock_init(main_clock);
+
+ /* Register the processor-specific clocks */
+ at91sam9263_register_clocks();
+
+ /* Register GPIO subsystem */
+ at91_gpio_init(at91sam9263_gpio, 5);
+}
+
+/* --------------------------------------------------------------------
+ * Interrupt initialization
+ * -------------------------------------------------------------------- */
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
+ 7, /* Advanced Interrupt Controller (FIQ) */
+ 7, /* System Peripherals */
+ 0, /* Parallel IO Controller A */
+ 0, /* Parallel IO Controller B */
+ 0, /* Parallel IO Controller C, D and E */
+ 0,
+ 0,
+ 6, /* USART 0 */
+ 6, /* USART 1 */
+ 6, /* USART 2 */
+ 0, /* Multimedia Card Interface 0 */
+ 0, /* Multimedia Card Interface 1 */
+ 4, /* CAN */
+ 0, /* Two-Wire Interface */
+ 6, /* Serial Peripheral Interface 0 */
+ 6, /* Serial Peripheral Interface 1 */
+ 5, /* Serial Synchronous Controller 0 */
+ 5, /* Serial Synchronous Controller 1 */
+ 6, /* AC97 Controller */
+ 0, /* Timer Counter 0, 1 and 2 */
+ 0, /* Pulse Width Modulation Controller */
+ 3, /* Ethernet */
+ 0,
+ 0, /* 2D Graphic Engine */
+ 3, /* USB Device Port */
+ 0, /* Image Sensor Interface */
+ 3, /* LDC Controller */
+ 0, /* DMA Controller */
+ 0,
+ 3, /* USB Host port */
+ 0, /* Advanced Interrupt Controller (IRQ0) */
+ 0, /* Advanced Interrupt Controller (IRQ1) */
+};
+
+void __init at91sam9263_init_interrupts(unsigned int priority[NR_AIC_IRQS])
+{
+ if (!priority)
+ priority = at91sam9263_default_irq_priority;
+
+ /* Initialize the AIC interrupt controller */
+ at91_aic_init(priority);
+
+ /* Enable GPIO interrupts */
+ at91_gpio_irq_setup();
+}
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
new file mode 100644
index 00000000000..d9af7ca58bc
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -0,0 +1,818 @@
+/*
+ * arch/arm/mach-at91/at91sam9263_devices.c
+ *
+ * Copyright (C) 2007 Atmel 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.
+ *
+ */
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam9263.h>
+#include <asm/arch/at91sam926x_mc.h>
+#include <asm/arch/at91sam9263_matrix.h>
+
+#include "generic.h"
+
+#define SZ_512 0x00000200
+#define SZ_256 0x00000100
+#define SZ_16 0x00000010
+
+/* --------------------------------------------------------------------
+ * USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource usbh_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_UHP_BASE,
+ .end = AT91SAM9263_UHP_BASE + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_UHP,
+ .end = AT91SAM9263_ID_UHP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91_usbh_device = {
+ .name = "at91_ohci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &usbh_data,
+ },
+ .resource = usbh_resources,
+ .num_resources = ARRAY_SIZE(usbh_resources),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+ int i;
+
+ if (!data)
+ return;
+
+ /* Enable VBus control for UHP ports */
+ for (i = 0; i < data->ports; i++) {
+ if (data->vbus_pin[i])
+ at91_set_gpio_output(data->vbus_pin[i], 0);
+ }
+
+ usbh_data = *data;
+ platform_device_register(&at91_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource udc_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_UDP,
+ .end = AT91SAM9263_BASE_UDP + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_UDP,
+ .end = AT91SAM9263_ID_UDP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91_udc_device = {
+ .name = "at91_udc",
+ .id = -1,
+ .dev = {
+ .platform_data = &udc_data,
+ },
+ .resource = udc_resources,
+ .num_resources = ARRAY_SIZE(udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+ if (!data)
+ return;
+
+ if (data->vbus_pin) {
+ at91_set_gpio_input(data->vbus_pin, 0);
+ at91_set_deglitch(data->vbus_pin, 1);
+ }
+
+ /* Pullup pin is handled internally by USB device peripheral */
+
+ udc_data = *data;
+ platform_device_register(&at91_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
+static u64 eth_dmamask = 0xffffffffUL;
+static struct at91_eth_data eth_data;
+
+static struct resource eth_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_EMAC,
+ .end = AT91SAM9263_BASE_EMAC + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_EMAC,
+ .end = AT91SAM9263_ID_EMAC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_eth_device = {
+ .name = "macb",
+ .id = -1,
+ .dev = {
+ .dma_mask = &eth_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &eth_data,
+ },
+ .resource = eth_resources,
+ .num_resources = ARRAY_SIZE(eth_resources),
+};
+
+void __init at91_add_device_eth(struct at91_eth_data *data)
+{
+ if (!data)
+ return;
+
+ if (data->phy_irq_pin) {
+ at91_set_gpio_input(data->phy_irq_pin, 0);
+ at91_set_deglitch(data->phy_irq_pin, 1);
+ }
+
+ /* Pins used for MII and RMII */
+ at91_set_A_periph(AT91_PIN_PE21, 0); /* ETXCK_EREFCK */
+ at91_set_B_periph(AT91_PIN_PC25, 0); /* ERXDV */
+ at91_set_A_periph(AT91_PIN_PE25, 0); /* ERX0 */
+ at91_set_A_periph(AT91_PIN_PE26, 0); /* ERX1 */
+ at91_set_A_periph(AT91_PIN_PE27, 0); /* ERXER */
+ at91_set_A_periph(AT91_PIN_PE28, 0); /* ETXEN */
+ at91_set_A_periph(AT91_PIN_PE23, 0); /* ETX0 */
+ at91_set_A_periph(AT91_PIN_PE24, 0); /* ETX1 */
+ at91_set_A_periph(AT91_PIN_PE30, 0); /* EMDIO */
+ at91_set_A_periph(AT91_PIN_PE29, 0); /* EMDC */
+
+ if (!data->is_rmii) {
+ at91_set_A_periph(AT91_PIN_PE22, 0); /* ECRS */
+ at91_set_B_periph(AT91_PIN_PC26, 0); /* ECOL */
+ at91_set_B_periph(AT91_PIN_PC22, 0); /* ERX2 */
+ at91_set_B_periph(AT91_PIN_PC23, 0); /* ERX3 */
+ at91_set_B_periph(AT91_PIN_PC27, 0); /* ERXCK */
+ at91_set_B_periph(AT91_PIN_PC20, 0); /* ETX2 */
+ at91_set_B_periph(AT91_PIN_PC21, 0); /* ETX3 */
+ at91_set_B_periph(AT91_PIN_PC24, 0); /* ETXER */
+ }
+
+ eth_data = *data;
+ platform_device_register(&at91sam9263_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc0_data, mmc1_data;
+
+static struct resource mmc0_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_MCI0,
+ .end = AT91SAM9263_BASE_MCI0 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_MCI0,
+ .end = AT91SAM9263_ID_MCI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_mmc0_device = {
+ .name = "at91_mci",
+ .id = 0,
+ .dev = {
+ .dma_mask = &mmc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &mmc0_data,
+ },
+ .resource = mmc0_resources,
+ .num_resources = ARRAY_SIZE(mmc0_resources),
+};
+
+static struct resource mmc1_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_MCI1,
+ .end = AT91SAM9263_BASE_MCI1 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_MCI1,
+ .end = AT91SAM9263_ID_MCI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_mmc1_device = {
+ .name = "at91_mci",
+ .id = 1,
+ .dev = {
+ .dma_mask = &mmc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &mmc1_data,
+ },
+ .resource = mmc1_resources,
+ .num_resources = ARRAY_SIZE(mmc1_resources),
+};
+
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+{
+ if (!data)
+ return;
+
+ /* input/irq */
+ if (data->det_pin) {
+ at91_set_gpio_input(data->det_pin, 1);
+ at91_set_deglitch(data->det_pin, 1);
+ }
+ if (data->wp_pin)
+ at91_set_gpio_input(data->wp_pin, 1);
+ if (data->vcc_pin)
+ at91_set_gpio_output(data->vcc_pin, 0);
+
+ if (mmc_id == 0) { /* MCI0 */
+ /* CLK */
+ at91_set_A_periph(AT91_PIN_PA12, 0);
+
+ if (data->slot_b) {
+ /* CMD */
+ at91_set_A_periph(AT91_PIN_PA16, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_A_periph(AT91_PIN_PA17, 1);
+ if (data->wire4) {
+ at91_set_A_periph(AT91_PIN_PA18, 1);
+ at91_set_A_periph(AT91_PIN_PA19, 1);
+ at91_set_A_periph(AT91_PIN_PA20, 1);
+ }
+ } else {
+ /* CMD */
+ at91_set_A_periph(AT91_PIN_PA1, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_A_periph(AT91_PIN_PA0, 1);
+ if (data->wire4) {
+ at91_set_A_periph(AT91_PIN_PA3, 1);
+ at91_set_A_periph(AT91_PIN_PA4, 1);
+ at91_set_A_periph(AT91_PIN_PA5, 1);
+ }
+ }
+
+ mmc0_data = *data;
+ at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
+ platform_device_register(&at91sam9263_mmc0_device);
+ } else { /* MCI1 */
+ /* CLK */
+ at91_set_A_periph(AT91_PIN_PA6, 0);
+
+ if (data->slot_b) {
+ /* CMD */
+ at91_set_A_periph(AT91_PIN_PA21, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_A_periph(AT91_PIN_PA22, 1);
+ if (data->wire4) {
+ at91_set_A_periph(AT91_PIN_PA23, 1);
+ at91_set_A_periph(AT91_PIN_PA24, 1);
+ at91_set_A_periph(AT91_PIN_PA25, 1);
+ }
+ } else {
+ /* CMD */
+ at91_set_A_periph(AT91_PIN_PA7, 1);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_A_periph(AT91_PIN_PA8, 1);
+ if (data->wire4) {
+ at91_set_A_periph(AT91_PIN_PA9, 1);
+ at91_set_A_periph(AT91_PIN_PA10, 1);
+ at91_set_A_periph(AT91_PIN_PA11, 1);
+ }
+ }
+
+ mmc1_data = *data;
+ at91_clock_associate("mci1_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
+ platform_device_register(&at91sam9263_mmc1_device);
+ }
+}
+#else
+void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+#define NAND_BASE AT91_CHIPSELECT_3
+
+static struct resource nand_resources[] = {
+ {
+ .start = NAND_BASE,
+ .end = NAND_BASE + SZ_256M - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device at91sam9263_nand_device = {
+ .name = "at91_nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &nand_data,
+ },
+ .resource = nand_resources,
+ .num_resources = ARRAY_SIZE(nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+ unsigned long csa, mode;
+
+ if (!data)
+ return;
+
+ csa = at91_sys_read(AT91_MATRIX_EBI0CSA);
+ at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC);
+
+ /* set the bus interface characteristics */
+ at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
+ | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
+
+ at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3)
+ | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3));
+
+ at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5));
+
+ if (data->bus_width_16)
+ mode = AT91_SMC_DBW_16;
+ else
+ mode = AT91_SMC_DBW_8;
+ at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2));
+
+ /* enable pin */
+ if (data->enable_pin)
+ at91_set_gpio_output(data->enable_pin, 1);
+
+ /* ready/busy pin */
+ if (data->rdy_pin)
+ at91_set_gpio_input(data->rdy_pin, 1);
+
+ /* card detect pin */
+ if (data->det_pin)
+ at91_set_gpio_input(data->det_pin, 1);
+
+ nand_data = *data;
+ platform_device_register(&at91sam9263_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+
+static struct resource twi_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_TWI,
+ .end = AT91SAM9263_BASE_TWI + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_TWI,
+ .end = AT91SAM9263_ID_TWI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_twi_device = {
+ .name = "at91_i2c",
+ .id = -1,
+ .resource = twi_resources,
+ .num_resources = ARRAY_SIZE(twi_resources),
+};
+
+void __init at91_add_device_i2c(void)
+{
+ /* pins used for TWI interface */
+ at91_set_A_periph(AT91_PIN_PB4, 0); /* TWD */
+ at91_set_multi_drive(AT91_PIN_PB4, 1);
+
+ at91_set_A_periph(AT91_PIN_PB5, 0); /* TWCK */
+ at91_set_multi_drive(AT91_PIN_PB5, 1);
+
+ platform_device_register(&at91sam9263_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource spi0_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_SPI0,
+ .end = AT91SAM9263_BASE_SPI0 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_SPI0,
+ .end = AT91SAM9263_ID_SPI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_spi0_device = {
+ .name = "atmel_spi",
+ .id = 0,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = spi0_resources,
+ .num_resources = ARRAY_SIZE(spi0_resources),
+};
+
+static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11 };
+
+static struct resource spi1_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_SPI1,
+ .end = AT91SAM9263_BASE_SPI1 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_SPI1,
+ .end = AT91SAM9263_ID_SPI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91sam9263_spi1_device = {
+ .name = "atmel_spi",
+ .id = 1,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = spi1_resources,
+ .num_resources = ARRAY_SIZE(spi1_resources),
+};
+
+static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+ int i;
+ unsigned long cs_pin;
+ short enable_spi0 = 0;
+ short enable_spi1 = 0;
+
+ /* Choose SPI chip-selects */
+ for (i = 0; i < nr_devices; i++) {
+ if (devices[i].controller_data)
+ cs_pin = (unsigned long) devices[i].controller_data;
+ else if (devices[i].bus_num == 0)
+ cs_pin = spi0_standard_cs[devices[i].chip_select];
+ else
+ cs_pin = spi1_standard_cs[devices[i].chip_select];
+
+ if (devices[i].bus_num == 0)
+ enable_spi0 = 1;
+ else
+ enable_spi1 = 1;
+
+ /* enable chip-select pin */
+ at91_set_gpio_output(cs_pin, 1);
+
+ /* pass chip-select pin to driver */
+ devices[i].controller_data = (void *) cs_pin;
+ }
+
+ spi_register_board_info(devices, nr_devices);
+
+ /* Configure SPI bus(es) */
+ if (enable_spi0) {
+ at91_set_B_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */
+ at91_set_B_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */
+ at91_set_B_periph(AT91_PIN_PA2, 0); /* SPI1_SPCK */
+
+ at91_clock_associate("spi0_clk", &at91sam9263_spi0_device.dev, "spi_clk");
+ platform_device_register(&at91sam9263_spi0_device);
+ }
+ if (enable_spi1) {
+ at91_set_A_periph(AT91_PIN_PB12, 0); /* SPI1_MISO */
+ at91_set_A_periph(AT91_PIN_PB13, 0); /* SPI1_MOSI */
+ at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_SPCK */
+
+ at91_clock_associate("spi1_clk", &at91sam9263_spi1_device.dev, "spi_clk");
+ platform_device_register(&at91sam9263_spi1_device);
+ }
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+ /* Enable GPIO to access the LEDs */
+ at91_set_gpio_output(cpu_led, 1);
+ at91_set_gpio_output(timer_led, 1);
+
+ at91_leds_cpu = cpu_led;
+ at91_leds_timer = timer_led;
+}
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_ATMEL)
+
+static struct resource dbgu_resources[] = {
+ [0] = {
+ .start = AT91_VA_BASE_SYS + AT91_DBGU,
+ .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91_ID_SYS,
+ .end = AT91_ID_SYS,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data dbgu_data = {
+ .use_dma_tx = 0,
+ .use_dma_rx = 0, /* DBGU not capable of receive DMA */
+ .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
+};
+
+static struct platform_device at91sam9263_dbgu_device = {
+ .name = "atmel_usart",
+ .id = 0,
+ .dev = {
+ .platform_data = &dbgu_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = dbgu_resources,
+ .num_resources = ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PC30, 0); /* DRXD */
+ at91_set_A_periph(AT91_PIN_PC31, 1); /* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_US0,
+ .end = AT91SAM9263_BASE_US0 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_US0,
+ .end = AT91SAM9263_ID_US0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart0_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9263_uart0_device = {
+ .name = "atmel_usart",
+ .id = 1,
+ .dev = {
+ .platform_data = &uart0_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart0_resources,
+ .num_resources = ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PA26, 1); /* TXD0 */
+ at91_set_A_periph(AT91_PIN_PA27, 0); /* RXD0 */
+ at91_set_A_periph(AT91_PIN_PA28, 0); /* RTS0 */
+ at91_set_A_periph(AT91_PIN_PA29, 0); /* CTS0 */
+}
+
+static struct resource uart1_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_US1,
+ .end = AT91SAM9263_BASE_US1 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_US1,
+ .end = AT91SAM9263_ID_US1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart1_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9263_uart1_device = {
+ .name = "atmel_usart",
+ .id = 2,
+ .dev = {
+ .platform_data = &uart1_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart1_resources,
+ .num_resources = ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PD0, 1); /* TXD1 */
+ at91_set_A_periph(AT91_PIN_PD1, 0); /* RXD1 */
+ at91_set_B_periph(AT91_PIN_PD7, 0); /* RTS1 */
+ at91_set_B_periph(AT91_PIN_PD8, 0); /* CTS1 */
+}
+
+static struct resource uart2_resources[] = {
+ [0] = {
+ .start = AT91SAM9263_BASE_US2,
+ .end = AT91SAM9263_BASE_US2 + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91SAM9263_ID_US2,
+ .end = AT91SAM9263_ID_US2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct atmel_uart_data uart2_data = {
+ .use_dma_tx = 1,
+ .use_dma_rx = 1,
+};
+
+static struct platform_device at91sam9263_uart2_device = {
+ .name = "atmel_usart",
+ .id = 3,
+ .dev = {
+ .platform_data = &uart2_data,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .resource = uart2_resources,
+ .num_resources = ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+ at91_set_A_periph(AT91_PIN_PD2, 1); /* TXD2 */
+ at91_set_A_periph(AT91_PIN_PD3, 0); /* RXD2 */
+ at91_set_B_periph(AT91_PIN_PD5, 0); /* RTS2 */
+ at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */
+}
+
+struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
+struct platform_device *atmel_default_console_device; /* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+ int i;
+
+ /* Fill in list of supported UARTs */
+ for (i = 0; i < config->nr_tty; i++) {
+ switch (config->tty_map[i]) {
+ case 0:
+ configure_usart0_pins();
+ at91_uarts[i] = &at91sam9263_uart0_device;
+ at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart");
+ break;
+ case 1:
+ configure_usart1_pins();
+ at91_uarts[i] = &at91sam9263_uart1_device;
+ at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart");
+ break;
+ case 2:
+ configure_usart2_pins();
+ at91_uarts[i] = &at91sam9263_uart2_device;
+ at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart");
+ break;
+ case 3:
+ configure_dbgu_pins();
+ at91_uarts[i] = &at91sam9263_dbgu_device;
+ at91_clock_associate("mck", &at91sam9263_dbgu_device.dev, "usart");
+ break;
+ default:
+ continue;
+ }
+ at91_uarts[i]->id = i; /* update ID number to mapped ID */
+ }
+
+ /* Set serial console device */
+ if (config->console_tty < ATMEL_MAX_UART)
+ atmel_default_console_device = at91_uarts[config->console_tty];
+ if (!atmel_default_console_device)
+ printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+ int i;
+
+ for (i = 0; i < ATMEL_MAX_UART; i++) {
+ if (at91_uarts[i])
+ platform_device_register(at91_uarts[i]);
+ }
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+ return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91rm9200/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index 99df5f6ee42..a4dded27fa1 100644
--- a/arch/arm/mach-at91rm9200/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/at91sam926x_time.c
+ * linux/arch/arm/mach-at91/at91sam926x_time.c
*
* Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
* Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France
@@ -30,7 +30,6 @@
* Returns number of microseconds since last timer interrupt. Note that interrupts
* will have been disabled by do_gettimeofday()
* 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
- * 'tick' is usecs per jiffy (linux/timex.h).
*/
static unsigned long at91sam926x_gettimeoffset(void)
{
@@ -39,7 +38,7 @@ static unsigned long at91sam926x_gettimeoffset(void)
elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t); /* hardware clock cycles */
- return (unsigned long)(elapsed * 1000000) / LATCH;
+ return (unsigned long)(elapsed * jiffies_to_usecs(1)) / LATCH;
}
/*
diff --git a/arch/arm/mach-at91rm9200/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
index 971c3e2d8e3..2d3d4b6f7b0 100644
--- a/arch/arm/mach-at91rm9200/board-1arm.c
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/board-1arm.c
+ * linux/arch/arm/mach-at91/board-1arm.c
*
* Copyright (C) 2005 SAN People
*
diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index 654f0379550..b4518619063 100644
--- a/arch/arm/mach-at91rm9200/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/board-carmeva.c
+ * linux/arch/arm/mach-at91/board-carmeva.c
*
* Copyright (c) 2005 Peer Georgi
* Conitec Datasystems
@@ -134,7 +134,7 @@ static void __init carmeva_board_init(void)
/* Compact Flash */
// at91_add_device_cf(&carmeva_cf_data);
/* MMC */
- at91_add_device_mmc(&carmeva_mmc_data);
+ at91_add_device_mmc(0, &carmeva_mmc_data);
}
MACHINE_START(CARMEVA, "Carmeva")
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index b8bb8052607..e18a41e61f0 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/board-csb337.c
+ * linux/arch/arm/mach-at91/board-csb337.c
*
* Copyright (C) 2005 SAN People
*
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
+#include <linux/mtd/physmap.h>
#include <asm/hardware.h>
#include <asm/setup.h>
@@ -112,6 +113,42 @@ static struct spi_board_info csb337_spi_devices[] = {
},
};
+#define CSB_FLASH_BASE AT91_CHIPSELECT_0
+#define CSB_FLASH_SIZE 0x800000
+
+static struct mtd_partition csb_flash_partitions[] = {
+ {
+ .name = "uMON flash",
+ .offset = 0,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = MTD_WRITEABLE, /* read only */
+ }
+};
+
+static struct physmap_flash_data csb_flash_data = {
+ .width = 2,
+ .parts = csb_flash_partitions,
+ .nr_parts = ARRAY_SIZE(csb_flash_partitions),
+};
+
+static struct resource csb_flash_resources[] = {
+ {
+ .start = CSB_FLASH_BASE,
+ .end = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device csb_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &csb_flash_data,
+ },
+ .resource = csb_flash_resources,
+ .num_resources = ARRAY_SIZE(csb_flash_resources),
+};
+
static void __init csb337_board_init(void)
{
/* Serial */
@@ -130,7 +167,9 @@ static void __init csb337_board_init(void)
/* SPI */
at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices));
/* MMC */
- at91_add_device_mmc(&csb337_mmc_data);
+ at91_add_device_mmc(0, &csb337_mmc_data);
+ /* NOR flash */
+ platform_device_register(&csb_flash);
}
MACHINE_START(CSB337, "Cogent CSB337")
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index a29fa0e822c..77f04b935b3 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/board-csb637.c
+ * linux/arch/arm/mach-at91/board-csb637.c
*
* Copyright (C) 2005 SAN People
*
@@ -23,6 +23,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
#include <asm/hardware.h>
#include <asm/setup.h>
@@ -81,6 +82,42 @@ static struct at91_udc_data __initdata csb637_udc_data = {
.pullup_pin = AT91_PIN_PB1,
};
+#define CSB_FLASH_BASE AT91_CHIPSELECT_0
+#define CSB_FLASH_SIZE 0x1000000
+
+static struct mtd_partition csb_flash_partitions[] = {
+ {
+ .name = "uMON flash",
+ .offset = 0,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = MTD_WRITEABLE, /* read only */
+ }
+};
+
+static struct physmap_flash_data csb_flash_data = {
+ .width = 2,
+ .parts = csb_flash_partitions,
+ .nr_parts = ARRAY_SIZE(csb_flash_partitions),
+};
+
+static struct resource csb_flash_resources[] = {
+ {
+ .start = CSB_FLASH_BASE,
+ .end = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device csb_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &csb_flash_data,
+ },
+ .resource = csb_flash_resources,
+ .num_resources = ARRAY_SIZE(csb_flash_resources),
+};
+
static void __init csb637_board_init(void)
{
/* Serial */
@@ -95,6 +132,8 @@ static void __init csb637_board_init(void)
at91_add_device_i2c();
/* SPI */
at91_add_device_spi(NULL, 0);
+ /* NOR flash */
+ platform_device_register(&csb_flash);
}
MACHINE_START(CSB637, "Cogent CSB637")
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91/board-dk.c
index 7522bf91bce..6043c38c0a9 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91/board-dk.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/board-dk.c
+ * linux/arch/arm/mach-at91/board-dk.c
*
* Copyright (C) 2005 SAN People
*
@@ -194,7 +194,7 @@ static void __init dk_board_init(void)
#else
/* MMC */
at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
- at91_add_device_mmc(&dk_mmc_data);
+ at91_add_device_mmc(0, &dk_mmc_data);
#endif
/* NAND */
at91_add_device_nand(&dk_nand_data);
diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index 80b72cf7264..20458b5548f 100644
--- a/arch/arm/mach-at91rm9200/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/board-eb9200.c
+ * linux/arch/arm/mach-at91/board-eb9200.c
*
* Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest
* by Andrew Patrikalakis
@@ -109,7 +109,7 @@ static void __init eb9200_board_init(void)
at91_add_device_spi(NULL, 0);
/* MMC */
/* only supports 1 or 4 bit interface, not wired through to SPI */
- at91_add_device_mmc(&eb9200_mmc_data);
+ at91_add_device_mmc(0, &eb9200_mmc_data);
}
MACHINE_START(ATEB9200, "Embest ATEB9200")
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91/board-ek.c
index c4fdb415f20..322fdd75a1e 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91/board-ek.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/board-ek.c
+ * linux/arch/arm/mach-at91/board-ek.c
*
* Copyright (C) 2005 SAN People
*
@@ -154,7 +154,7 @@ static void __init ek_board_init(void)
#else
/* MMC */
at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
- at91_add_device_mmc(&ek_mmc_data);
+ at91_add_device_mmc(0, &ek_mmc_data);
#endif
/* NOR Flash */
platform_device_register(&ek_flash);
diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index 6ef3c487982..c77d84ce9ca 100644
--- a/arch/arm/mach-at91rm9200/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/board-kafa.c
+ * linux/arch/arm/mach-at91/board-kafa.c
*
* Copyright (C) 2006 Sperry-Sun
*
diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index 759d8191854..76f6e1e553e 100644
--- a/arch/arm/mach-at91rm9200/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/board-kb9202.c
+ * linux/arch/arm/mach-at91/board-kb9202.c
*
* Copyright (c) 2005 kb_admin
* KwikByte, Inc.
@@ -122,7 +122,7 @@ static void __init kb9202_board_init(void)
/* USB Device */
at91_add_device_udc(&kb9202_udc_data);
/* MMC */
- at91_add_device_mmc(&kb9202_mmc_data);
+ at91_add_device_mmc(0, &kb9202_mmc_data);
/* I2C */
at91_add_device_i2c();
/* SPI */
diff --git a/arch/arm/mach-at91rm9200/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index da5d58ac870..57fb4499d96 100644
--- a/arch/arm/mach-at91rm9200/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/board-ek.c
+ * linux/arch/arm/mach-at91/board-sam9260ek.c
*
* Copyright (C) 2005 SAN People
* Copyright (C) 2006 Atmel
@@ -118,7 +118,7 @@ static struct spi_board_info ek_spi_devices[] = {
/*
* MACB Ethernet device
*/
-static struct __initdata eth_platform_data ek_macb_data = {
+static struct __initdata at91_eth_data ek_macb_data = {
.phy_irq_pin = AT91_PIN_PA7,
.is_rmii = 1,
};
@@ -187,7 +187,7 @@ static void __init ek_board_init(void)
/* Ethernet */
at91_add_device_eth(&ek_macb_data);
/* MMC */
- at91_add_device_mmc(&ek_mmc_data);
+ at91_add_device_mmc(0, &ek_mmc_data);
}
MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
diff --git a/arch/arm/mach-at91rm9200/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 30b490d8886..b7e772467cf 100644
--- a/arch/arm/mach-at91rm9200/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/board-ek.c
+ * linux/arch/arm/mach-at91/board-sam9261ek.c
*
* Copyright (C) 2005 SAN People
* Copyright (C) 2006 Atmel
@@ -243,7 +243,7 @@ static void __init ek_board_init(void)
at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
#else
/* MMC */
- at91_add_device_mmc(&ek_mmc_data);
+ at91_add_device_mmc(0, &ek_mmc_data);
#endif
}
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
new file mode 100644
index 00000000000..8fdce11a880
--- /dev/null
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -0,0 +1,176 @@
+/*
+ * linux/arch/arm/mach-at91/board-sam9263ek.c
+ *
+ * Copyright (C) 2005 SAN People
+ * Copyright (C) 2007 Atmel 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91sam926x_mc.h>
+
+#include "generic.h"
+
+
+/*
+ * Serial port configuration.
+ * 0 .. 2 = USART0 .. USART2
+ * 3 = DBGU
+ */
+static struct at91_uart_config __initdata ek_uart_config = {
+ .console_tty = 0, /* ttyS0 */
+ .nr_tty = 2,
+ .tty_map = { 3, 0, -1, -1, } /* ttyS0, ..., ttyS3 */
+};
+
+static void __init ek_map_io(void)
+{
+ /* Initialize processor: 16.367 MHz crystal */
+ at91sam9263_initialize(16367660);
+
+ /* Setup the serial ports and console */
+ at91_init_serial(&ek_uart_config);
+}
+
+static void __init ek_init_irq(void)
+{
+ at91sam9263_init_interrupts(NULL);
+}
+
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+ .ports = 2,
+ .vbus_pin = { AT91_PIN_PA24, AT91_PIN_PA21 },
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+ .vbus_pin = AT91_PIN_PA25,
+ .pullup_pin = 0, /* pull-up driven by UDC */
+};
+
+
+/*
+ * SPI devices.
+ */
+static struct spi_board_info ek_spi_devices[] = {
+#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
+ { /* DataFlash card */
+ .modalias = "mtd_dataflash",
+ .chip_select = 0,
+ .max_speed_hz = 15 * 1000 * 1000,
+ .bus_num = 0,
+ },
+#endif
+};
+
+
+/*
+ * MCI (SD/MMC)
+ */
+static struct at91_mmc_data __initdata ek_mmc_data = {
+ .wire4 = 1,
+ .det_pin = AT91_PIN_PE18,
+ .wp_pin = AT91_PIN_PE19,
+// .vcc_pin = ... not connected
+};
+
+
+/*
+ * NAND flash
+ */
+static struct mtd_partition __initdata ek_nand_partition[] = {
+ {
+ .name = "Partition 1",
+ .offset = 0,
+ .size = 64 * 1024 * 1024,
+ },
+ {
+ .name = "Partition 2",
+ .offset = 64 * 1024 * 1024,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct mtd_partition *nand_partitions(int size, int *num_partitions)
+{
+ *num_partitions = ARRAY_SIZE(ek_nand_partition);
+ return ek_nand_partition;
+}
+
+static struct at91_nand_data __initdata ek_nand_data = {
+ .ale = 21,
+ .cle = 22,
+// .det_pin = ... not connected
+ .rdy_pin = AT91_PIN_PA22,
+ .enable_pin = AT91_PIN_PD15,
+ .partition_info = nand_partitions,
+#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
+ .bus_width_16 = 1,
+#else
+ .bus_width_16 = 0,
+#endif
+};
+
+
+static void __init ek_board_init(void)
+{
+ /* Serial */
+ at91_add_device_serial();
+ /* USB Host */
+ at91_add_device_usbh(&ek_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&ek_udc_data);
+ /* SPI */
+ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+ /* MMC */
+ at91_add_device_mmc(1, &ek_mmc_data);
+ /* NAND */
+ at91_add_device_nand(&ek_nand_data);
+}
+
+MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
+ /* Maintainer: Atmel */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91sam926x_timer,
+ .map_io = ek_map_io,
+ .init_irq = ek_init_irq,
+ .init_machine = ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91/clock.c
index 36a8e4d1cc6..06c9a0507d0 100644
--- a/arch/arm/mach-at91rm9200/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/clock.c
+ * linux/arch/arm/mach-at91/clock.c
*
* Copyright (C) 2005 David Brownell
* Copyright (C) 2005 Ivan Kokshaysky
@@ -525,27 +525,6 @@ fail:
return 0;
}
-/*
- * Several unused clocks may be active. Turn them off.
- */
-static void __init at91_periphclk_reset(void)
-{
- unsigned long reg;
- struct clk *clk;
-
- reg = at91_sys_read(AT91_PMC_PCSR);
-
- list_for_each_entry(clk, &clocks, node) {
- if (clk->mode != pmc_periph_mode)
- continue;
-
- if (clk->users > 0)
- reg &= ~clk->pmc_mask;
- }
-
- at91_sys_write(AT91_PMC_PCDR, reg);
-}
-
static struct clk *const standard_pmc_clocks[] __initdata = {
/* four primary clocks */
&clk32k,
@@ -586,7 +565,7 @@ int __init at91_clock_init(unsigned long main_clock)
pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
/*
- * USB clock init: choose 48 MHz PLLB value, turn all clocks off,
+ * USB clock init: choose 48 MHz PLLB value,
* disable 48MHz clock during usb peripheral suspend.
*
* REVISIT: assumes MCK doesn't derive from PLLB!
@@ -596,16 +575,10 @@ int __init at91_clock_init(unsigned long main_clock)
if (cpu_is_at91rm9200()) {
uhpck.pmc_mask = AT91RM9200_PMC_UHP;
udpck.pmc_mask = AT91RM9200_PMC_UDP;
- at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP);
at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
- } else if (cpu_is_at91sam9260()) {
+ } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) {
uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
udpck.pmc_mask = AT91SAM926x_PMC_UDP;
- at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP);
- } else if (cpu_is_at91sam9261()) {
- uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0);
- udpck.pmc_mask = AT91SAM926x_PMC_UDP;
- at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP);
}
at91_sys_write(AT91_CKGR_PLLBR, 0);
@@ -634,11 +607,34 @@ int __init at91_clock_init(unsigned long main_clock)
(unsigned) main_clock / 1000000,
((unsigned) main_clock % 1000000) / 1000);
- /* disable all programmable clocks */
- at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3);
+ return 0;
+}
+
+/*
+ * Several unused clocks may be active. Turn them off.
+ */
+static int __init at91_clock_reset(void)
+{
+ unsigned long pcdr = 0;
+ unsigned long scdr = 0;
+ struct clk *clk;
+
+ list_for_each_entry(clk, &clocks, node) {
+ if (clk->users > 0)
+ continue;
+
+ if (clk->mode == pmc_periph_mode)
+ pcdr |= clk->pmc_mask;
+
+ if (clk->mode == pmc_sys_mode)
+ scdr |= clk->pmc_mask;
+
+ pr_debug("Clocks: disable unused %s\n", clk->name);
+ }
- /* disable all other unused peripheral clocks */
- at91_periphclk_reset();
+ at91_sys_write(AT91_PMC_PCDR, pcdr);
+ at91_sys_write(AT91_PMC_SCDR, scdr);
return 0;
}
+late_initcall(at91_clock_reset);
diff --git a/arch/arm/mach-at91rm9200/clock.h b/arch/arm/mach-at91/clock.h
index b5c7a2eb2d1..1ba3b95ff35 100644
--- a/arch/arm/mach-at91rm9200/clock.h
+++ b/arch/arm/mach-at91/clock.h
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/clock.h
+ * linux/arch/arm/mach-at91/clock.h
*
* 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
diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91/generic.h
index 8c4d5a77d48..bda26221c52 100644
--- a/arch/arm/mach-at91rm9200/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/generic.h
+ * linux/arch/arm/mach-at91/generic.h
*
* Copyright (C) 2005 David Brownell
*
@@ -12,11 +12,13 @@
extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks);
extern void __init at91sam9260_initialize(unsigned long main_clock);
extern void __init at91sam9261_initialize(unsigned long main_clock);
+extern void __init at91sam9263_initialize(unsigned long main_clock);
/* Interrupts */
extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
extern void __init at91sam9260_init_interrupts(unsigned int priority[]);
extern void __init at91sam9261_init_interrupts(unsigned int priority[]);
+extern void __init at91sam9263_init_interrupts(unsigned int priority[]);
extern void __init at91_aic_init(unsigned int priority[]);
/* Timer */
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91/gpio.c
index 15eb5b6b29f..7b87f3f101b 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/gpio.c
+ * linux/arch/arm/mach-at91/gpio.c
*
* Copyright (C) 2005 HP Labs
*
diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91/irq.c
index 2148daafd29..78a5cdb746d 100644
--- a/arch/arm/mach-at91rm9200/irq.c
+++ b/arch/arm/mach-at91/irq.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-at91rm9200/irq.c
+ * linux/arch/arm/mach-at91/irq.c
*
* Copyright (C) 2004 SAN People
* Copyright (C) 2004 ATMEL
diff --git a/arch/arm/mach-at91rm9200/leds.c b/arch/arm/mach-at91/leds.c
index 1a333730466..0d514497398 100644
--- a/arch/arm/mach-at91rm9200/leds.c
+++ b/arch/arm/mach-at91/leds.c
@@ -86,10 +86,6 @@ static int __init leds_init(void)
if (!at91_leds_timer || !at91_leds_cpu)
return -ENODEV;
- /* Enable PIO to access the LEDs */
- at91_set_gpio_output(at91_leds_timer, 1);
- at91_set_gpio_output(at91_leds_cpu, 1);
-
leds_event = at91_leds_event;
leds_event(led_start);
diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91/pm.c
index 67aa5572a3e..b49bfda53d7 100644
--- a/arch/arm/mach-at91rm9200/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-at91rm9200/pm.c
+ * arch/arm/mach-at91/pm.c
* AT91 Power Management
*
* Copyright (C) 2005 David Brownell
@@ -80,6 +80,8 @@ static int at91_pm_verify_clocks(void)
#warning "Check SAM9260 USB clocks"
} else if (cpu_is_at91sam9261()) {
#warning "Check SAM9261 USB clocks"
+ } else if (cpu_is_at91sam9263()) {
+#warning "Check SAM9263 USB clocks"
}
#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index af7904b3d0a..575a21dabd2 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -51,6 +51,31 @@ config MACH_GESBC9312
Say 'Y' here if you want your kernel to support the Glomation
GESBC-9312-sx board.
+config MACH_MICRO9
+ bool
+ default n
+
+config MACH_MICRO9H
+ bool "Support Contec Hypercontrol Micro9-H"
+ select MACH_MICRO9
+ help
+ Say 'Y' here if you want your kernel to support the
+ Contec Hypercontrol Micro9-H board.
+
+config MACH_MICRO9M
+ bool "Support Contec Hypercontrol Micro9-M"
+ select MACH_MICRO9
+ help
+ Say 'Y' here if you want your kernel to support the
+ Contec Hypercontrol Micro9-M board.
+
+config MACH_MICRO9L
+ bool "Support Contec Hypercontrol Micro9-L"
+ select MACH_MICRO9
+ help
+ Say 'Y' here if you want your kernel to support the
+ Contec Hypercontrol Micro9-L board.
+
config MACH_TS72XX
bool "Support Technologic Systems TS-72xx SBC"
help
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index b06641dd450..0d3bf932654 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -13,4 +13,5 @@ obj-$(CONFIG_MACH_EDB9312) += edb9312.o
obj-$(CONFIG_MACH_EDB9315) += edb9315.o
obj-$(CONFIG_MACH_EDB9315A) += edb9315a.o
obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o
+obj-$(CONFIG_MACH_MICRO9) += micro9.o
obj-$(CONFIG_MACH_TS72XX) += ts72xx.o
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index 08ad782c164..f174d1a3b11 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/module.h>
#include <linux/string.h>
#include <asm/div64.h>
#include <asm/hardware.h>
@@ -124,7 +125,7 @@ static unsigned long calc_pll_rate(u32 config_word)
return (unsigned long)rate;
}
-void ep93xx_clock_init(void)
+static int __init ep93xx_clock_init(void)
{
u32 value;
@@ -153,4 +154,7 @@ void ep93xx_clock_init(void)
printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
clk_f.rate / 1000000, clk_h.rate / 1000000,
clk_p.rate / 1000000);
+
+ return 0;
}
+arch_initcall(ep93xx_clock_init);
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 6b26346191c..829aed696d9 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -152,22 +152,30 @@ struct sys_timer ep93xx_timer = {
/*************************************************************************
* GPIO handling for EP93xx
*************************************************************************/
-static unsigned char gpio_int_enable[2];
-static unsigned char gpio_int_type1[2];
-static unsigned char gpio_int_type2[2];
+static unsigned char gpio_int_unmasked[3];
+static unsigned char gpio_int_enabled[3];
+static unsigned char gpio_int_type1[3];
+static unsigned char gpio_int_type2[3];
-static void update_gpio_ab_int_params(int port)
+static void update_gpio_int_params(int abf)
{
- if (port == 0) {
+ if (abf == 0) {
__raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE);
__raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2);
__raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1);
- __raw_writeb(gpio_int_enable[0], EP93XX_GPIO_A_INT_ENABLE);
- } else if (port == 1) {
+ __raw_writeb(gpio_int_unmasked[0] & gpio_int_enabled[0], EP93XX_GPIO_A_INT_ENABLE);
+ } else if (abf == 1) {
__raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE);
__raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2);
__raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1);
- __raw_writeb(gpio_int_enable[1], EP93XX_GPIO_B_INT_ENABLE);
+ __raw_writeb(gpio_int_unmasked[1] & gpio_int_enabled[1], EP93XX_GPIO_B_INT_ENABLE);
+ } else if (abf == 2) {
+ __raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE);
+ __raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2);
+ __raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1);
+ __raw_writeb(gpio_int_unmasked[2] & gpio_int_enabled[2], EP93XX_GPIO_F_INT_ENABLE);
+ } else {
+ BUG();
}
}
@@ -192,8 +200,13 @@ void gpio_line_config(int line, int direction)
local_irq_save(flags);
if (direction == GPIO_OUT) {
if (line >= 0 && line < 16) {
- gpio_int_enable[line >> 3] &= ~(1 << (line & 7));
- update_gpio_ab_int_params(line >> 3);
+ /* Port A/B. */
+ gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
+ update_gpio_int_params(line >> 3);
+ } else if (line >= 40 && line < 48) {
+ /* Port F. */
+ gpio_int_unmasked[2] &= ~(1 << (line & 7));
+ update_gpio_int_params(2);
}
v = __raw_readb(data_direction_register);
@@ -244,8 +257,7 @@ EXPORT_SYMBOL(gpio_line_set);
/*************************************************************************
* EP93xx IRQ handling
*************************************************************************/
-static void ep93xx_gpio_ab_irq_handler(unsigned int irq,
- struct irq_desc *desc)
+static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
{
unsigned char status;
int i;
@@ -267,37 +279,46 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq,
}
}
-static void ep93xx_gpio_ab_irq_mask_ack(unsigned int irq)
+static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4);
+
+ desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
+}
+
+static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
{
int line = irq - IRQ_EP93XX_GPIO(0);
int port = line >> 3;
- gpio_int_enable[port] &= ~(1 << (line & 7));
- update_gpio_ab_int_params(port);
+ gpio_int_unmasked[port] &= ~(1 << (line & 7));
+ update_gpio_int_params(port);
- if (line >> 3) {
- __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
- } else {
+ if (port == 0) {
__raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK);
+ } else if (port == 1) {
+ __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
+ } else if (port == 2) {
+ __raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK);
}
}
-static void ep93xx_gpio_ab_irq_mask(unsigned int irq)
+static void ep93xx_gpio_irq_mask(unsigned int irq)
{
int line = irq - IRQ_EP93XX_GPIO(0);
int port = line >> 3;
- gpio_int_enable[port] &= ~(1 << (line & 7));
- update_gpio_ab_int_params(port);
+ gpio_int_unmasked[port] &= ~(1 << (line & 7));
+ update_gpio_int_params(port);
}
-static void ep93xx_gpio_ab_irq_unmask(unsigned int irq)
+static void ep93xx_gpio_irq_unmask(unsigned int irq)
{
int line = irq - IRQ_EP93XX_GPIO(0);
int port = line >> 3;
- gpio_int_enable[port] |= 1 << (line & 7);
- update_gpio_ab_int_params(port);
+ gpio_int_unmasked[port] |= 1 << (line & 7);
+ update_gpio_int_params(port);
}
@@ -306,40 +327,51 @@ static void ep93xx_gpio_ab_irq_unmask(unsigned int irq)
* edge (1) triggered, while gpio_int_type2 controls whether it
* triggers on low/falling (0) or high/rising (1).
*/
-static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type)
+static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
{
int port;
int line;
line = irq - IRQ_EP93XX_GPIO(0);
- gpio_line_config(line, GPIO_IN);
+ if (line >= 0 && line < 16) {
+ gpio_line_config(line, GPIO_IN);
+ } else {
+ gpio_line_config(EP93XX_GPIO_LINE_F(line), GPIO_IN);
+ }
port = line >> 3;
line &= 7;
if (type & IRQT_RISING) {
+ gpio_int_enabled[port] |= 1 << line;
gpio_int_type1[port] |= 1 << line;
gpio_int_type2[port] |= 1 << line;
} else if (type & IRQT_FALLING) {
+ gpio_int_enabled[port] |= 1 << line;
gpio_int_type1[port] |= 1 << line;
gpio_int_type2[port] &= ~(1 << line);
} else if (type & IRQT_HIGH) {
+ gpio_int_enabled[port] |= 1 << line;
gpio_int_type1[port] &= ~(1 << line);
gpio_int_type2[port] |= 1 << line;
} else if (type & IRQT_LOW) {
+ gpio_int_enabled[port] |= 1 << line;
gpio_int_type1[port] &= ~(1 << line);
gpio_int_type2[port] &= ~(1 << line);
+ } else {
+ gpio_int_enabled[port] &= ~(1 << line);
}
- update_gpio_ab_int_params(port);
+ update_gpio_int_params(port);
return 0;
}
-static struct irq_chip ep93xx_gpio_ab_irq_chip = {
- .ack = ep93xx_gpio_ab_irq_mask_ack,
- .mask = ep93xx_gpio_ab_irq_mask,
- .unmask = ep93xx_gpio_ab_irq_unmask,
- .set_type = ep93xx_gpio_ab_irq_type,
+static struct irq_chip ep93xx_gpio_irq_chip = {
+ .name = "GPIO",
+ .ack = ep93xx_gpio_irq_mask_ack,
+ .mask = ep93xx_gpio_irq_mask,
+ .unmask = ep93xx_gpio_irq_unmask,
+ .set_type = ep93xx_gpio_irq_type,
};
@@ -350,12 +382,21 @@ void __init ep93xx_init_irq(void)
vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
- for (irq = IRQ_EP93XX_GPIO(0) ; irq <= IRQ_EP93XX_GPIO(15); irq++) {
- set_irq_chip(irq, &ep93xx_gpio_ab_irq_chip);
+ for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) {
+ set_irq_chip(irq, &ep93xx_gpio_irq_chip);
set_irq_handler(irq, handle_level_irq);
set_irq_flags(irq, IRQF_VALID);
}
+
set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
+ set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
+ set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
+ set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
+ set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
+ set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
+ set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
+ set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
+ set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
}
@@ -461,8 +502,6 @@ void __init ep93xx_init_devices(void)
{
unsigned int v;
- ep93xx_clock_init();
-
/*
* Disallow access to MaverickCrunch initially.
*/
@@ -477,8 +516,4 @@ void __init ep93xx_init_devices(void)
platform_device_register(&ep93xx_rtc_device);
platform_device_register(&ep93xx_ohci_device);
-
-#ifdef CONFIG_CRUNCH
- elf_hwcap |= HWCAP_CRUNCH;
-#endif
}
diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c
new file mode 100644
index 00000000000..f28c1294cae
--- /dev/null
+++ b/arch/arm/mach-ep93xx/micro9.c
@@ -0,0 +1,157 @@
+/*
+ * linux/arch/arm/mach-ep93xx/micro9.c
+ *
+ * Copyright (C) 2006 Contec Steuerungstechnik & Automation GmbH
+ * Manfred Gruber <manfred.gruber@contec.at>
+ *
+ * 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/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+
+#include <linux/mtd/physmap.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+static struct ep93xx_eth_data micro9_eth_data = {
+ .phy_id = 0x1f,
+};
+
+static struct resource micro9_eth_resource[] = {
+ {
+ .start = EP93XX_ETHERNET_PHYS_BASE,
+ .end = EP93XX_ETHERNET_PHYS_BASE + 0xffff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_EP93XX_ETHERNET,
+ .end = IRQ_EP93XX_ETHERNET,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device micro9_eth_device = {
+ .name = "ep93xx-eth",
+ .id = -1,
+ .dev = {
+ .platform_data = &micro9_eth_data,
+ },
+ .num_resources = ARRAY_SIZE(micro9_eth_resource),
+ .resource = micro9_eth_resource,
+};
+
+static void __init micro9_eth_init(void)
+{
+ memcpy(micro9_eth_data.dev_addr,
+ (void *)(EP93XX_ETHERNET_BASE + 0x50), 6);
+ platform_device_register(&micro9_eth_device);
+}
+
+static void __init micro9_init(void)
+{
+ micro9_eth_init();
+}
+
+/*
+ * Micro9-H
+ */
+#ifdef CONFIG_MACH_MICRO9H
+static struct physmap_flash_data micro9h_flash_data = {
+ .width = 4,
+};
+
+static struct resource micro9h_flash_resource = {
+ .start = 0x10000000,
+ .end = 0x13ffffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device micro9h_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &micro9h_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &micro9h_flash_resource,
+};
+
+static void __init micro9h_init(void)
+{
+ platform_device_register(&micro9h_flash);
+}
+
+static void __init micro9h_init_machine(void)
+{
+ ep93xx_init_devices();
+ micro9_init();
+ micro9h_init();
+}
+
+MACHINE_START(MICRO9, "Contec Hypercontrol Micro9-H")
+ /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+ .phys_io = EP93XX_APB_PHYS_BASE,
+ .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = micro9h_init_machine,
+MACHINE_END
+#endif
+
+/*
+ * Micro9-M
+ */
+#ifdef CONFIG_MACH_MICRO9M
+static void __init micro9m_init_machine(void)
+{
+ ep93xx_init_devices();
+ micro9_init();
+}
+
+MACHINE_START(MICRO9M, "Contec Hypercontrol Micro9-M")
+ /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+ .phys_io = EP93XX_APB_PHYS_BASE,
+ .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = micro9m_init_machine,
+MACHINE_END
+#endif
+
+/*
+ * Micro9-L
+ */
+#ifdef CONFIG_MACH_MICRO9L
+static void __init micro9l_init_machine(void)
+{
+ ep93xx_init_devices();
+ micro9_init();
+}
+
+MACHINE_START(MICRO9L, "Contec Hypercontrol Micro9-L")
+ /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */
+ .phys_io = EP93XX_APB_PHYS_BASE,
+ .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = ep93xx_map_io,
+ .init_irq = ep93xx_init_irq,
+ .timer = &ep93xx_timer,
+ .init_machine = micro9l_init_machine,
+MACHINE_END
+#endif
+
diff --git a/arch/arm/mach-iop13xx/irq.c b/arch/arm/mach-iop13xx/irq.c
index dbbc07c38b1..162b9321496 100644
--- a/arch/arm/mach-iop13xx/irq.c
+++ b/arch/arm/mach-iop13xx/irq.c
@@ -250,11 +250,14 @@ static struct irq_chip iop13xx_irqchip4 = {
.unmask = iop13xx_irq_unmask3,
};
+extern void iop_init_cp6_handler(void);
+
void __init iop13xx_init_irq(void)
{
unsigned int i;
u32 cp_flags = iop13xx_cp6_save();
+ iop_init_cp6_handler();
/* disable all interrupts */
write_intctl_0(0);
diff --git a/arch/arm/mach-iop32x/irq.c b/arch/arm/mach-iop32x/irq.c
index 3ec1cd5c4f9..8b0ac5590ae 100644
--- a/arch/arm/mach-iop32x/irq.c
+++ b/arch/arm/mach-iop32x/irq.c
@@ -60,6 +60,8 @@ void __init iop32x_init_irq(void)
{
int i;
+ iop_init_cp6_handler();
+
intctl_write(0);
intstr_write(0);
if (machine_is_glantank() ||
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 2499a7707e3..966aa51aee0 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -120,6 +120,20 @@ static struct hw_pci n2100_pci __initdata = {
.map_irq = n2100_pci_map_irq,
};
+/*
+ * Both r8169 chips on the n2100 exhibit PCI parity problems. Set
+ * the ->broken_parity_status flag for both ports so that the r8169
+ * driver knows it should ignore error interrupts.
+ */
+static void n2100_fixup_r8169(struct pci_dev *dev)
+{
+ if (dev->bus->number == 0 &&
+ (dev->devfn == PCI_DEVFN(1, 0) ||
+ dev->devfn == PCI_DEVFN(2, 0)))
+ dev->broken_parity_status = 1;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REALTEK, PCI_ANY_ID, n2100_fixup_r8169);
+
static int __init n2100_pci_init(void)
{
if (machine_is_n2100())
diff --git a/arch/arm/mach-iop33x/irq.c b/arch/arm/mach-iop33x/irq.c
index 00b37f32d72..effbe6b782d 100644
--- a/arch/arm/mach-iop33x/irq.c
+++ b/arch/arm/mach-iop33x/irq.c
@@ -110,6 +110,8 @@ void __init iop33x_init_irq(void)
{
int i;
+ iop_init_cp6_handler();
+
intctl0_write(0);
intctl1_write(0);
intstr0_write(0);
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index e316bd93313..8a339cdfe22 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -17,7 +17,7 @@ config MACH_NSLU2
NSLU2 NAS device. For more information on this platform,
see http://www.nslu2-linux.org
-config ARCH_AVILA
+config MACH_AVILA
bool "Avila"
select PCI
help
@@ -25,6 +25,14 @@ config ARCH_AVILA
Avila Network Platform. For more information on this platform,
see <file:Documentation/arm/IXP4xx>.
+config MACH_LOFT
+ bool "Loft"
+ depends on MACH_AVILA
+ help
+ Say 'Y' here if you want your kernel to support the Giant
+ Shoulder Inc Loft board (a minor variation on the standard
+ Gateworks Avila Network Platform).
+
config ARCH_ADI_COYOTE
bool "Coyote"
select PCI
@@ -86,7 +94,7 @@ config MACH_NAS100D
#
config ARCH_IXDP4XX
bool
- depends on ARCH_IXDP425 || ARCH_AVILA || MACH_IXDP465
+ depends on ARCH_IXDP425 || MACH_IXDP465
default y
#
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 640315d8b96..746e297284e 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -6,6 +6,7 @@ obj-pci-y :=
obj-pci-n :=
obj-pci-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o
+obj-pci-$(CONFIG_MACH_AVILA) += avila-pci.o
obj-pci-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o
obj-pci-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o
obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o
@@ -15,6 +16,7 @@ obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o
obj-y += common.o
obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-setup.o
+obj-$(CONFIG_MACH_AVILA) += avila-setup.o
obj-$(CONFIG_MACH_IXDPG425) += coyote-setup.o
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o
obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o
diff --git a/arch/arm/mach-ixp4xx/avila-pci.c b/arch/arm/mach-ixp4xx/avila-pci.c
new file mode 100644
index 00000000000..3f867691d9f
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/avila-pci.c
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-ixp4xx/avila-pci.c
+ *
+ * Gateworks Avila board-level PCI initialization
+ *
+ * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
+ *
+ * Based on ixdp-pci.c
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+
+#include <asm/mach/pci.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+void __init avila_pci_preinit(void)
+{
+ set_irq_type(IRQ_AVILA_PCI_INTA, IRQT_LOW);
+ set_irq_type(IRQ_AVILA_PCI_INTB, IRQT_LOW);
+ set_irq_type(IRQ_AVILA_PCI_INTC, IRQT_LOW);
+ set_irq_type(IRQ_AVILA_PCI_INTD, IRQT_LOW);
+
+ ixp4xx_pci_preinit();
+}
+
+static int __init avila_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ static int pci_irq_table[AVILA_PCI_IRQ_LINES] = {
+ IRQ_AVILA_PCI_INTA,
+ IRQ_AVILA_PCI_INTB,
+ IRQ_AVILA_PCI_INTC,
+ IRQ_AVILA_PCI_INTD
+ };
+
+ int irq = -1;
+
+ if (slot >= 1 &&
+ slot <= (machine_is_loft() ? LOFT_PCI_MAX_DEV : AVILA_PCI_MAX_DEV) &&
+ pin >= 1 && pin <= AVILA_PCI_IRQ_LINES) {
+ irq = pci_irq_table[(slot + pin - 2) % 4];
+ }
+
+ return irq;
+}
+
+struct hw_pci avila_pci __initdata = {
+ .nr_controllers = 1,
+ .preinit = avila_pci_preinit,
+ .swizzle = pci_std_swizzle,
+ .setup = ixp4xx_setup,
+ .scan = ixp4xx_scan_bus,
+ .map_irq = avila_map_irq,
+};
+
+int __init avila_pci_init(void)
+{
+ if (machine_is_avila() || machine_is_loft())
+ pci_common_init(&avila_pci);
+ return 0;
+}
+
+subsys_initcall(avila_pci_init);
+
diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
new file mode 100644
index 00000000000..d59b8dc7dc7
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/avila-setup.c
@@ -0,0 +1,192 @@
+/*
+ * arch/arm/mach-ixp4xx/avila-setup.c
+ *
+ * Gateworks Avila board-setup
+ *
+ * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
+ *
+ * Based on ixdp-setup.c
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data avila_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+};
+
+static struct resource avila_flash_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device avila_flash = {
+ .name = "IXP4XX-Flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &avila_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &avila_flash_resource,
+};
+
+static struct ixp4xx_i2c_pins avila_i2c_gpio_pins = {
+ .sda_pin = AVILA_SDA_PIN,
+ .scl_pin = AVILA_SCL_PIN,
+};
+
+static struct platform_device avila_i2c_controller = {
+ .name = "IXP4XX-I2C",
+ .id = 0,
+ .dev = {
+ .platform_data = &avila_i2c_gpio_pins,
+ },
+ .num_resources = 0
+};
+
+static struct resource avila_uart_resources[] = {
+ {
+ .start = IXP4XX_UART1_BASE_PHYS,
+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM
+ },
+ {
+ .start = IXP4XX_UART2_BASE_PHYS,
+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM
+ }
+};
+
+static struct plat_serial8250_port avila_uart_data[] = {
+ {
+ .mapbase = IXP4XX_UART1_BASE_PHYS,
+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+ .irq = IRQ_IXP4XX_UART1,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+ },
+ {
+ .mapbase = IXP4XX_UART2_BASE_PHYS,
+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+ .irq = IRQ_IXP4XX_UART2,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+ },
+ { },
+};
+
+static struct platform_device avila_uart = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev.platform_data = avila_uart_data,
+ .num_resources = 2,
+ .resource = avila_uart_resources
+};
+
+static struct resource avila_pata_resources[] = {
+ {
+ .flags = IORESOURCE_MEM
+ },
+ {
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "intrq",
+ .start = IRQ_IXP4XX_GPIO12,
+ .end = IRQ_IXP4XX_GPIO12,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct ixp4xx_pata_data avila_pata_data = {
+ .cs0_bits = 0xbfff0043,
+ .cs1_bits = 0xbfff0043,
+};
+
+static struct platform_device avila_pata = {
+ .name = "pata_ixp4xx_cf",
+ .id = 0,
+ .dev.platform_data = &avila_pata_data,
+ .num_resources = ARRAY_SIZE(avila_pata_resources),
+ .resource = avila_pata_resources,
+};
+
+static struct platform_device *avila_devices[] __initdata = {
+ &avila_i2c_controller,
+ &avila_flash,
+ &avila_uart
+};
+
+static void __init avila_init(void)
+{
+ ixp4xx_sys_init();
+
+ avila_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+ avila_flash_resource.end =
+ IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+ platform_add_devices(avila_devices, ARRAY_SIZE(avila_devices));
+
+ avila_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(1);
+ avila_pata_resources[0].end = IXP4XX_EXP_BUS_END(1);
+
+ avila_pata_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
+ avila_pata_resources[1].end = IXP4XX_EXP_BUS_END(2);
+
+ avila_pata_data.cs0_cfg = IXP4XX_EXP_CS1;
+ avila_pata_data.cs1_cfg = IXP4XX_EXP_CS2;
+
+ platform_device_register(&avila_pata);
+
+}
+
+MACHINE_START(AVILA, "Gateworks Avila Network Platform")
+ /* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+ .map_io = ixp4xx_map_io,
+ .init_irq = ixp4xx_init_irq,
+ .timer = &ixp4xx_timer,
+ .boot_params = 0x0100,
+ .init_machine = avila_init,
+MACHINE_END
+
+ /*
+ * Loft is functionally equivalent to Avila except that it has a
+ * different number for the maximum PCI devices. The MACHINE
+ * structure below is identical to Avila except for the comment.
+ */
+#ifdef CONFIG_MACH_LOFT
+MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
+ /* Maintainer: Tom Billman <kernel@giantshoulderinc.com> */
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+ .map_io = ixp4xx_map_io,
+ .init_irq = ixp4xx_init_irq,
+ .timer = &ixp4xx_timer,
+ .boot_params = 0x0100,
+ .init_machine = avila_init,
+MACHINE_END
+#endif
+
diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c
index d5156c043f0..99c1dc8033c 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
@@ -66,7 +66,7 @@ struct hw_pci ixdp425_pci __initdata = {
int __init ixdp425_pci_init(void)
{
if (machine_is_ixdp425() || machine_is_ixcdp1100() ||
- machine_is_avila() || machine_is_ixdp465())
+ machine_is_ixdp465())
pci_common_init(&ixdp425_pci);
return 0;
}
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index da72383ee30..04b1d56396a 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -156,23 +156,3 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
.init_machine = ixdp425_init,
MACHINE_END
#endif
-
-/*
- * Avila is functionally equivalent to IXDP425 except that it adds
- * a CF IDE slot hanging off the expansion bus. When we have a
- * driver for IXP4xx CF IDE with driver model support we'll move
- * Avila to it's own setup file.
- */
-#ifdef CONFIG_ARCH_AVILA
-MACHINE_START(AVILA, "Gateworks Avila Network Platform")
- /* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
- .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
- .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
- .map_io = ixp4xx_map_io,
- .init_irq = ixp4xx_init_irq,
- .timer = &ixp4xx_timer,
- .boot_params = 0x0100,
- .init_machine = ixdp425_init,
-MACHINE_END
-#endif
-
diff --git a/arch/arm/mach-ns9xxx/Kconfig b/arch/arm/mach-ns9xxx/Kconfig
new file mode 100644
index 00000000000..8175ba92a2f
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/Kconfig
@@ -0,0 +1,21 @@
+if ARCH_NS9XXX
+
+menu "NS9xxx Implementations"
+
+config MACH_CC9P9360DEV
+ bool "Connect Core 9P 9360 on an A9M9750 Devboard"
+ select PROCESSOR_NS9360
+ select BOARD_A9M9750DEV
+ help
+ Say Y here if you are using the Digi Connect Core 9P 9360
+ on an A9M9750 Development Board.
+
+config PROCESSOR_NS9360
+ bool
+
+config BOARD_A9M9750DEV
+ bool
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-ns9xxx/Makefile b/arch/arm/mach-ns9xxx/Makefile
new file mode 100644
index 00000000000..91e945f5e16
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/Makefile
@@ -0,0 +1,5 @@
+obj-y := irq.o time.o generic.o
+
+obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o
+
+obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o
diff --git a/arch/arm/mach-ns9xxx/Makefile.boot b/arch/arm/mach-ns9xxx/Makefile.boot
new file mode 100644
index 00000000000..75ed64e90fa
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/Makefile.boot
@@ -0,0 +1,2 @@
+zreladdr-y := 0x108000
+params_phys-y := 0x100
diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.c b/arch/arm/mach-ns9xxx/board-a9m9750dev.c
new file mode 100644
index 00000000000..25289884a60
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/board-a9m9750dev.c
@@ -0,0 +1,199 @@
+/*
+ * arch/arm/mach-ns9xxx/board-a9m9750dev.c
+ *
+ * Copyright (C) 2006,2007 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/irq.h>
+
+#include <asm/mach/map.h>
+
+#include <asm/arch-ns9xxx/board.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/regs-mem.h>
+#include <asm/arch-ns9xxx/regs-bbu.h>
+#include <asm/arch-ns9xxx/regs-board-a9m9750dev.h>
+
+#include "board-a9m9750dev.h"
+
+static struct map_desc board_a9m9750dev_io_desc[] __initdata = {
+ { /* FPGA on CS0 */
+ .virtual = io_p2v(NS9XXX_CSxSTAT_PHYS(0)),
+ .pfn = __phys_to_pfn(NS9XXX_CSxSTAT_PHYS(0)),
+ .length = NS9XXX_CS0STAT_LENGTH,
+ .type = MT_DEVICE,
+ },
+};
+
+void __init board_a9m9750dev_map_io(void)
+{
+ iotable_init(board_a9m9750dev_io_desc,
+ ARRAY_SIZE(board_a9m9750dev_io_desc));
+}
+
+static void a9m9750dev_fpga_ack_irq(unsigned int irq)
+{
+ /* nothing */
+}
+
+static void a9m9750dev_fpga_mask_irq(unsigned int irq)
+{
+ FPGA_IER &= ~(1 << (irq - FPGA_IRQ(0)));
+}
+
+static void a9m9750dev_fpga_maskack_irq(unsigned int irq)
+{
+ a9m9750dev_fpga_mask_irq(irq);
+ a9m9750dev_fpga_ack_irq(irq);
+}
+
+static void a9m9750dev_fpga_unmask_irq(unsigned int irq)
+{
+ FPGA_IER |= 1 << (irq - FPGA_IRQ(0));
+}
+
+static struct irq_chip a9m9750dev_fpga_chip = {
+ .ack = a9m9750dev_fpga_ack_irq,
+ .mask = a9m9750dev_fpga_mask_irq,
+ .mask_ack = a9m9750dev_fpga_maskack_irq,
+ .unmask = a9m9750dev_fpga_unmask_irq,
+};
+
+static void a9m9750dev_fpga_demux_handler(unsigned int irq,
+ struct irq_desc *desc)
+{
+ int stat = FPGA_ISR;
+
+ while (stat != 0) {
+ int irqno = fls(stat) - 1;
+
+ stat &= ~(1 << irqno);
+
+ desc = irq_desc + FPGA_IRQ(irqno);
+
+ desc_handle_irq(irqno, desc);
+ }
+}
+
+void __init board_a9m9750dev_init_irq(void)
+{
+ u32 reg;
+ int i;
+
+ /*
+ * configure gpio for IRQ_EXT2
+ * use GPIO 11, because GPIO 32 is used for the LCD
+ */
+ /* XXX: proper GPIO handling */
+ BBU_GC(2) &= ~0x2000;
+
+ for (i = FPGA_IRQ(0); i <= FPGA_IRQ(7); ++i) {
+ set_irq_chip(i, &a9m9750dev_fpga_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+
+ /* IRQ_EXT2: level sensitive + active low */
+ reg = SYS_EIC(2);
+ REGSET(reg, SYS_EIC, PLTY, AL);
+ REGSET(reg, SYS_EIC, LVEDG, LEVEL);
+ SYS_EIC(2) = reg;
+
+ set_irq_chained_handler(IRQ_EXT2,
+ a9m9750dev_fpga_demux_handler);
+}
+
+static struct plat_serial8250_port board_a9m9750dev_serial8250_port[] = {
+ {
+ .iobase = FPGA_UARTA_BASE,
+ .membase = (unsigned char*)FPGA_UARTA_BASE,
+ .mapbase = FPGA_UARTA_BASE,
+ .irq = IRQ_FPGA_UARTA,
+ .iotype = UPIO_MEM,
+ .uartclk = 18432000,
+ .regshift = 0,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+ }, {
+ .iobase = FPGA_UARTB_BASE,
+ .membase = (unsigned char*)FPGA_UARTB_BASE,
+ .mapbase = FPGA_UARTB_BASE,
+ .irq = IRQ_FPGA_UARTB,
+ .iotype = UPIO_MEM,
+ .uartclk = 18432000,
+ .regshift = 0,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+ }, {
+ .iobase = FPGA_UARTC_BASE,
+ .membase = (unsigned char*)FPGA_UARTC_BASE,
+ .mapbase = FPGA_UARTC_BASE,
+ .irq = IRQ_FPGA_UARTC,
+ .iotype = UPIO_MEM,
+ .uartclk = 18432000,
+ .regshift = 0,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+ }, {
+ .iobase = FPGA_UARTD_BASE,
+ .membase = (unsigned char*)FPGA_UARTD_BASE,
+ .mapbase = FPGA_UARTD_BASE,
+ .irq = IRQ_FPGA_UARTD,
+ .iotype = UPIO_MEM,
+ .uartclk = 18432000,
+ .regshift = 0,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
+ }, {
+ /* end marker */
+ },
+};
+
+static struct platform_device board_a9m9750dev_serial_device = {
+ .name = "serial8250",
+ .dev = {
+ .platform_data = board_a9m9750dev_serial8250_port,
+ },
+};
+
+static struct platform_device *board_a9m9750dev_devices[] __initdata = {
+ &board_a9m9750dev_serial_device,
+};
+
+void __init board_a9m9750dev_init_machine(void)
+{
+ u32 reg;
+
+ /* setup static CS0: memory base ... */
+ REGSETIM(SYS_SMCSSMB(0), SYS_SMCSSMB, CSxB,
+ NS9XXX_CSxSTAT_PHYS(0) >> 12);
+
+ /* ... and mask */
+ reg = SYS_SMCSSMM(0);
+ REGSETIM(reg, SYS_SMCSSMM, CSxM, 0xfffff);
+ REGSET(reg, SYS_SMCSSMM, CSEx, EN);
+ SYS_SMCSSMM(0) = reg;
+
+ /* setup static CS0: memory configuration */
+ reg = MEM_SMC(0);
+ REGSET(reg, MEM_SMC, WSMC, OFF);
+ REGSET(reg, MEM_SMC, BSMC, OFF);
+ REGSET(reg, MEM_SMC, EW, OFF);
+ REGSET(reg, MEM_SMC, PB, 1);
+ REGSET(reg, MEM_SMC, PC, AL);
+ REGSET(reg, MEM_SMC, PM, DIS);
+ REGSET(reg, MEM_SMC, MW, 8);
+ MEM_SMC(0) = reg;
+
+ /* setup static CS0: timing */
+ MEM_SMWED(0) = 0x2;
+ MEM_SMOED(0) = 0x2;
+ MEM_SMRD(0) = 0x6;
+ MEM_SMWD(0) = 0x6;
+
+ platform_add_devices(board_a9m9750dev_devices,
+ ARRAY_SIZE(board_a9m9750dev_devices));
+}
+
diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.h b/arch/arm/mach-ns9xxx/board-a9m9750dev.h
new file mode 100644
index 00000000000..edc75abbc5d
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/board-a9m9750dev.h
@@ -0,0 +1,15 @@
+/*
+ * arch/arm/mach-ns9xxx/board-a9m9750dev.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/init.h>
+
+void __init board_a9m9750dev_map_io(void);
+void __init board_a9m9750dev_init_machine(void);
+void __init board_a9m9750dev_init_irq(void);
diff --git a/arch/arm/mach-ns9xxx/generic.c b/arch/arm/mach-ns9xxx/generic.c
new file mode 100644
index 00000000000..83e2b6532b2
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/generic.c
@@ -0,0 +1,42 @@
+/*
+ * arch/arm/mach-ns9xxx/generic.c
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/regs-mem.h>
+#include <asm/arch-ns9xxx/board.h>
+
+static struct map_desc standard_io_desc[] __initdata = {
+ { /* BBus */
+ .virtual = io_p2v(0x90000000),
+ .pfn = __phys_to_pfn(0x90000000),
+ .length = 0x00700000,
+ .type = MT_DEVICE,
+ }, { /* AHB */
+ .virtual = io_p2v(0xa0100000),
+ .pfn = __phys_to_pfn(0xa0100000),
+ .length = 0x00900000,
+ .type = MT_DEVICE,
+ },
+};
+
+void __init ns9xxx_map_io(void)
+{
+ iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+}
+
+void __init ns9xxx_init_machine(void)
+{
+}
diff --git a/arch/arm/mach-ns9xxx/generic.h b/arch/arm/mach-ns9xxx/generic.h
new file mode 100644
index 00000000000..687e291773f
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/generic.h
@@ -0,0 +1,19 @@
+/*
+ * arch/arm/mach-ns9xxx/generic.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/time.h>
+#include <asm/mach/time.h>
+#include <linux/init.h>
+
+void __init ns9xxx_init_irq(void);
+void __init ns9xxx_map_io(void);
+void __init ns9xxx_init_machine(void);
+
+extern struct sys_timer ns9xxx_timer;
diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c
new file mode 100644
index 00000000000..83d92724a97
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/irq.c
@@ -0,0 +1,94 @@
+/*
+ * arch/arm/mach-ns9xxx/irq.c
+ *
+ * Copyright (C) 2006,2007 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/interrupt.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/irqs.h>
+#include <asm/arch-ns9xxx/board.h>
+
+#include "generic.h"
+
+static void ns9xxx_ack_irq_timer(unsigned int irq)
+{
+ u32 tc = SYS_TC(irq - IRQ_TIMER0);
+
+ REGSET(tc, SYS_TCx, INTC, SET);
+ SYS_TC(irq - IRQ_TIMER0) = tc;
+
+ REGSET(tc, SYS_TCx, INTC, UNSET);
+ SYS_TC(irq - IRQ_TIMER0) = tc;
+}
+
+void (*ns9xxx_ack_irq_functions[NR_IRQS])(unsigned int) = {
+ [IRQ_TIMER0] = ns9xxx_ack_irq_timer,
+ [IRQ_TIMER1] = ns9xxx_ack_irq_timer,
+ [IRQ_TIMER2] = ns9xxx_ack_irq_timer,
+ [IRQ_TIMER3] = ns9xxx_ack_irq_timer,
+};
+
+static void ns9xxx_mask_irq(unsigned int irq)
+{
+ /* XXX: better use cpp symbols */
+ SYS_IC(irq / 4) &= ~(1 << (7 + 8 * (3 - (irq & 3))));
+}
+
+static void ns9xxx_ack_irq(unsigned int irq)
+{
+ if (!ns9xxx_ack_irq_functions[irq]) {
+ printk(KERN_ERR "no ack function for irq %u\n", irq);
+ BUG();
+ }
+
+ ns9xxx_ack_irq_functions[irq](irq);
+ SYS_ISRADDR = 0;
+}
+
+static void ns9xxx_maskack_irq(unsigned int irq)
+{
+ ns9xxx_mask_irq(irq);
+ ns9xxx_ack_irq(irq);
+}
+
+static void ns9xxx_unmask_irq(unsigned int irq)
+{
+ /* XXX: better use cpp symbols */
+ SYS_IC(irq / 4) |= 1 << (7 + 8 * (3 - (irq & 3)));
+}
+
+static struct irq_chip ns9xxx_chip = {
+ .ack = ns9xxx_ack_irq,
+ .mask = ns9xxx_mask_irq,
+ .mask_ack = ns9xxx_maskack_irq,
+ .unmask = ns9xxx_unmask_irq,
+};
+
+void __init ns9xxx_init_irq(void)
+{
+ int i;
+
+ /* disable all IRQs */
+ for (i = 0; i < 8; ++i)
+ SYS_IC(i) = (4 * i) << 24 | (4 * i + 1) << 16 |
+ (4 * i + 2) << 8 | (4 * i + 3);
+
+ /* simple interrupt prio table:
+ * prio(x) < prio(y) <=> x < y
+ */
+ for (i = 0; i < 32; ++i)
+ SYS_IVA(i) = i;
+
+ for (i = IRQ_WATCHDOG; i <= IRQ_EXT3; ++i) {
+ set_irq_chip(i, &ns9xxx_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+}
diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c b/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
new file mode 100644
index 00000000000..a193dd93151
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
@@ -0,0 +1,41 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "board-a9m9750dev.h"
+#include "generic.h"
+
+static void __init mach_cc9p9360dev_map_io(void)
+{
+ ns9xxx_map_io();
+ board_a9m9750dev_map_io();
+}
+
+static void __init mach_cc9p9360dev_init_irq(void)
+{
+ ns9xxx_init_irq();
+ board_a9m9750dev_init_irq();
+}
+
+static void __init mach_cc9p9360dev_init_machine(void)
+{
+ ns9xxx_init_machine();
+ board_a9m9750dev_init_machine();
+}
+
+MACHINE_START(CC9P9360DEV, "Connect Core 9P 9360 on an A9M9750 Devboard")
+ .map_io = mach_cc9p9360dev_map_io,
+ .init_irq = mach_cc9p9360dev_init_irq,
+ .init_machine = mach_cc9p9360dev_init_machine,
+ .timer = &ns9xxx_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/time.c b/arch/arm/mach-ns9xxx/time.c
new file mode 100644
index 00000000000..eec05f18714
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/time.c
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/mach-ns9xxx/time.c
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/arch-ns9xxx/clock.h>
+#include <asm/arch-ns9xxx/irqs.h>
+#include <asm/arch/system.h>
+#include "generic.h"
+
+#define TIMERCLOCKSELECT 64
+
+static u32 usecs_per_tick;
+
+static irqreturn_t
+ns9xxx_timer_interrupt(int irq, void *dev_id)
+{
+ write_seqlock(&xtime_lock);
+ timer_tick();
+ write_sequnlock(&xtime_lock);
+
+ return IRQ_HANDLED;
+}
+
+static unsigned long ns9xxx_timer_gettimeoffset(void)
+{
+ /* return the microseconds which have passed since the last interrupt
+ * was _serviced_. That is, if an interrupt is pending or the counter
+ * reloads, return one periode more. */
+
+ u32 counter1 = SYS_TR(0);
+ int pending = SYS_ISR & (1 << IRQ_TIMER0);
+ u32 counter2 = SYS_TR(0);
+ u32 elapsed;
+
+ if (pending || counter2 > counter1)
+ elapsed = 2 * SYS_TRC(0) - counter2;
+ else
+ elapsed = SYS_TRC(0) - counter1;
+
+ return (elapsed * usecs_per_tick) >> 16;
+
+}
+
+static struct irqaction ns9xxx_timer_irq = {
+ .name = "NS9xxx Timer Tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = ns9xxx_timer_interrupt,
+};
+
+static void __init ns9xxx_timer_init(void)
+{
+ int tc;
+
+ usecs_per_tick =
+ SH_DIV(1000000 * TIMERCLOCKSELECT, ns9xxx_cpuclock(), 16);
+
+ /* disable timer */
+ if ((tc = SYS_TC(0)) & SYS_TCx_TEN)
+ SYS_TC(0) = tc & ~SYS_TCx_TEN;
+
+ SYS_TRC(0) = SH_DIV(ns9xxx_cpuclock(), (TIMERCLOCKSELECT * HZ), 0);
+
+ REGSET(tc, SYS_TCx, TEN, EN);
+ REGSET(tc, SYS_TCx, TLCS, DIV64); /* This must match TIMERCLOCKSELECT */
+ REGSET(tc, SYS_TCx, INTS, EN);
+ REGSET(tc, SYS_TCx, UDS, DOWN);
+ REGSET(tc, SYS_TCx, TDBG, STOP);
+ REGSET(tc, SYS_TCx, TSZ, 32);
+ REGSET(tc, SYS_TCx, REN, EN);
+ SYS_TC(0) = tc;
+
+ setup_irq(IRQ_TIMER0, &ns9xxx_timer_irq);
+}
+
+struct sys_timer ns9xxx_timer = {
+ .init = ns9xxx_timer_init,
+ .offset = ns9xxx_timer_gettimeoffset,
+};
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 9de1278d234..390524c4710 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -338,6 +338,27 @@ static struct platform_device i2c_device = {
.num_resources = ARRAY_SIZE(i2c_resources),
};
+#ifdef CONFIG_PXA27x
+static struct resource i2c_power_resources[] = {
+ {
+ .start = 0x40f00180,
+ .end = 0x40f001a3,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_PWRI2C,
+ .end = IRQ_PWRI2C,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c_power_device = {
+ .name = "pxa2xx-i2c",
+ .id = 1,
+ .resource = i2c_power_resources,
+ .num_resources = ARRAY_SIZE(i2c_resources),
+};
+#endif
+
void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
{
i2c_device.dev.platform_data = info;
@@ -392,6 +413,9 @@ static struct platform_device *devices[] __initdata = {
&stuart_device,
&pxaficp_device,
&i2c_device,
+#ifdef CONFIG_PXA27x
+ &i2c_power_device,
+#endif
&i2s_device,
&pxartc_device,
};
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index 17f5f4439fe..35156ca39df 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -10,10 +10,21 @@ config MACH_REALVIEW_EB
config REALVIEW_MPCORE
bool "Support MPcore tile"
depends on MACH_REALVIEW_EB
+ select CACHE_L2X0
help
Enable support for the MPCore tile on the Realview platform.
Since there are device address and interrupt differences, a
kernel built with this option enabled is not compatible with
other tiles.
+config REALVIEW_MPCORE_REVB
+ bool "Support MPcore RevB tile"
+ depends on REALVIEW_MPCORE
+ default n
+ help
+ Enable support for the MPCore RevB tile on the Realview platform.
+ Since there are device address differences, a
+ kernel built with this option enabled is not compatible with
+ other tiles.
+
endmenu
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index b8484e15dac..fce3596f995 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -52,13 +52,14 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
- gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE));
+ gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
/*
* let the primary processor know we're out of the
* pen, then head off into the C entry point
*/
pen_release = -1;
+ smp_wmb();
/*
* Synchronise with the boot thread.
@@ -102,6 +103,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
+ smp_rmb();
if (pen_release == -1)
break;
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 9741b4d3c9c..3dba666151d 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -31,6 +31,7 @@
#include <asm/mach-types.h>
#include <asm/hardware/gic.h>
#include <asm/hardware/icst307.h>
+#include <asm/hardware/cache-l2x0.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -57,7 +58,26 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
.pfn = __phys_to_pfn(REALVIEW_GIC_DIST_BASE),
.length = SZ_4K,
.type = MT_DEVICE,
+ },
+#ifdef CONFIG_REALVIEW_MPCORE
+ {
+ .virtual = IO_ADDRESS(REALVIEW_GIC1_CPU_BASE),
+ .pfn = __phys_to_pfn(REALVIEW_GIC1_CPU_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = IO_ADDRESS(REALVIEW_GIC1_DIST_BASE),
+ .pfn = __phys_to_pfn(REALVIEW_GIC1_DIST_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
}, {
+ .virtual = IO_ADDRESS(REALVIEW_MPCORE_L220_BASE),
+ .pfn = __phys_to_pfn(REALVIEW_MPCORE_L220_BASE),
+ .length = SZ_8K,
+ .type = MT_DEVICE,
+ },
+#endif
+ {
.virtual = IO_ADDRESS(REALVIEW_SCTL_BASE),
.pfn = __phys_to_pfn(REALVIEW_SCTL_BASE),
.length = SZ_4K,
@@ -138,19 +158,29 @@ static void __init gic_init_irq(void)
#ifdef CONFIG_REALVIEW_MPCORE
unsigned int pldctrl;
writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
- pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + 0xd8);
+ pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
pldctrl |= 0x00800000; /* New irq mode */
- writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + 0xd8);
+ writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
#endif
- gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE));
- gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE));
+ gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
+ gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
+#ifdef CONFIG_REALVIEW_MPCORE
+ gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64);
+ gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE));
+ gic_cascade_irq(1, IRQ_EB_IRQ1);
+#endif
}
static void __init realview_eb_init(void)
{
int i;
+#ifdef CONFIG_REALVIEW_MPCORE
+ /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
+ * Bits: .... ...0 0111 1001 0000 .... .... .... */
+ l2x0_init(__io_address(REALVIEW_MPCORE_L220_BASE), 0x00790000, 0xfe000fff);
+#endif
clk_register(&realview_clcd_clk);
platform_device_register(&realview_flash_device);
diff --git a/arch/arm/mach-s3c2400/Kconfig b/arch/arm/mach-s3c2400/Kconfig
new file mode 100644
index 00000000000..deab0722836
--- /dev/null
+++ b/arch/arm/mach-s3c2400/Kconfig
@@ -0,0 +1,13 @@
+# arch/arm/mach-s3c2400/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+
+
+menu "S3C2400 Machines"
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2400/Makefile b/arch/arm/mach-s3c2400/Makefile
new file mode 100644
index 00000000000..7e23f4e1376
--- /dev/null
+++ b/arch/arm/mach-s3c2400/Makefile
@@ -0,0 +1,15 @@
+# arch/arm/mach-s3c2400/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_CPU_S3C2400) += gpio.o
+
+# Machine support
+
diff --git a/arch/arm/mach-s3c2410/s3c2400-gpio.c b/arch/arm/mach-s3c2400/gpio.c
index 1576d01d5f8..758e160410e 100644
--- a/arch/arm/mach-s3c2410/s3c2400-gpio.c
+++ b/arch/arm/mach-s3c2400/gpio.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2400-gpio.c
+/* linux/arch/arm/mach-s3c2400/gpio.c
*
* Copyright (c) 2006 Lucas Correia Villa Real <lucasvr@gobolinux.org>
*
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index eb4ec411312..d4b013b283c 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -1,54 +1,51 @@
-if ARCH_S3C2410
+# arch/arm/mach-s3c2410/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
-menu "S3C24XX Implementations"
+config CPU_S3C2410
+ bool
+ depends on ARCH_S3C2410
+ select S3C2410_CLOCK
+ select S3C2410_GPIO
+ select S3C2410_PM if PM
+ help
+ Support for S3C2410 and S3C2410A family from the S3C24XX line
+ of Samsung Mobile CPUs.
-config MACH_AML_M5900
- bool "AML M5900 Series"
- select CPU_S3C2410
- select PM_SIMTEC if PM
+config CPU_S3C2410_DMA
+ bool
+ depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
+ default y if CPU_S3C2410 || CPU_S3C2442
help
- Say Y here if you are using the American Microsystems M5900 Series
- <http://www.amltd.com>
+ DMA device selection for S3C2410 and compatible CPUs
-config MACH_ANUBIS
- bool "Simtec Electronics ANUBIS"
- select CPU_S3C2440
- select PM_SIMTEC if PM
+config S3C2410_PM
+ bool
help
- Say Y here if you are using the Simtec Electronics ANUBIS
- development system
+ Power Management code common to S3C2410 and better
-config MACH_OSIRIS
- bool "Simtec IM2440D20 (OSIRIS) module"
- select CPU_S3C2440
- select PM_SIMTEC if PM
+config S3C2410_GPIO
+ bool
help
- Say Y here if you are using the Simtec IM2440D20 module, also
- known as the Osiris.
+ GPIO code for S3C2410 and similar processors
-config ARCH_BAST
- bool "Simtec Electronics BAST (EB2410ITX)"
- select CPU_S3C2410
- select PM_SIMTEC if PM
- select ISA
+config S3C2410_CLOCK
+ bool
help
- Say Y here if you are using the Simtec Electronics EB2410ITX
- development board (also known as BAST)
+ Clock code for the S3C2410, and similar processors
- Product page: <http://www.simtec.co.uk/products/EB2410ITX/>.
-config BAST_PC104_IRQ
- bool "BAST PC104 IRQ support"
- depends on ARCH_BAST
- default y
- help
- Say Y here to enable the PC104 IRQ routing on the
- Simtec BAST (EB2410ITX)
+menu "S3C2410 Machines"
-config PM_H1940
- bool
+config ARCH_SMDK2410
+ bool "SMDK2410/A9M2410"
+ select CPU_S3C2410
+ select MACH_SMDK
help
- Internal node for H1940 and related PM
+ Say Y here if you are using the SMDK2410 or the derived module A9M2410
+ <http://www.fsforth.de>
config ARCH_H1940
bool "IPAQ H1940"
@@ -57,7 +54,10 @@ config ARCH_H1940
help
Say Y here if you are using the HP IPAQ H1940
- <http://www.handhelds.org/projects/h1940.html>.
+config PM_H1940
+ bool
+ help
+ Internal node for H1940 and related PM
config MACH_N30
bool "Acer N30"
@@ -65,53 +65,36 @@ config MACH_N30
help
Say Y here if you are using the Acer N30
- <http://zoo.weinigel.se/n30>.
-
-config MACH_SMDK
- bool
- help
- Common machine code for SMDK2410 and SMDK2440
-
-config ARCH_SMDK2410
- bool "SMDK2410/A9M2410"
+config ARCH_BAST
+ bool "Simtec Electronics BAST (EB2410ITX)"
select CPU_S3C2410
- select MACH_SMDK
+ select PM_SIMTEC if PM
+ select ISA
help
- Say Y here if you are using the SMDK2410 or the derived module A9M2410
- <http://www.fsforth.de>
+ Say Y here if you are using the Simtec Electronics EB2410ITX
+ development board (also known as BAST)
-config ARCH_S3C2440
- bool "SMDK2440"
- select CPU_S3C2440
- select MACH_SMDK
+config MACH_OTOM
+ bool "NexVision OTOM Board"
+ select CPU_S3C2410
help
- Say Y here if you are using the SMDK2440.
-
-config SMDK2440_CPU2440
- bool "SMDK2440 with S3C2440 CPU module"
- depends on ARCH_S3C2440
- default y if ARCH_S3C2440
- select CPU_S3C2440
-
-config SMDK2440_CPU2442
- bool "SMDM2440 with S3C2442 CPU module"
- depends on ARCH_S3C2440
- select CPU_S3C2442
+ Say Y here if you are using the Nex Vision OTOM board
-config MACH_S3C2413
- bool
+config MACH_AML_M5900
+ bool "AML M5900 Series"
+ select CPU_S3C2410
+ select PM_SIMTEC if PM
help
- Internal node for S3C2413 version of SMDK2413, so that
- machine_is_s3c2413() will work when MACH_SMDK2413 is
- selected
+ Say Y here if you are using the American Microsystems M5900 Series
+ <http://www.amltd.com>
-config MACH_SMDK2413
- bool "SMDK2413"
- select CPU_S3C2412
- select MACH_S3C2413
- select MACH_SMDK
+config BAST_PC104_IRQ
+ bool "BAST PC104 IRQ support"
+ depends on ARCH_BAST
+ default y
help
- Say Y here if you are using an SMDK2413
+ Say Y here to enable the PC104 IRQ routing on the
+ Simtec BAST (EB2410ITX)
config MACH_VR1000
bool "Thorcom VR1000"
@@ -120,202 +103,11 @@ config MACH_VR1000
help
Say Y here if you are using the Thorcom VR1000 board.
- This linux port is currently being maintained by Simtec, on behalf
- of Thorcom. Any queries, please contact Thorcom first.
-
-config MACH_RX3715
- bool "HP iPAQ rx3715"
- select CPU_S3C2440
- select PM_H1940 if PM
- help
- Say Y here if you are using the HP iPAQ rx3715.
-
- See <http://www.handhelds.org/projects/rx3715.html> for more
- information on this project
-
-config MACH_OTOM
- bool "NexVision OTOM Board"
- select CPU_S3C2410
- help
- Say Y here if you are using the Nex Vision OTOM board
-
-config MACH_NEXCODER_2440
- bool "NexVision NEXCODER 2440 Light Board"
- select CPU_S3C2440
- help
- Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
-
-config MACH_VSTMS
- bool "VMSTMS"
- select CPU_S3C2412
+config MACH_QT2410
+ bool "QT2410"
+ select CPU_S3C2410
help
- Say Y here if you are using an VSTMS board
+ Say Y here if you are using the Armzone QT2410
endmenu
-config S3C2410_CLOCK
- bool
- help
- Clock code for the S3C2410, and similar processors
-
-config S3C2410_PM
- bool
- help
- Power Management code common to S3C2410 and better
-
-config CPU_S3C2410_DMA
- bool
- depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
- default y if CPU_S3C2410 || CPU_S3C2442
- help
- DMA device selection for S3C2410 and compatible CPUs
-
-config CPU_S3C2410
- bool
- depends on ARCH_S3C2410
- select S3C2410_CLOCK
- select S3C2410_PM if PM
- help
- Support for S3C2410 and S3C2410A family from the S3C24XX line
- of Samsung Mobile CPUs.
-
-# internal node to signify if we are only dealing with an S3C2412
-
-config CPU_S3C2412_ONLY
- bool
- depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
- !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
- default y if CPU_S3C2412
-
-config S3C2412_PM
- bool
- help
- Internal config node to apply S3C2412 power management
-
-config CPU_S3C2412
- bool
- depends on ARCH_S3C2410
- select S3C2412_PM if PM
- help
- Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
-
-config CPU_S3C244X
- bool
- depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
- help
- Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
-
-config CPU_S3C2440
- bool
- depends on ARCH_S3C2410
- select S3C2410_CLOCK
- select S3C2410_PM if PM
- select CPU_S3C244X
- help
- Support for S3C2440 Samsung Mobile CPU based systems.
-
-config CPU_S3C2442
- bool
- depends on ARCH_S3C2420
- select S3C2410_CLOCK
- select S3C2410_PM if PM
- select CPU_S3C244X
- help
- Support for S3C2442 Samsung Mobile CPU based systems.
-
-comment "S3C2410 Boot"
-
-config S3C2410_BOOT_WATCHDOG
- bool "S3C2410 Initialisation watchdog"
- depends on ARCH_S3C2410 && S3C2410_WATCHDOG
- help
- Say y to enable the watchdog during the kernel decompression
- stage. If the kernel fails to uncompress, then the watchdog
- will trigger a reset and the system should restart.
-
- Although this uses the same hardware unit as the kernel watchdog
- driver, it is not a replacement for it. If you use this option,
- you will have to use the watchdg driver to either stop the timeout
- or restart it. If you do not, then your kernel will reboot after
- startup.
-
- The driver uses a fixed timeout value, so the exact time till the
- system resets depends on the value of PCLK. The timeout on an
- 200MHz s3c2410 should be about 30 seconds.
-
-config S3C2410_BOOT_ERROR_RESET
- bool "S3C2410 Reboot on decompression error"
- depends on ARCH_S3C2410
- help
- Say y here to use the watchdog to reset the system if the
- kernel decompressor detects an error during decompression.
-
-
-comment "S3C2410 Setup"
-
-config S3C2410_DMA
- bool "S3C2410 DMA support"
- depends on ARCH_S3C2410
- help
- S3C2410 DMA support. This is needed for drivers like sound which
- use the S3C2410's DMA system to move data to and from the
- peripheral blocks.
-
-config S3C2410_DMA_DEBUG
- bool "S3C2410 DMA support debug"
- depends on ARCH_S3C2410 && S3C2410_DMA
- help
- Enable debugging output for the DMA code. This option sends info
- to the kernel log, at priority KERN_DEBUG.
-
- Note, it is easy to create and fill the log buffer in a small
- amount of time, as well as using an significant percentage of
- the CPU time doing so.
-
-
-config S3C2410_PM_DEBUG
- bool "S3C2410 PM Suspend debug"
- depends on ARCH_S3C2410 && PM
- help
- Say Y here if you want verbose debugging from the PM Suspend and
- Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
- for more information.
-
-config S3C2410_PM_CHECK
- bool "S3C2410 PM Suspend Memory CRC"
- depends on ARCH_S3C2410 && PM && CRC32
- help
- Enable the PM code's memory area checksum over sleep. This option
- will generate CRCs of all blocks of memory, and store them before
- going to sleep. The blocks are then checked on resume for any
- errors.
-
-config S3C2410_PM_CHECK_CHUNKSIZE
- int "S3C2410 PM Suspend CRC Chunksize (KiB)"
- depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
- default 64
- help
- Set the chunksize in Kilobytes of the CRC for checking memory
- corruption over suspend and resume. A smaller value will mean that
- the CRC data block will take more memory, but wil identify any
- faults with better precision.
-
-config PM_SIMTEC
- bool
- help
- Common power management code for systems that are
- compatible with the Simtec style of power management
-
-config S3C2410_LOWLEVEL_UART_PORT
- int "S3C2410 UART to use for low-level messages"
- default 0
- help
- Choice of which UART port to use for the low-level messages,
- such as the `Uncompressing...` at start time. The value of
- this configuration should be between zero and two. The port
- must have been initialised by the boot-loader before use.
-
- Note, this does not affect the port used by the debug messages,
- which is a separate configuration.
-
-endif
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 27663e28cc8..9a3d3d24c08 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -1,92 +1,31 @@
-
+# arch/arm/mach-s3c2410/Makefile
#
-# Makefile for the linux kernel.
+# Copyright 2007 Simtec Electronics
#
+# Licensed under GPLv2
-# Object file lists.
-
-obj-y := cpu.o irq.o time.o gpio.o clock.o devs.o
-obj-m :=
-obj-n :=
-obj- :=
-obj-dma-y :=
-obj-dma-n :=
-
-# DMA
-obj-$(CONFIG_S3C2410_DMA) += dma.o
-
-# S3C2400 support files
-obj-$(CONFIG_CPU_S3C2400) += s3c2400-gpio.o
-
-# S3C2410 support files
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
obj-$(CONFIG_CPU_S3C2410) += s3c2410.o
-obj-$(CONFIG_CPU_S3C2410) += s3c2410-gpio.o
-obj-$(CONFIG_CPU_S3C2410) += s3c2410-irq.o
-
-obj-$(CONFIG_S3C2410_PM) += s3c2410-pm.o s3c2410-sleep.o
-obj-$(CONFIG_CPU_S3C2410_DMA) += s3c2410-dma.o
-
-# Power Management support
-
-obj-$(CONFIG_PM) += pm.o sleep.o
-obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
-obj-$(CONFIG_PM_H1940) += pm-h1940.o
-
-# S3C2412 support
-obj-$(CONFIG_CPU_S3C2412) += s3c2412.o
-obj-$(CONFIG_CPU_S3C2412) += s3c2412-irq.o
-obj-$(CONFIG_CPU_S3C2412) += s3c2412-clock.o
-obj-dma-$(CONFIG_CPU_S3C2412) += s3c2412-dma.o
-
-obj-$(CONFIG_S3C2412_PM) += s3c2412-pm.o
-
-#
-# S3C244X support
-
-obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
-obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o
-
-# Clock control
-
-obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o
-
-# S3C2440 support
-
-obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
-obj-$(CONFIG_CPU_S3C2440) += s3c2440-irq.o
-obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o
-obj-$(CONFIG_CPU_S3C2440) += s3c2410-gpio.o
-obj-dma-$(CONFIG_CPU_S3C2440) += s3c2440-dma.o
+obj-$(CONFIG_CPU_S3C2410) += irq.o
+obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
+obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
+obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o
+obj-$(CONFIG_S3C2410_GPIO) += gpio.o
+obj-$(CONFIG_S3C2410_CLOCK) += clock.o
-# S3C2442 support
+# Machine support
-obj-$(CONFIG_CPU_S3C2442) += s3c2442.o
-obj-$(CONFIG_CPU_S3C2442) += s3c2442-clock.o
-
-# bast extras
-
-obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o
-
-# merge in dma objects
-
-obj-y += $(obj-dma-y)
-
-# machine specific support
-
-obj-$(CONFIG_MACH_AML_M5900) += mach-amlm5900.o
-obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o
-obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o
-obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
+obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o
obj-$(CONFIG_ARCH_H1940) += mach-h1940.o
+obj-$(CONFIG_PM_H1940) += pm-h1940.o
obj-$(CONFIG_MACH_N30) += mach-n30.o
-obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o
-obj-$(CONFIG_MACH_SMDK2413) += mach-smdk2413.o
-obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
-obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
-obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
+obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
obj-$(CONFIG_MACH_OTOM) += mach-otom.o
-obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
-obj-$(CONFIG_MACH_VSTMS) += mach-vstms.o
-
-obj-$(CONFIG_MACH_SMDK) += common-smdk.o \ No newline at end of file
+obj-$(CONFIG_MACH_AML_M5900) += mach-amlm5900.o
+obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o
+obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
+obj-$(CONFIG_MACH_QT2410) += mach-qt2410.o
diff --git a/arch/arm/mach-s3c2410/bast-irq.c b/arch/arm/mach-s3c2410/bast-irq.c
index 379efe70778..daeba427d78 100644
--- a/arch/arm/mach-s3c2410/bast-irq.c
+++ b/arch/arm/mach-s3c2410/bast-irq.c
@@ -39,7 +39,7 @@
#include <asm/arch/bast-map.h>
#include <asm/arch/bast-irq.h>
-#include "irq.h"
+#include <asm/plat-s3c24xx/irq.h>
#if 0
#include <asm/debug-ll.h>
diff --git a/arch/arm/mach-s3c2410/bast.h b/arch/arm/mach-s3c2410/bast.h
index e5d03311752..e98543742eb 100644
--- a/arch/arm/mach-s3c2410/bast.h
+++ b/arch/arm/mach-s3c2410/bast.h
@@ -1,2 +1,2 @@
-
+/* linux/arch/arm/mach-s3c2410/bast.h
extern void bast_init_irq(void);
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index e13fb677889..5b4831c4c1d 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -1,15 +1,9 @@
/* linux/arch/arm/mach-s3c2410/clock.c
*
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
- * S3C24XX Core clock control support
- *
- * Based on, and code from linux/arch/arm/mach-versatile/clock.c
- **
- ** Copyright (C) 2004 ARM Limited.
- ** Written by Deep Blue Solutions Limited.
- *
+ * S3C2410,S3C2440,S3C2442 Clock control support
*
* 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
@@ -32,418 +26,251 @@
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
-#include <linux/platform_device.h>
#include <linux/sysdev.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/map.h>
#include <asm/hardware.h>
-#include <asm/irq.h>
#include <asm/io.h>
+#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-gpio.h>
-#include "clock.h"
-#include "cpu.h"
-
-/* clock information */
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
-static LIST_HEAD(clocks);
-
-DEFINE_MUTEX(clocks_mutex);
-
-/* enable and disable calls for use with the clk struct */
-
-static int clk_null_enable(struct clk *clk, int enable)
+int s3c2410_clkcon_enable(struct clk *clk, int enable)
{
- return 0;
-}
-
-/* Clock API calls */
+ unsigned int clocks = clk->ctrlbit;
+ unsigned long clkcon;
-struct clk *clk_get(struct device *dev, const char *id)
-{
- struct clk *p;
- struct clk *clk = ERR_PTR(-ENOENT);
- int idno;
+ clkcon = __raw_readl(S3C2410_CLKCON);
- if (dev == NULL || dev->bus != &platform_bus_type)
- idno = -1;
+ if (enable)
+ clkcon |= clocks;
else
- idno = to_platform_device(dev)->id;
-
- mutex_lock(&clocks_mutex);
-
- list_for_each_entry(p, &clocks, list) {
- if (p->id == idno &&
- strcmp(id, p->name) == 0 &&
- try_module_get(p->owner)) {
- clk = p;
- break;
- }
- }
-
- /* check for the case where a device was supplied, but the
- * clock that was being searched for is not device specific */
-
- if (IS_ERR(clk)) {
- list_for_each_entry(p, &clocks, list) {
- if (p->id == -1 && strcmp(id, p->name) == 0 &&
- try_module_get(p->owner)) {
- clk = p;
- break;
- }
- }
- }
+ clkcon &= ~clocks;
- mutex_unlock(&clocks_mutex);
- return clk;
-}
+ /* ensure none of the special function bits set */
+ clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
-void clk_put(struct clk *clk)
-{
- module_put(clk->owner);
-}
+ __raw_writel(clkcon, S3C2410_CLKCON);
-int clk_enable(struct clk *clk)
-{
- if (IS_ERR(clk) || clk == NULL)
- return -EINVAL;
-
- clk_enable(clk->parent);
-
- mutex_lock(&clocks_mutex);
-
- if ((clk->usage++) == 0)
- (clk->enable)(clk, 1);
-
- mutex_unlock(&clocks_mutex);
return 0;
}
-void clk_disable(struct clk *clk)
-{
- if (IS_ERR(clk) || clk == NULL)
- return;
-
- mutex_lock(&clocks_mutex);
-
- if ((--clk->usage) == 0)
- (clk->enable)(clk, 0);
-
- mutex_unlock(&clocks_mutex);
- clk_disable(clk->parent);
-}
-
-
-unsigned long clk_get_rate(struct clk *clk)
-{
- if (IS_ERR(clk))
- return 0;
-
- if (clk->rate != 0)
- return clk->rate;
-
- if (clk->get_rate != NULL)
- return (clk->get_rate)(clk);
-
- if (clk->parent != NULL)
- return clk_get_rate(clk->parent);
-
- return clk->rate;
-}
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
- if (!IS_ERR(clk) && clk->round_rate)
- return (clk->round_rate)(clk, rate);
-
- return rate;
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
- int ret;
-
- if (IS_ERR(clk))
- return -EINVAL;
-
- mutex_lock(&clocks_mutex);
- ret = (clk->set_rate)(clk, rate);
- mutex_unlock(&clocks_mutex);
-
- return ret;
-}
-
-struct clk *clk_get_parent(struct clk *clk)
+static int s3c2410_upll_enable(struct clk *clk, int enable)
{
- return clk->parent;
-}
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
- int ret = 0;
-
- if (IS_ERR(clk))
- return -EINVAL;
-
- mutex_lock(&clocks_mutex);
-
- if (clk->set_parent)
- ret = (clk->set_parent)(clk, parent);
-
- mutex_unlock(&clocks_mutex);
-
- return ret;
-}
-
-EXPORT_SYMBOL(clk_get);
-EXPORT_SYMBOL(clk_put);
-EXPORT_SYMBOL(clk_enable);
-EXPORT_SYMBOL(clk_disable);
-EXPORT_SYMBOL(clk_get_rate);
-EXPORT_SYMBOL(clk_round_rate);
-EXPORT_SYMBOL(clk_set_rate);
-EXPORT_SYMBOL(clk_get_parent);
-EXPORT_SYMBOL(clk_set_parent);
-
-/* base clocks */
-
-struct clk clk_xtal = {
- .name = "xtal",
- .id = -1,
- .rate = 0,
- .parent = NULL,
- .ctrlbit = 0,
-};
-
-struct clk clk_mpll = {
- .name = "mpll",
- .id = -1,
-};
-
-struct clk clk_upll = {
- .name = "upll",
- .id = -1,
- .parent = NULL,
- .ctrlbit = 0,
-};
-
-struct clk clk_f = {
- .name = "fclk",
- .id = -1,
- .rate = 0,
- .parent = &clk_mpll,
- .ctrlbit = 0,
-};
-
-struct clk clk_h = {
- .name = "hclk",
- .id = -1,
- .rate = 0,
- .parent = NULL,
- .ctrlbit = 0,
-};
-
-struct clk clk_p = {
- .name = "pclk",
- .id = -1,
- .rate = 0,
- .parent = NULL,
- .ctrlbit = 0,
-};
-
-struct clk clk_usb_bus = {
- .name = "usb-bus",
- .id = -1,
- .rate = 0,
- .parent = &clk_upll,
-};
-
-/* clocks that could be registered by external code */
-
-static int s3c24xx_dclk_enable(struct clk *clk, int enable)
-{
- unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
+ unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+ unsigned long orig = clkslow;
if (enable)
- dclkcon |= clk->ctrlbit;
+ clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
else
- dclkcon &= ~clk->ctrlbit;
+ clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
- __raw_writel(dclkcon, S3C24XX_DCLKCON);
+ __raw_writel(clkslow, S3C2410_CLKSLOW);
- return 0;
-}
+ /* if we started the UPLL, then allow to settle */
-static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
-{
- unsigned long dclkcon;
- unsigned int uclk;
-
- if (parent == &clk_upll)
- uclk = 1;
- else if (parent == &clk_p)
- uclk = 0;
- else
- return -EINVAL;
-
- clk->parent = parent;
-
- dclkcon = __raw_readl(S3C24XX_DCLKCON);
-
- if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
- if (uclk)
- dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
- else
- dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
- } else {
- if (uclk)
- dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
- else
- dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
- }
-
- __raw_writel(dclkcon, S3C24XX_DCLKCON);
+ if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
+ udelay(200);
return 0;
}
-
-static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
-{
- unsigned long mask;
- unsigned long source;
-
- /* calculate the MISCCR setting for the clock */
-
- if (parent == &clk_xtal)
- source = S3C2410_MISCCR_CLK0_MPLL;
- else if (parent == &clk_upll)
- source = S3C2410_MISCCR_CLK0_UPLL;
- else if (parent == &clk_f)
- source = S3C2410_MISCCR_CLK0_FCLK;
- else if (parent == &clk_h)
- source = S3C2410_MISCCR_CLK0_HCLK;
- else if (parent == &clk_p)
- source = S3C2410_MISCCR_CLK0_PCLK;
- else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
- source = S3C2410_MISCCR_CLK0_DCLK0;
- else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1)
- source = S3C2410_MISCCR_CLK0_DCLK0;
- else
- return -EINVAL;
-
- clk->parent = parent;
-
- if (clk == &s3c24xx_dclk0)
- mask = S3C2410_MISCCR_CLK0_MASK;
- else {
- source <<= 4;
- mask = S3C2410_MISCCR_CLK1_MASK;
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+ {
+ .name = "nand",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_NAND,
+ }, {
+ .name = "sdi",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_SDI,
+ }, {
+ .name = "adc",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_ADC,
+ }, {
+ .name = "i2c",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_IIC,
+ }, {
+ .name = "iis",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_IIS,
+ }, {
+ .name = "spi",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_SPI,
}
-
- s3c2410_modify_misccr(mask, source);
- return 0;
-}
-
-/* external clock definitions */
-
-struct clk s3c24xx_dclk0 = {
- .name = "dclk0",
- .id = -1,
- .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
- .enable = s3c24xx_dclk_enable,
- .set_parent = s3c24xx_dclk_setparent,
-};
-
-struct clk s3c24xx_dclk1 = {
- .name = "dclk1",
- .id = -1,
- .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
- .enable = s3c24xx_dclk_enable,
- .set_parent = s3c24xx_dclk_setparent,
};
-struct clk s3c24xx_clkout0 = {
- .name = "clkout0",
- .id = -1,
- .set_parent = s3c24xx_clkout_setparent,
+static struct clk init_clocks[] = {
+ {
+ .name = "lcd",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_LCDC,
+ }, {
+ .name = "gpio",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_GPIO,
+ }, {
+ .name = "usb-host",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_USBH,
+ }, {
+ .name = "usb-device",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_USBD,
+ }, {
+ .name = "timers",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_PWMT,
+ }, {
+ .name = "uart",
+ .id = 0,
+ .parent = &clk_p,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_UART0,
+ }, {
+ .name = "uart",
+ .id = 1,
+ .parent = &clk_p,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_UART1,
+ }, {
+ .name = "uart",
+ .id = 2,
+ .parent = &clk_p,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_UART2,
+ }, {
+ .name = "rtc",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2410_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_RTC,
+ }, {
+ .name = "watchdog",
+ .id = -1,
+ .parent = &clk_p,
+ .ctrlbit = 0,
+ }, {
+ .name = "usb-bus-host",
+ .id = -1,
+ .parent = &clk_usb_bus,
+ }, {
+ .name = "usb-bus-gadget",
+ .id = -1,
+ .parent = &clk_usb_bus,
+ },
};
-struct clk s3c24xx_clkout1 = {
- .name = "clkout1",
- .id = -1,
- .set_parent = s3c24xx_clkout_setparent,
-};
-
-struct clk s3c24xx_uclk = {
- .name = "uclk",
- .id = -1,
-};
-
-/* initialise the clock system */
-
-int s3c24xx_register_clock(struct clk *clk)
-{
- clk->owner = THIS_MODULE;
-
- if (clk->enable == NULL)
- clk->enable = clk_null_enable;
-
- /* add to the list of available clocks */
-
- mutex_lock(&clocks_mutex);
- list_add(&clk->list, &clocks);
- mutex_unlock(&clocks_mutex);
-
- return 0;
-}
-
-/* initalise all the clocks */
+/* s3c2410_baseclk_add()
+ *
+ * Add all the clocks used by the s3c2410 or compatible CPUs
+ * such as the S3C2440 and S3C2442.
+ *
+ * We cannot use a system device as we are needed before any
+ * of the init-calls that initialise the devices are actually
+ * done.
+*/
-int __init s3c24xx_setup_clocks(unsigned long xtal,
- unsigned long fclk,
- unsigned long hclk,
- unsigned long pclk)
+int __init s3c2410_baseclk_add(void)
{
- printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
+ unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+ unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
+ struct clk *clkp;
+ struct clk *xtal;
+ int ret;
+ int ptr;
- /* initialise the main system clocks */
+ clk_upll.enable = s3c2410_upll_enable;
- clk_xtal.rate = xtal;
- clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
+ if (s3c24xx_register_clock(&clk_usb_bus) < 0)
+ printk(KERN_ERR "failed to register usb bus clock\n");
- clk_mpll.rate = fclk;
- clk_h.rate = hclk;
- clk_p.rate = pclk;
- clk_f.rate = fclk;
+ /* register clocks from clock array */
- /* assume uart clocks are correctly setup */
+ clkp = init_clocks;
+ for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+ /* ensure that we note the clock state */
- /* register our clocks */
+ clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
- if (s3c24xx_register_clock(&clk_xtal) < 0)
- printk(KERN_ERR "failed to register master xtal\n");
+ ret = s3c24xx_register_clock(clkp);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register clock %s (%d)\n",
+ clkp->name, ret);
+ }
+ }
- if (s3c24xx_register_clock(&clk_mpll) < 0)
- printk(KERN_ERR "failed to register mpll clock\n");
+ /* We must be careful disabling the clocks we are not intending to
+ * be using at boot time, as subsytems such as the LCD which do
+ * their own DMA requests to the bus can cause the system to lockup
+ * if they where in the middle of requesting bus access.
+ *
+ * Disabling the LCD clock if the LCD is active is very dangerous,
+ * and therefore the bootloader should be careful to not enable
+ * the LCD clock if it is not needed.
+ */
+
+ /* install (and disable) the clocks we do not need immediately */
+
+ clkp = init_clocks_disable;
+ for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+ ret = s3c24xx_register_clock(clkp);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register clock %s (%d)\n",
+ clkp->name, ret);
+ }
- if (s3c24xx_register_clock(&clk_upll) < 0)
- printk(KERN_ERR "failed to register upll clock\n");
+ s3c2410_clkcon_enable(clkp, 0);
+ }
- if (s3c24xx_register_clock(&clk_f) < 0)
- printk(KERN_ERR "failed to register cpu fclk\n");
+ /* show the clock-slow value */
- if (s3c24xx_register_clock(&clk_h) < 0)
- printk(KERN_ERR "failed to register cpu hclk\n");
+ xtal = clk_get(NULL, "xtal");
- if (s3c24xx_register_clock(&clk_p) < 0)
- printk(KERN_ERR "failed to register cpu pclk\n");
+ printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
+ print_mhz(clk_get_rate(xtal) /
+ ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
+ (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
+ (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
+ (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
return 0;
}
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index fa860e716b4..67d1ad36397 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -1,9 +1,9 @@
/* linux/arch/arm/mach-s3c2410/dma.c
*
- * Copyright (c) 2003-2005,2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
- * S3C2410 DMA core
+ * S3C2410 DMA selection
*
* http://armlinux.simtec.co.uk/
*
@@ -12,1430 +12,170 @@
* published by the Free Software Foundation.
*/
-
-#ifdef CONFIG_S3C2410_DMA_DEBUG
-#define DEBUG
-#endif
-
-#include <linux/module.h>
+#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
#include <linux/sysdev.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
+#include <linux/serial_core.h>
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
#include <asm/dma.h>
-
-#include <asm/mach/dma.h>
-#include <asm/arch/map.h>
-
-#include "dma.h"
-
-/* io map for dma */
-static void __iomem *dma_base;
-static struct kmem_cache *dma_kmem;
-
-struct s3c24xx_dma_selection dma_sel;
-
-/* dma channel state information */
-struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
-
-/* debugging functions */
-
-#define BUF_MAGIC (0xcafebabe)
-
-#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
-
-#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
-
-#if 1
-#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
-#else
-static inline void
-dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
-{
- pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
- writel(val, dma_regaddr(chan, reg));
-}
-#endif
-
-#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
-
-/* captured register state for debug */
-
-struct s3c2410_dma_regstate {
- unsigned long dcsrc;
- unsigned long disrc;
- unsigned long dstat;
- unsigned long dcon;
- unsigned long dmsktrig;
+#include <asm/arch/dma.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/dma.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
+ [DMACH_XD0] = {
+ .name = "xdreq0",
+ .channels[0] = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
+ },
+ [DMACH_XD1] = {
+ .name = "xdreq1",
+ .channels[1] = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
+ },
+ [DMACH_SDI] = {
+ .name = "sdi",
+ .channels[0] = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
+ .channels[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
+ .channels[3] = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
+ .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
+ .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
+ },
+ [DMACH_SPI0] = {
+ .name = "spi0",
+ .channels[1] = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
+ .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT,
+ .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT,
+ },
+ [DMACH_SPI1] = {
+ .name = "spi1",
+ .channels[3] = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
+ .hw_addr.to = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+ .hw_addr.from = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+ },
+ [DMACH_UART0] = {
+ .name = "uart0",
+ .channels[0] = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
+ .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
+ .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
+ },
+ [DMACH_UART1] = {
+ .name = "uart1",
+ .channels[1] = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
+ .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
+ .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
+ },
+ [DMACH_UART2] = {
+ .name = "uart2",
+ .channels[3] = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
+ .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
+ .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
+ },
+ [DMACH_TIMER] = {
+ .name = "timer",
+ .channels[0] = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
+ .channels[2] = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
+ .channels[3] = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
+ },
+ [DMACH_I2S_IN] = {
+ .name = "i2s-sdi",
+ .channels[1] = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
+ .channels[2] = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
+ .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
+ },
+ [DMACH_I2S_OUT] = {
+ .name = "i2s-sdo",
+ .channels[2] = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
+ .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
+ },
+ [DMACH_USB_EP1] = {
+ .name = "usb-ep1",
+ .channels[0] = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
+ },
+ [DMACH_USB_EP2] = {
+ .name = "usb-ep2",
+ .channels[1] = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
+ },
+ [DMACH_USB_EP3] = {
+ .name = "usb-ep3",
+ .channels[2] = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
+ },
+ [DMACH_USB_EP4] = {
+ .name = "usb-ep4",
+ .channels[3] =S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
+ },
};
-#ifdef CONFIG_S3C2410_DMA_DEBUG
-
-/* dmadbg_showregs
- *
- * simple debug routine to print the current state of the dma registers
-*/
-
-static void
-dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
-{
- regs->dcsrc = dma_rdreg(chan, S3C2410_DMA_DCSRC);
- regs->disrc = dma_rdreg(chan, S3C2410_DMA_DISRC);
- regs->dstat = dma_rdreg(chan, S3C2410_DMA_DSTAT);
- regs->dcon = dma_rdreg(chan, S3C2410_DMA_DCON);
- regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-}
-
-static void
-dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
- struct s3c2410_dma_regstate *regs)
-{
- printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
- chan->number, fname, line,
- regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
- regs->dcon);
-}
-
-static void
-dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
-{
- struct s3c2410_dma_regstate state;
-
- dmadbg_capture(chan, &state);
-
- printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
- chan->number, fname, line, chan->load_state,
- chan->curr, chan->next, chan->end);
-
- dmadbg_dumpregs(fname, line, chan, &state);
-}
-
-static void
-dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
-{
- struct s3c2410_dma_regstate state;
-
- dmadbg_capture(chan, &state);
- dmadbg_dumpregs(fname, line, chan, &state);
-}
-
-#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
-#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
-#else
-#define dbg_showregs(chan) do { } while(0)
-#define dbg_showchan(chan) do { } while(0)
-#endif /* CONFIG_S3C2410_DMA_DEBUG */
-
-static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
-
-/* lookup_dma_channel
- *
- * change the dma channel number given into a real dma channel id
-*/
-
-static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
-{
- if (channel & DMACH_LOW_LEVEL)
- return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
- else
- return dma_chan_map[channel];
-}
-
-/* s3c2410_dma_stats_timeout
- *
- * Update DMA stats from timeout info
-*/
-
-static void
-s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
+static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
+ struct s3c24xx_dma_map *map)
{
- if (stats == NULL)
- return;
-
- if (val > stats->timeout_longest)
- stats->timeout_longest = val;
- if (val < stats->timeout_shortest)
- stats->timeout_shortest = val;
-
- stats->timeout_avg += val;
+ chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
}
-/* s3c2410_dma_waitforload
- *
- * wait for the DMA engine to load a buffer, and update the state accordingly
-*/
-
-static int
-s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
-{
- int timeout = chan->load_timeout;
- int took;
-
- if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
- printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
- return 0;
- }
-
- if (chan->stats != NULL)
- chan->stats->loads++;
-
- while (--timeout > 0) {
- if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
- took = chan->load_timeout - timeout;
-
- s3c2410_dma_stats_timeout(chan->stats, took);
-
- switch (chan->load_state) {
- case S3C2410_DMALOAD_1LOADED:
- chan->load_state = S3C2410_DMALOAD_1RUNNING;
- break;
-
- default:
- printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
- }
-
- return 1;
- }
- }
-
- if (chan->stats != NULL) {
- chan->stats->timeout_failed++;
- }
-
- return 0;
-}
-
-
-
-/* s3c2410_dma_loadbuffer
- *
- * load a buffer, and update the channel state
-*/
-
-static inline int
-s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
- struct s3c2410_dma_buf *buf)
-{
- unsigned long reload;
-
- pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
- buf, (unsigned long)buf->data, buf->size);
-
- if (buf == NULL) {
- dmawarn("buffer is NULL\n");
- return -EINVAL;
- }
-
- /* check the state of the channel before we do anything */
-
- if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
- dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
- }
-
- if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
- dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
- }
-
- /* it would seem sensible if we are the last buffer to not bother
- * with the auto-reload bit, so that the DMA engine will not try
- * and load another transfer after this one has finished...
- */
- if (chan->load_state == S3C2410_DMALOAD_NONE) {
- pr_debug("load_state is none, checking for noreload (next=%p)\n",
- buf->next);
- reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
- } else {
- //pr_debug("load_state is %d => autoreload\n", chan->load_state);
- reload = S3C2410_DCON_AUTORELOAD;
- }
-
- if ((buf->data & 0xf0000000) != 0x30000000) {
- dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
- }
-
- writel(buf->data, chan->addr_reg);
-
- dma_wrreg(chan, S3C2410_DMA_DCON,
- chan->dcon | reload | (buf->size/chan->xfer_unit));
-
- chan->next = buf->next;
-
- /* update the state of the channel */
-
- switch (chan->load_state) {
- case S3C2410_DMALOAD_NONE:
- chan->load_state = S3C2410_DMALOAD_1LOADED;
- break;
-
- case S3C2410_DMALOAD_1RUNNING:
- chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
- break;
-
- default:
- dmawarn("dmaload: unknown state %d in loadbuffer\n",
- chan->load_state);
- break;
- }
-
- return 0;
-}
-
-/* s3c2410_dma_call_op
- *
- * small routine to call the op routine with the given op if it has been
- * registered
-*/
-
-static void
-s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
-{
- if (chan->op_fn != NULL) {
- (chan->op_fn)(chan, op);
- }
-}
-
-/* s3c2410_dma_buffdone
- *
- * small wrapper to check if callback routine needs to be called, and
- * if so, call it
-*/
-
-static inline void
-s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
- enum s3c2410_dma_buffresult result)
-{
-#if 0
- pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
- chan->callback_fn, buf, buf->id, buf->size, result);
-#endif
-
- if (chan->callback_fn != NULL) {
- (chan->callback_fn)(chan, buf->id, buf->size, result);
- }
-}
-
-/* s3c2410_dma_start
- *
- * start a dma channel going
-*/
-
-static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
-{
- unsigned long tmp;
- unsigned long flags;
-
- pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
-
- local_irq_save(flags);
-
- if (chan->state == S3C2410_DMA_RUNNING) {
- pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
- local_irq_restore(flags);
- return 0;
- }
-
- chan->state = S3C2410_DMA_RUNNING;
-
- /* check wether there is anything to load, and if not, see
- * if we can find anything to load
- */
-
- if (chan->load_state == S3C2410_DMALOAD_NONE) {
- if (chan->next == NULL) {
- printk(KERN_ERR "dma%d: channel has nothing loaded\n",
- chan->number);
- chan->state = S3C2410_DMA_IDLE;
- local_irq_restore(flags);
- return -EINVAL;
- }
-
- s3c2410_dma_loadbuffer(chan, chan->next);
- }
-
- dbg_showchan(chan);
-
- /* enable the channel */
-
- if (!chan->irq_enabled) {
- enable_irq(chan->irq);
- chan->irq_enabled = 1;
- }
-
- /* start the channel going */
-
- tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
- tmp &= ~S3C2410_DMASKTRIG_STOP;
- tmp |= S3C2410_DMASKTRIG_ON;
- dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
-
- pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
-
-#if 0
- /* the dma buffer loads should take care of clearing the AUTO
- * reloading feature */
- tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
- tmp &= ~S3C2410_DCON_NORELOAD;
- dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
-#endif
-
- s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
-
- dbg_showchan(chan);
-
- /* if we've only loaded one buffer onto the channel, then chec
- * to see if we have another, and if so, try and load it so when
- * the first buffer is finished, the new one will be loaded onto
- * the channel */
-
- if (chan->next != NULL) {
- if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
-
- if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
- pr_debug("%s: buff not yet loaded, no more todo\n",
- __FUNCTION__);
- } else {
- chan->load_state = S3C2410_DMALOAD_1RUNNING;
- s3c2410_dma_loadbuffer(chan, chan->next);
- }
-
- } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
- s3c2410_dma_loadbuffer(chan, chan->next);
- }
- }
-
-
- local_irq_restore(flags);
-
- return 0;
-}
-
-/* s3c2410_dma_canload
- *
- * work out if we can queue another buffer into the DMA engine
-*/
-
-static int
-s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
-{
- if (chan->load_state == S3C2410_DMALOAD_NONE ||
- chan->load_state == S3C2410_DMALOAD_1RUNNING)
- return 1;
-
- return 0;
-}
-
-/* s3c2410_dma_enqueue
- *
- * queue an given buffer for dma transfer.
- *
- * id the device driver's id information for this buffer
- * data the physical address of the buffer data
- * size the size of the buffer in bytes
- *
- * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
- * is checked, and if set, the channel is started. If this flag isn't set,
- * then an error will be returned.
- *
- * It is possible to queue more than one DMA buffer onto a channel at
- * once, and the code will deal with the re-loading of the next buffer
- * when necessary.
-*/
-
-int s3c2410_dma_enqueue(unsigned int channel, void *id,
- dma_addr_t data, int size)
-{
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
- struct s3c2410_dma_buf *buf;
- unsigned long flags;
-
- if (chan == NULL)
- return -EINVAL;
-
- pr_debug("%s: id=%p, data=%08x, size=%d\n",
- __FUNCTION__, id, (unsigned int)data, size);
-
- buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
- if (buf == NULL) {
- pr_debug("%s: out of memory (%ld alloc)\n",
- __FUNCTION__, (long)sizeof(*buf));
- return -ENOMEM;
- }
-
- //pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
- //dbg_showchan(chan);
-
- buf->next = NULL;
- buf->data = buf->ptr = data;
- buf->size = size;
- buf->id = id;
- buf->magic = BUF_MAGIC;
-
- local_irq_save(flags);
-
- if (chan->curr == NULL) {
- /* we've got nothing loaded... */
- pr_debug("%s: buffer %p queued onto empty channel\n",
- __FUNCTION__, buf);
-
- chan->curr = buf;
- chan->end = buf;
- chan->next = NULL;
- } else {
- pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
- chan->number, __FUNCTION__, buf);
-
- if (chan->end == NULL)
- pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
- chan->number, __FUNCTION__, chan);
-
- chan->end->next = buf;
- chan->end = buf;
- }
-
- /* if necessary, update the next buffer field */
- if (chan->next == NULL)
- chan->next = buf;
-
- /* check to see if we can load a buffer */
- if (chan->state == S3C2410_DMA_RUNNING) {
- if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
- if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
- printk(KERN_ERR "dma%d: loadbuffer:"
- "timeout loading buffer\n",
- chan->number);
- dbg_showchan(chan);
- local_irq_restore(flags);
- return -EINVAL;
- }
- }
-
- while (s3c2410_dma_canload(chan) && chan->next != NULL) {
- s3c2410_dma_loadbuffer(chan, chan->next);
- }
- } else if (chan->state == S3C2410_DMA_IDLE) {
- if (chan->flags & S3C2410_DMAF_AUTOSTART) {
- s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
- }
- }
-
- local_irq_restore(flags);
- return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-static inline void
-s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
-{
- int magicok = (buf->magic == BUF_MAGIC);
-
- buf->magic = -1;
-
- if (magicok) {
- kmem_cache_free(dma_kmem, buf);
- } else {
- printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
- }
-}
-
-/* s3c2410_dma_lastxfer
- *
- * called when the system is out of buffers, to ensure that the channel
- * is prepared for shutdown.
-*/
-
-static inline void
-s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
-{
-#if 0
- pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
- chan->number, chan->load_state);
-#endif
-
- switch (chan->load_state) {
- case S3C2410_DMALOAD_NONE:
- break;
-
- case S3C2410_DMALOAD_1LOADED:
- if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
- /* flag error? */
- printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
- chan->number, __FUNCTION__);
- return;
- }
- break;
-
- case S3C2410_DMALOAD_1LOADED_1RUNNING:
- /* I belive in this case we do not have anything to do
- * until the next buffer comes along, and we turn off the
- * reload */
- return;
-
- default:
- pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
- chan->number, chan->load_state);
- return;
-
- }
-
- /* hopefully this'll shut the damned thing up after the transfer... */
- dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
-}
-
-
-#define dmadbg2(x...)
-
-static irqreturn_t
-s3c2410_dma_irq(int irq, void *devpw)
-{
- struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
- struct s3c2410_dma_buf *buf;
-
- buf = chan->curr;
-
- dbg_showchan(chan);
-
- /* modify the channel state */
-
- switch (chan->load_state) {
- case S3C2410_DMALOAD_1RUNNING:
- /* TODO - if we are running only one buffer, we probably
- * want to reload here, and then worry about the buffer
- * callback */
-
- chan->load_state = S3C2410_DMALOAD_NONE;
- break;
-
- case S3C2410_DMALOAD_1LOADED:
- /* iirc, we should go back to NONE loaded here, we
- * had a buffer, and it was never verified as being
- * loaded.
- */
-
- chan->load_state = S3C2410_DMALOAD_NONE;
- break;
-
- case S3C2410_DMALOAD_1LOADED_1RUNNING:
- /* we'll worry about checking to see if another buffer is
- * ready after we've called back the owner. This should
- * ensure we do not wait around too long for the DMA
- * engine to start the next transfer
- */
-
- chan->load_state = S3C2410_DMALOAD_1LOADED;
- break;
-
- case S3C2410_DMALOAD_NONE:
- printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
- chan->number);
- break;
-
- default:
- printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
- chan->number, chan->load_state);
- break;
- }
-
- if (buf != NULL) {
- /* update the chain to make sure that if we load any more
- * buffers when we call the callback function, things should
- * work properly */
-
- chan->curr = buf->next;
- buf->next = NULL;
-
- if (buf->magic != BUF_MAGIC) {
- printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
- chan->number, __FUNCTION__, buf);
- return IRQ_HANDLED;
- }
-
- s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
-
- /* free resouces */
- s3c2410_dma_freebuf(buf);
- } else {
- }
-
- /* only reload if the channel is still running... our buffer done
- * routine may have altered the state by requesting the dma channel
- * to stop or shutdown... */
-
- /* todo: check that when the channel is shut-down from inside this
- * function, we cope with unsetting reload, etc */
-
- if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
- unsigned long flags;
-
- switch (chan->load_state) {
- case S3C2410_DMALOAD_1RUNNING:
- /* don't need to do anything for this state */
- break;
-
- case S3C2410_DMALOAD_NONE:
- /* can load buffer immediately */
- break;
-
- case S3C2410_DMALOAD_1LOADED:
- if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
- /* flag error? */
- printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
- chan->number, __FUNCTION__);
- return IRQ_HANDLED;
- }
-
- break;
-
- case S3C2410_DMALOAD_1LOADED_1RUNNING:
- goto no_load;
-
- default:
- printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
- chan->number, chan->load_state);
- return IRQ_HANDLED;
- }
-
- local_irq_save(flags);
- s3c2410_dma_loadbuffer(chan, chan->next);
- local_irq_restore(flags);
- } else {
- s3c2410_dma_lastxfer(chan);
-
- /* see if we can stop this channel.. */
- if (chan->load_state == S3C2410_DMALOAD_NONE) {
- pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
- chan->number, jiffies);
- s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
- S3C2410_DMAOP_STOP);
- }
- }
-
- no_load:
- return IRQ_HANDLED;
-}
-
-static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
-
-/* s3c2410_request_dma
- *
- * get control of an dma channel
-*/
-
-int s3c2410_dma_request(unsigned int channel,
- struct s3c2410_dma_client *client,
- void *dev)
-{
- struct s3c2410_dma_chan *chan;
- unsigned long flags;
- int err;
-
- pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
- channel, client->name, dev);
-
- local_irq_save(flags);
-
- chan = s3c2410_dma_map_channel(channel);
- if (chan == NULL) {
- local_irq_restore(flags);
- return -EBUSY;
- }
-
- dbg_showchan(chan);
-
- chan->client = client;
- chan->in_use = 1;
-
- if (!chan->irq_claimed) {
- pr_debug("dma%d: %s : requesting irq %d\n",
- channel, __FUNCTION__, chan->irq);
-
- chan->irq_claimed = 1;
- local_irq_restore(flags);
-
- err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
- client->name, (void *)chan);
-
- local_irq_save(flags);
-
- if (err) {
- chan->in_use = 0;
- chan->irq_claimed = 0;
- local_irq_restore(flags);
-
- printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
- client->name, chan->irq, chan->number);
- return err;
- }
-
- chan->irq_enabled = 1;
- }
-
- local_irq_restore(flags);
-
- /* need to setup */
-
- pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
-
- return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_request);
+static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
+ .select = s3c2410_dma_select,
+ .dcon_mask = 7 << 24,
+ .map = s3c2410_dma_mappings,
+ .map_size = ARRAY_SIZE(s3c2410_dma_mappings),
+};
-/* s3c2410_dma_free
- *
- * release the given channel back to the system, will stop and flush
- * any outstanding transfers, and ensure the channel is ready for the
- * next claimant.
- *
- * Note, although a warning is currently printed if the freeing client
- * info is not the same as the registrant's client info, the free is still
- * allowed to go through.
-*/
+static struct s3c24xx_dma_order __initdata s3c2410_dma_order = {
+ .channels = {
+ [DMACH_SDI] = {
+ .list = {
+ [0] = 3 | DMA_CH_VALID,
+ [1] = 2 | DMA_CH_VALID,
+ [2] = 0 | DMA_CH_VALID,
+ },
+ },
+ [DMACH_I2S_IN] = {
+ .list = {
+ [0] = 1 | DMA_CH_VALID,
+ [1] = 2 | DMA_CH_VALID,
+ },
+ },
+ },
+};
-int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
+static int s3c2410_dma_add(struct sys_device *sysdev)
{
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
- unsigned long flags;
-
- if (chan == NULL)
- return -EINVAL;
-
- local_irq_save(flags);
-
- if (chan->client != client) {
- printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
- channel, chan->client, client);
- }
-
- /* sort out stopping and freeing the channel */
-
- if (chan->state != S3C2410_DMA_IDLE) {
- pr_debug("%s: need to stop dma channel %p\n",
- __FUNCTION__, chan);
-
- /* possibly flush the channel */
- s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
- }
-
- chan->client = NULL;
- chan->in_use = 0;
-
- if (chan->irq_claimed)
- free_irq(chan->irq, (void *)chan);
-
- chan->irq_claimed = 0;
-
- if (!(channel & DMACH_LOW_LEVEL))
- dma_chan_map[channel] = NULL;
-
- local_irq_restore(flags);
-
- return 0;
+ s3c2410_dma_init();
+ s3c24xx_dma_order_set(&s3c2410_dma_order);
+ return s3c24xx_dma_init_map(&s3c2410_dma_sel);
}
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
-{
- unsigned long flags;
- unsigned long tmp;
-
- pr_debug("%s:\n", __FUNCTION__);
-
- dbg_showchan(chan);
-
- local_irq_save(flags);
-
- s3c2410_dma_call_op(chan, S3C2410_DMAOP_STOP);
-
- tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
- tmp |= S3C2410_DMASKTRIG_STOP;
- //tmp &= ~S3C2410_DMASKTRIG_ON;
- dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
-
-#if 0
- /* should also clear interrupts, according to WinCE BSP */
- tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
- tmp |= S3C2410_DCON_NORELOAD;
- dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
-#endif
-
- /* should stop do this, or should we wait for flush? */
- chan->state = S3C2410_DMA_IDLE;
- chan->load_state = S3C2410_DMALOAD_NONE;
-
- local_irq_restore(flags);
-
- return 0;
-}
+#if defined(CONFIG_CPU_S3C2410)
+static struct sysdev_driver s3c2410_dma_driver = {
+ .add = s3c2410_dma_add,
+};
-void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
+static int __init s3c2410_dma_drvinit(void)
{
- unsigned long tmp;
- unsigned int timeout = 0x10000;
-
- while (timeout-- > 0) {
- tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-
- if (!(tmp & S3C2410_DMASKTRIG_ON))
- return;
- }
-
- pr_debug("dma%d: failed to stop?\n", chan->number);
+ return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
}
-
-/* s3c2410_dma_flush
- *
- * stop the channel, and remove all current and pending transfers
-*/
-
-static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
-{
- struct s3c2410_dma_buf *buf, *next;
- unsigned long flags;
-
- pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
-
- dbg_showchan(chan);
-
- local_irq_save(flags);
-
- if (chan->state != S3C2410_DMA_IDLE) {
- pr_debug("%s: stopping channel...\n", __FUNCTION__ );
- s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
- }
-
- buf = chan->curr;
- if (buf == NULL)
- buf = chan->next;
-
- chan->curr = chan->next = chan->end = NULL;
-
- if (buf != NULL) {
- for ( ; buf != NULL; buf = next) {
- next = buf->next;
-
- pr_debug("%s: free buffer %p, next %p\n",
- __FUNCTION__, buf, buf->next);
-
- s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
- s3c2410_dma_freebuf(buf);
- }
- }
-
- dbg_showregs(chan);
-
- s3c2410_dma_waitforstop(chan);
-
-#if 0
- /* should also clear interrupts, according to WinCE BSP */
- {
- unsigned long tmp;
-
- tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
- tmp |= S3C2410_DCON_NORELOAD;
- dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
- }
+arch_initcall(s3c2410_dma_drvinit);
#endif
- dbg_showregs(chan);
-
- local_irq_restore(flags);
-
- return 0;
-}
-
-int
-s3c2410_dma_started(struct s3c2410_dma_chan *chan)
-{
- unsigned long flags;
-
- local_irq_save(flags);
-
- dbg_showchan(chan);
-
- /* if we've only loaded one buffer onto the channel, then chec
- * to see if we have another, and if so, try and load it so when
- * the first buffer is finished, the new one will be loaded onto
- * the channel */
-
- if (chan->next != NULL) {
- if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
-
- if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
- pr_debug("%s: buff not yet loaded, no more todo\n",
- __FUNCTION__);
- } else {
- chan->load_state = S3C2410_DMALOAD_1RUNNING;
- s3c2410_dma_loadbuffer(chan, chan->next);
- }
-
- } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
- s3c2410_dma_loadbuffer(chan, chan->next);
- }
- }
-
-
- local_irq_restore(flags);
-
- return 0;
-
-}
-
-int
-s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
-{
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
- if (chan == NULL)
- return -EINVAL;
-
- switch (op) {
- case S3C2410_DMAOP_START:
- return s3c2410_dma_start(chan);
-
- case S3C2410_DMAOP_STOP:
- return s3c2410_dma_dostop(chan);
-
- case S3C2410_DMAOP_PAUSE:
- case S3C2410_DMAOP_RESUME:
- return -ENOENT;
-
- case S3C2410_DMAOP_FLUSH:
- return s3c2410_dma_flush(chan);
-
- case S3C2410_DMAOP_STARTED:
- return s3c2410_dma_started(chan);
-
- case S3C2410_DMAOP_TIMEOUT:
- return 0;
-
- }
-
- return -ENOENT; /* unknown, don't bother */
-}
-
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-/* DMA configuration for each channel
- *
- * DISRCC -> source of the DMA (AHB,APB)
- * DISRC -> source address of the DMA
- * DIDSTC -> destination of the DMA (AHB,APD)
- * DIDST -> destination address of the DMA
-*/
-
-/* s3c2410_dma_config
- *
- * xfersize: size of unit in bytes (1,2,4)
- * dcon: base value of the DCONx register
-*/
-
-int s3c2410_dma_config(dmach_t channel,
- int xferunit,
- int dcon)
-{
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
- pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
- __FUNCTION__, channel, xferunit, dcon);
-
- if (chan == NULL)
- return -EINVAL;
-
- pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
-
- dcon |= chan->dcon & dma_sel.dcon_mask;
-
- pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
-
- switch (xferunit) {
- case 1:
- dcon |= S3C2410_DCON_BYTE;
- break;
-
- case 2:
- dcon |= S3C2410_DCON_HALFWORD;
- break;
-
- case 4:
- dcon |= S3C2410_DCON_WORD;
- break;
-
- default:
- pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
- return -EINVAL;
- }
-
- dcon |= S3C2410_DCON_HWTRIG;
- dcon |= S3C2410_DCON_INTREQ;
-
- pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
-
- chan->dcon = dcon;
- chan->xfer_unit = xferunit;
-
- return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
-{
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
- if (chan == NULL)
- return -EINVAL;
-
- pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
-
- chan->flags = flags;
-
- return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_setflags);
-
-
-/* do we need to protect the settings of the fields from
- * irq?
-*/
-
-int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
-{
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
- if (chan == NULL)
- return -EINVAL;
-
- pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
-
- chan->op_fn = rtn;
-
- return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_set_opfn);
-
-int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
-{
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
- if (chan == NULL)
- return -EINVAL;
-
- pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
-
- chan->callback_fn = rtn;
-
- return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
-
-/* s3c2410_dma_devconfig
- *
- * configure the dma source/destination hardware type and address
- *
- * source: S3C2410_DMASRC_HW: source is hardware
- * S3C2410_DMASRC_MEM: source is memory
- *
- * hwcfg: the value for xxxSTCn register,
- * bit 0: 0=increment pointer, 1=leave pointer
- * bit 1: 0=soucre is AHB, 1=soucre is APB
- *
- * devaddr: physical address of the source
-*/
-
-int s3c2410_dma_devconfig(int channel,
- enum s3c2410_dmasrc source,
- int hwcfg,
- unsigned long devaddr)
-{
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
- if (chan == NULL)
- return -EINVAL;
-
- pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
- __FUNCTION__, (int)source, hwcfg, devaddr);
-
- chan->source = source;
- chan->dev_addr = devaddr;
-
- switch (source) {
- case S3C2410_DMASRC_HW:
- /* source is hardware */
- pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
- __FUNCTION__, devaddr, hwcfg);
- dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
- dma_wrreg(chan, S3C2410_DMA_DISRC, devaddr);
- dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
-
- chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
- return 0;
-
- case S3C2410_DMASRC_MEM:
- /* source is memory */
- pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
- __FUNCTION__, devaddr, hwcfg);
- dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
- dma_wrreg(chan, S3C2410_DMA_DIDST, devaddr);
- dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
-
- chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
- return 0;
- }
-
- printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
- return -EINVAL;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-/* s3c2410_dma_getposition
- *
- * returns the current transfer points for the dma source and destination
-*/
-
-int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
-{
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
- if (chan == NULL)
- return -EINVAL;
-
- if (src != NULL)
- *src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
-
- if (dst != NULL)
- *dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
-
- return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-
-/* system device class */
-
-#ifdef CONFIG_PM
-
-static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
-{
- struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
-
- printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
-
- if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
- /* the dma channel is still working, which is probably
- * a bad thing to do over suspend/resume. We stop the
- * channel and assume that the client is either going to
- * retry after resume, or that it is broken.
- */
-
- printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
- cp->number);
-
- s3c2410_dma_dostop(cp);
- }
-
- return 0;
-}
-
-static int s3c2410_dma_resume(struct sys_device *dev)
-{
- return 0;
-}
-
-#else
-#define s3c2410_dma_suspend NULL
-#define s3c2410_dma_resume NULL
-#endif /* CONFIG_PM */
-
-struct sysdev_class dma_sysclass = {
- set_kset_name("s3c24xx-dma"),
- .suspend = s3c2410_dma_suspend,
- .resume = s3c2410_dma_resume,
+#if defined(CONFIG_CPU_S3C2442)
+/* S3C2442 DMA contains the same selection table as the S3C2410 */
+static struct sysdev_driver s3c2442_dma_driver = {
+ .add = s3c2410_dma_add,
};
-/* kmem cache implementation */
-
-static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
-{
- memset(p, 0, sizeof(struct s3c2410_dma_buf));
-}
-
-/* initialisation code */
-
-static int __init s3c2410_init_dma(void)
-{
- struct s3c2410_dma_chan *cp;
- int channel;
- int ret;
-
- printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
-
- dma_base = ioremap(S3C24XX_PA_DMA, 0x200);
- if (dma_base == NULL) {
- printk(KERN_ERR "dma failed to remap register block\n");
- return -ENOMEM;
- }
-
- printk("Registering sysclass\n");
-
- ret = sysdev_class_register(&dma_sysclass);
- if (ret != 0) {
- printk(KERN_ERR "dma sysclass registration failed\n");
- goto err;
- }
-
- dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0,
- SLAB_HWCACHE_ALIGN,
- s3c2410_dma_cache_ctor, NULL);
-
- if (dma_kmem == NULL) {
- printk(KERN_ERR "dma failed to make kmem cache\n");
- ret = -ENOMEM;
- goto err;
- }
-
- for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
- cp = &s3c2410_chans[channel];
-
- memset(cp, 0, sizeof(struct s3c2410_dma_chan));
-
- /* dma channel irqs are in order.. */
- cp->number = channel;
- cp->irq = channel + IRQ_DMA0;
- cp->regs = dma_base + (channel*0x40);
-
- /* point current stats somewhere */
- cp->stats = &cp->stats_store;
- cp->stats_store.timeout_shortest = LONG_MAX;
-
- /* basic channel configuration */
-
- cp->load_timeout = 1<<18;
-
- /* register system device */
-
- cp->dev.cls = &dma_sysclass;
- cp->dev.id = channel;
- ret = sysdev_register(&cp->dev);
-
- printk("DMA channel %d at %p, irq %d\n",
- cp->number, cp->regs, cp->irq);
- }
-
- return 0;
-
- err:
- kmem_cache_destroy(dma_kmem);
- iounmap(dma_base);
- dma_base = NULL;
- return ret;
-}
-
-core_initcall(s3c2410_init_dma);
-
-static inline int is_channel_valid(unsigned int channel)
+static int __init s3c2442_dma_drvinit(void)
{
- return (channel & DMA_CH_VALID);
+ return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
}
-/* s3c2410_dma_map_channel()
- *
- * turn the virtual channel number into a real, and un-used hardware
- * channel.
- *
- * currently this code uses first-free channel from the specified harware
- * map, not taking into account anything that the board setup code may
- * have to say about the likely peripheral set to be in use.
-*/
-
-struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
-{
- struct s3c24xx_dma_map *ch_map;
- struct s3c2410_dma_chan *dmach;
- int ch;
-
- if (dma_sel.map == NULL || channel > dma_sel.map_size)
- return NULL;
-
- ch_map = dma_sel.map + channel;
-
- for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
- if (!is_channel_valid(ch_map->channels[ch]))
- continue;
-
- if (s3c2410_chans[ch].in_use == 0) {
- printk("mapped channel %d to %d\n", channel, ch);
- break;
- }
- }
-
- if (ch >= S3C2410_DMA_CHANNELS)
- return NULL;
-
- /* update our channel mapping */
-
- dmach = &s3c2410_chans[ch];
- dma_chan_map[channel] = dmach;
-
- /* select the channel */
-
- (dma_sel.select)(dmach, ch_map);
-
- return dmach;
-}
-
-static void s3c24xx_dma_show_ch(struct s3c24xx_dma_map *map, int ch)
-{
- /* show the channel configuration */
-
- printk("%2d: %20s, channels %c%c%c%c\n", ch, map->name,
- (is_channel_valid(map->channels[0]) ? '0' : '-'),
- (is_channel_valid(map->channels[1]) ? '1' : '-'),
- (is_channel_valid(map->channels[2]) ? '2' : '-'),
- (is_channel_valid(map->channels[3]) ? '3' : '-'));
-}
-
-static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
-{
- if (1)
- s3c24xx_dma_show_ch(map, ch);
-
- return 0;
-}
-
-int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
-{
- struct s3c24xx_dma_map *nmap;
- size_t map_sz = sizeof(*nmap) * sel->map_size;
- int ptr;
-
- nmap = kmalloc(map_sz, GFP_KERNEL);
- if (nmap == NULL)
- return -ENOMEM;
-
- memcpy(nmap, sel->map, map_sz);
- memcpy(&dma_sel, sel, sizeof(*sel));
-
- dma_sel.map = nmap;
-
- for (ptr = 0; ptr < sel->map_size; ptr++)
- s3c24xx_dma_check_entry(nmap+ptr, ptr);
+arch_initcall(s3c2442_dma_drvinit);
+#endif
- return 0;
-}
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
index f6fb215bb48..01e795d1146 100644
--- a/arch/arm/mach-s3c2410/gpio.c
+++ b/arch/arm/mach-s3c2410/gpio.c
@@ -1,9 +1,9 @@
/* linux/arch/arm/mach-s3c2410/gpio.c
*
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2004-2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
- * S3C24XX GPIO support
+ * S3C2410 GPIO support
*
* 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
@@ -18,8 +18,7 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
+ */
#include <linux/kernel.h>
#include <linux/init.h>
@@ -33,156 +32,40 @@
#include <asm/arch/regs-gpio.h>
-void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
-{
- void __iomem *base = S3C24XX_GPIO_BASE(pin);
- unsigned long mask;
- unsigned long con;
- unsigned long flags;
-
- if (pin < S3C2410_GPIO_BANKB) {
- mask = 1 << S3C2410_GPIO_OFFSET(pin);
- } else {
- mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
- }
-
- switch (function) {
- case S3C2410_GPIO_LEAVE:
- mask = 0;
- function = 0;
- break;
-
- case S3C2410_GPIO_INPUT:
- case S3C2410_GPIO_OUTPUT:
- case S3C2410_GPIO_SFN2:
- case S3C2410_GPIO_SFN3:
- if (pin < S3C2410_GPIO_BANKB) {
- function -= 1;
- function &= 1;
- function <<= S3C2410_GPIO_OFFSET(pin);
- } else {
- function &= 3;
- function <<= S3C2410_GPIO_OFFSET(pin)*2;
- }
- }
-
- /* modify the specified register wwith IRQs off */
-
- local_irq_save(flags);
-
- con = __raw_readl(base + 0x00);
- con &= ~mask;
- con |= function;
-
- __raw_writel(con, base + 0x00);
-
- local_irq_restore(flags);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
-
-unsigned int s3c2410_gpio_getcfg(unsigned int pin)
-{
- void __iomem *base = S3C24XX_GPIO_BASE(pin);
- unsigned long val = __raw_readl(base);
-
- if (pin < S3C2410_GPIO_BANKB) {
- val >>= S3C2410_GPIO_OFFSET(pin);
- val &= 1;
- val += 1;
- } else {
- val >>= S3C2410_GPIO_OFFSET(pin)*2;
- val &= 3;
- }
-
- return val | S3C2410_GPIO_INPUT;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getcfg);
-
-void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
+int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+ unsigned int config)
{
- void __iomem *base = S3C24XX_GPIO_BASE(pin);
- unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+ void __iomem *reg = S3C24XX_EINFLT0;
unsigned long flags;
- unsigned long up;
-
- if (pin < S3C2410_GPIO_BANKB)
- return;
-
- local_irq_save(flags);
-
- up = __raw_readl(base + 0x08);
- up &= ~(1L << offs);
- up |= to << offs;
- __raw_writel(up, base + 0x08);
+ unsigned long val;
- local_irq_restore(flags);
-}
+ if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
+ return -1;
-EXPORT_SYMBOL(s3c2410_gpio_pullup);
+ config &= 0xff;
-void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
-{
- void __iomem *base = S3C24XX_GPIO_BASE(pin);
- unsigned long offs = S3C2410_GPIO_OFFSET(pin);
- unsigned long flags;
- unsigned long dat;
+ pin -= S3C2410_GPG8;
+ reg += pin & ~3;
local_irq_save(flags);
- dat = __raw_readl(base + 0x04);
- dat &= ~(1 << offs);
- dat |= to << offs;
- __raw_writel(dat, base + 0x04);
-
- local_irq_restore(flags);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_setpin);
-
-unsigned int s3c2410_gpio_getpin(unsigned int pin)
-{
- void __iomem *base = S3C24XX_GPIO_BASE(pin);
- unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+ /* update filter width and clock source */
- return __raw_readl(base + 0x04) & (1<< offs);
-}
+ val = __raw_readl(reg);
+ val &= ~(0xff << ((pin & 3) * 8));
+ val |= config << ((pin & 3) * 8);
+ __raw_writel(val, reg);
-EXPORT_SYMBOL(s3c2410_gpio_getpin);
+ /* update filter enable */
-unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
-{
- unsigned long flags;
- unsigned long misccr;
+ val = __raw_readl(S3C24XX_EXTINT2);
+ val &= ~(1 << ((pin * 4) + 3));
+ val |= on << ((pin * 4) + 3);
+ __raw_writel(val, S3C24XX_EXTINT2);
- local_irq_save(flags);
- misccr = __raw_readl(S3C24XX_MISCCR);
- misccr &= ~clear;
- misccr ^= change;
- __raw_writel(misccr, S3C24XX_MISCCR);
local_irq_restore(flags);
- return misccr;
-}
-
-EXPORT_SYMBOL(s3c2410_modify_misccr);
-
-int s3c2410_gpio_getirq(unsigned int pin)
-{
- if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
- return -1; /* not valid interrupts */
-
- if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
- return -1; /* not valid pin */
-
- if (pin < S3C2410_GPF4)
- return (pin - S3C2410_GPF0) + IRQ_EINT0;
-
- if (pin < S3C2410_GPG0)
- return (pin - S3C2410_GPF4) + IRQ_EINT4;
-
- return (pin - S3C2410_GPG0) + IRQ_EINT8;
+ return 0;
}
-EXPORT_SYMBOL(s3c2410_gpio_getirq);
+EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 3c0ed7871c5..53cbdaa43ac 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/irq.c
*
- * Copyright (c) 2003,2004 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* This program is free software; you can redistribute it and/or modify
@@ -17,37 +17,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * Changelog:
- *
- * 22-Jul-2004 Ben Dooks <ben@simtec.co.uk>
- * Fixed compile warnings
- *
- * 22-Jul-2004 Roc Wu <cooloney@yahoo.com.cn>
- * Fixed s3c_extirq_type
- *
- * 21-Jul-2004 Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
- * Addition of ADC/TC demux
- *
- * 04-Oct-2004 Klaus Fetscher <k.fetscher@fetron.de>
- * Fix for set_irq_type() on low EINT numbers
- *
- * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
- * Tidy up KF's patch and sort out new release
- *
- * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
- * Add support for power management controls
- *
- * 04-Nov-2004 Ben Dooks
- * Fix standard IRQ wake for EINT0..4 and RTC
- *
- * 22-Feb-2005 Ben Dooks
- * Fixed edge-triggering on ADC IRQ
- *
- * 28-Jun-2005 Ben Dooks
- * Mark IRQ_LCD valid
- *
- * 25-Jul-2005 Ben Dooks
- * Split the S3C2440 IRQ code to seperate file
*/
#include <linux/init.h>
@@ -57,745 +26,23 @@
#include <linux/ptrace.h>
#include <linux/sysdev.h>
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/mach/irq.h>
-
-#include <asm/arch/regs-irq.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
-
-/* wakeup irq control */
-
-#ifdef CONFIG_PM
-
-/* state for IRQs over sleep */
-
-/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
- *
- * set bit to 1 in allow bitfield to enable the wakeup settings on it
-*/
-
-unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
-unsigned long s3c_irqwake_intmask = 0xffffffffL;
-unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
-unsigned long s3c_irqwake_eintmask = 0xffffffffL;
-
-int
-s3c_irq_wake(unsigned int irqno, unsigned int state)
-{
- unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
-
- if (!(s3c_irqwake_intallow & irqbit))
- return -ENOENT;
-
- printk(KERN_INFO "wake %s for irq %d\n",
- state ? "enabled" : "disabled", irqno);
-
- if (!state)
- s3c_irqwake_intmask |= irqbit;
- else
- s3c_irqwake_intmask &= ~irqbit;
-
- return 0;
-}
-
-static int
-s3c_irqext_wake(unsigned int irqno, unsigned int state)
-{
- unsigned long bit = 1L << (irqno - EXTINT_OFF);
-
- if (!(s3c_irqwake_eintallow & bit))
- return -ENOENT;
-
- printk(KERN_INFO "wake %s for irq %d\n",
- state ? "enabled" : "disabled", irqno);
-
- if (!state)
- s3c_irqwake_eintmask |= bit;
- else
- s3c_irqwake_eintmask &= ~bit;
-
- return 0;
-}
-
-#else
-#define s3c_irqext_wake NULL
-#define s3c_irq_wake NULL
-#endif
-
-
-static void
-s3c_irq_mask(unsigned int irqno)
-{
- unsigned long mask;
-
- irqno -= IRQ_EINT0;
-
- mask = __raw_readl(S3C2410_INTMSK);
- mask |= 1UL << irqno;
- __raw_writel(mask, S3C2410_INTMSK);
-}
-
-static inline void
-s3c_irq_ack(unsigned int irqno)
-{
- unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-
- __raw_writel(bitval, S3C2410_SRCPND);
- __raw_writel(bitval, S3C2410_INTPND);
-}
-
-static inline void
-s3c_irq_maskack(unsigned int irqno)
-{
- unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
- unsigned long mask;
-
- mask = __raw_readl(S3C2410_INTMSK);
- __raw_writel(mask|bitval, S3C2410_INTMSK);
-
- __raw_writel(bitval, S3C2410_SRCPND);
- __raw_writel(bitval, S3C2410_INTPND);
-}
-
-
-static void
-s3c_irq_unmask(unsigned int irqno)
-{
- unsigned long mask;
-
- if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
- irqdbf2("s3c_irq_unmask %d\n", irqno);
-
- irqno -= IRQ_EINT0;
-
- mask = __raw_readl(S3C2410_INTMSK);
- mask &= ~(1UL << irqno);
- __raw_writel(mask, S3C2410_INTMSK);
-}
-
-struct irq_chip s3c_irq_level_chip = {
- .name = "s3c-level",
- .ack = s3c_irq_maskack,
- .mask = s3c_irq_mask,
- .unmask = s3c_irq_unmask,
- .set_wake = s3c_irq_wake
-};
-
-static struct irq_chip s3c_irq_chip = {
- .name = "s3c",
- .ack = s3c_irq_ack,
- .mask = s3c_irq_mask,
- .unmask = s3c_irq_unmask,
- .set_wake = s3c_irq_wake
-};
-
-static void
-s3c_irqext_mask(unsigned int irqno)
-{
- unsigned long mask;
-
- irqno -= EXTINT_OFF;
-
- mask = __raw_readl(S3C24XX_EINTMASK);
- mask |= ( 1UL << irqno);
- __raw_writel(mask, S3C24XX_EINTMASK);
-}
-
-static void
-s3c_irqext_ack(unsigned int irqno)
-{
- unsigned long req;
- unsigned long bit;
- unsigned long mask;
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
- bit = 1UL << (irqno - EXTINT_OFF);
-
- mask = __raw_readl(S3C24XX_EINTMASK);
-
- __raw_writel(bit, S3C24XX_EINTPEND);
-
- req = __raw_readl(S3C24XX_EINTPEND);
- req &= ~mask;
-
- /* not sure if we should be acking the parent irq... */
-
- if (irqno <= IRQ_EINT7 ) {
- if ((req & 0xf0) == 0)
- s3c_irq_ack(IRQ_EINT4t7);
- } else {
- if ((req >> 8) == 0)
- s3c_irq_ack(IRQ_EINT8t23);
- }
-}
-
-static void
-s3c_irqext_unmask(unsigned int irqno)
+static int s3c2410_irq_add(struct sys_device *sysdev)
{
- unsigned long mask;
-
- irqno -= EXTINT_OFF;
-
- mask = __raw_readl(S3C24XX_EINTMASK);
- mask &= ~( 1UL << irqno);
- __raw_writel(mask, S3C24XX_EINTMASK);
-}
-
-int
-s3c_irqext_type(unsigned int irq, unsigned int type)
-{
- void __iomem *extint_reg;
- void __iomem *gpcon_reg;
- unsigned long gpcon_offset, extint_offset;
- unsigned long newvalue = 0, value;
-
- if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
- {
- gpcon_reg = S3C2410_GPFCON;
- extint_reg = S3C24XX_EXTINT0;
- gpcon_offset = (irq - IRQ_EINT0) * 2;
- extint_offset = (irq - IRQ_EINT0) * 4;
- }
- else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
- {
- gpcon_reg = S3C2410_GPFCON;
- extint_reg = S3C24XX_EXTINT0;
- gpcon_offset = (irq - (EXTINT_OFF)) * 2;
- extint_offset = (irq - (EXTINT_OFF)) * 4;
- }
- else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
- {
- gpcon_reg = S3C2410_GPGCON;
- extint_reg = S3C24XX_EXTINT1;
- gpcon_offset = (irq - IRQ_EINT8) * 2;
- extint_offset = (irq - IRQ_EINT8) * 4;
- }
- else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
- {
- gpcon_reg = S3C2410_GPGCON;
- extint_reg = S3C24XX_EXTINT2;
- gpcon_offset = (irq - IRQ_EINT8) * 2;
- extint_offset = (irq - IRQ_EINT16) * 4;
- } else
- return -1;
-
- /* Set the GPIO to external interrupt mode */
- value = __raw_readl(gpcon_reg);
- value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
- __raw_writel(value, gpcon_reg);
-
- /* Set the external interrupt to pointed trigger type */
- switch (type)
- {
- case IRQT_NOEDGE:
- printk(KERN_WARNING "No edge setting!\n");
- break;
-
- case IRQT_RISING:
- newvalue = S3C2410_EXTINT_RISEEDGE;
- break;
-
- case IRQT_FALLING:
- newvalue = S3C2410_EXTINT_FALLEDGE;
- break;
-
- case IRQT_BOTHEDGE:
- newvalue = S3C2410_EXTINT_BOTHEDGE;
- break;
-
- case IRQT_LOW:
- newvalue = S3C2410_EXTINT_LOWLEV;
- break;
-
- case IRQT_HIGH:
- newvalue = S3C2410_EXTINT_HILEV;
- break;
-
- default:
- printk(KERN_ERR "No such irq type %d", type);
- return -1;
- }
-
- value = __raw_readl(extint_reg);
- value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
- __raw_writel(value, extint_reg);
-
return 0;
}
-static struct irq_chip s3c_irqext_chip = {
- .name = "s3c-ext",
- .mask = s3c_irqext_mask,
- .unmask = s3c_irqext_unmask,
- .ack = s3c_irqext_ack,
- .set_type = s3c_irqext_type,
- .set_wake = s3c_irqext_wake
-};
-
-static struct irq_chip s3c_irq_eint0t4 = {
- .name = "s3c-ext0",
- .ack = s3c_irq_ack,
- .mask = s3c_irq_mask,
- .unmask = s3c_irq_unmask,
- .set_wake = s3c_irq_wake,
- .set_type = s3c_irqext_type,
-};
-
-/* mask values for the parent registers for each of the interrupt types */
-
-#define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0))
-#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0))
-#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0))
-#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
-
-
-/* UART0 */
-
-static void
-s3c_irq_uart0_mask(unsigned int irqno)
-{
- s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
-}
-
-static void
-s3c_irq_uart0_unmask(unsigned int irqno)
-{
- s3c_irqsub_unmask(irqno, INTMSK_UART0);
-}
-
-static void
-s3c_irq_uart0_ack(unsigned int irqno)
-{
- s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
-}
-
-static struct irq_chip s3c_irq_uart0 = {
- .name = "s3c-uart0",
- .mask = s3c_irq_uart0_mask,
- .unmask = s3c_irq_uart0_unmask,
- .ack = s3c_irq_uart0_ack,
-};
-
-/* UART1 */
-
-static void
-s3c_irq_uart1_mask(unsigned int irqno)
-{
- s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
-}
-
-static void
-s3c_irq_uart1_unmask(unsigned int irqno)
-{
- s3c_irqsub_unmask(irqno, INTMSK_UART1);
-}
-
-static void
-s3c_irq_uart1_ack(unsigned int irqno)
-{
- s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
-}
-
-static struct irq_chip s3c_irq_uart1 = {
- .name = "s3c-uart1",
- .mask = s3c_irq_uart1_mask,
- .unmask = s3c_irq_uart1_unmask,
- .ack = s3c_irq_uart1_ack,
-};
-
-/* UART2 */
-
-static void
-s3c_irq_uart2_mask(unsigned int irqno)
-{
- s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
-}
-
-static void
-s3c_irq_uart2_unmask(unsigned int irqno)
-{
- s3c_irqsub_unmask(irqno, INTMSK_UART2);
-}
-
-static void
-s3c_irq_uart2_ack(unsigned int irqno)
-{
- s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
-}
-
-static struct irq_chip s3c_irq_uart2 = {
- .name = "s3c-uart2",
- .mask = s3c_irq_uart2_mask,
- .unmask = s3c_irq_uart2_unmask,
- .ack = s3c_irq_uart2_ack,
-};
-
-/* ADC and Touchscreen */
-
-static void
-s3c_irq_adc_mask(unsigned int irqno)
-{
- s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
-}
-
-static void
-s3c_irq_adc_unmask(unsigned int irqno)
-{
- s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
-}
-
-static void
-s3c_irq_adc_ack(unsigned int irqno)
-{
- s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
-}
-
-static struct irq_chip s3c_irq_adc = {
- .name = "s3c-adc",
- .mask = s3c_irq_adc_mask,
- .unmask = s3c_irq_adc_unmask,
- .ack = s3c_irq_adc_ack,
-};
-
-/* irq demux for adc */
-static void s3c_irq_demux_adc(unsigned int irq,
- struct irq_desc *desc)
-{
- unsigned int subsrc, submsk;
- unsigned int offset = 9;
- struct irq_desc *mydesc;
-
- /* read the current pending interrupts, and the mask
- * for what it is available */
-
- subsrc = __raw_readl(S3C2410_SUBSRCPND);
- submsk = __raw_readl(S3C2410_INTSUBMSK);
-
- subsrc &= ~submsk;
- subsrc >>= offset;
- subsrc &= 3;
-
- if (subsrc != 0) {
- if (subsrc & 1) {
- mydesc = irq_desc + IRQ_TC;
- desc_handle_irq(IRQ_TC, mydesc);
- }
- if (subsrc & 2) {
- mydesc = irq_desc + IRQ_ADC;
- desc_handle_irq(IRQ_ADC, mydesc);
- }
- }
-}
-
-static void s3c_irq_demux_uart(unsigned int start)
-{
- unsigned int subsrc, submsk;
- unsigned int offset = start - IRQ_S3CUART_RX0;
- struct irq_desc *desc;
-
- /* read the current pending interrupts, and the mask
- * for what it is available */
-
- subsrc = __raw_readl(S3C2410_SUBSRCPND);
- submsk = __raw_readl(S3C2410_INTSUBMSK);
-
- irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
- start, offset, subsrc, submsk);
-
- subsrc &= ~submsk;
- subsrc >>= offset;
- subsrc &= 7;
-
- if (subsrc != 0) {
- desc = irq_desc + start;
-
- if (subsrc & 1)
- desc_handle_irq(start, desc);
-
- desc++;
-
- if (subsrc & 2)
- desc_handle_irq(start+1, desc);
-
- desc++;
-
- if (subsrc & 4)
- desc_handle_irq(start+2, desc);
- }
-}
-
-/* uart demux entry points */
-
-static void
-s3c_irq_demux_uart0(unsigned int irq,
- struct irq_desc *desc)
-{
- irq = irq;
- s3c_irq_demux_uart(IRQ_S3CUART_RX0);
-}
-
-static void
-s3c_irq_demux_uart1(unsigned int irq,
- struct irq_desc *desc)
-{
- irq = irq;
- s3c_irq_demux_uart(IRQ_S3CUART_RX1);
-}
-
-static void
-s3c_irq_demux_uart2(unsigned int irq,
- struct irq_desc *desc)
-{
- irq = irq;
- s3c_irq_demux_uart(IRQ_S3CUART_RX2);
-}
-
-static void
-s3c_irq_demux_extint8(unsigned int irq,
- struct irq_desc *desc)
-{
- unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
- unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
-
- eintpnd &= ~eintmsk;
- eintpnd &= ~0xff; /* ignore lower irqs */
-
- /* we may as well handle all the pending IRQs here */
-
- while (eintpnd) {
- irq = __ffs(eintpnd);
- eintpnd &= ~(1<<irq);
-
- irq += (IRQ_EINT4 - 4);
- desc_handle_irq(irq, irq_desc + irq);
- }
-
-}
-
-static void
-s3c_irq_demux_extint4t7(unsigned int irq,
- struct irq_desc *desc)
-{
- unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
- unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
-
- eintpnd &= ~eintmsk;
- eintpnd &= 0xff; /* only lower irqs */
-
- /* we may as well handle all the pending IRQs here */
-
- while (eintpnd) {
- irq = __ffs(eintpnd);
- eintpnd &= ~(1<<irq);
-
- irq += (IRQ_EINT4 - 4);
-
- desc_handle_irq(irq, irq_desc + irq);
- }
-}
-
-#ifdef CONFIG_PM
-
-static struct sleep_save irq_save[] = {
- SAVE_ITEM(S3C2410_INTMSK),
- SAVE_ITEM(S3C2410_INTSUBMSK),
+static struct sysdev_driver s3c2410_irq_driver = {
+ .add = s3c2410_irq_add,
+ .suspend = s3c24xx_irq_suspend,
+ .resume = s3c24xx_irq_resume,
};
-/* the extint values move between the s3c2410/s3c2440 and the s3c2412
- * so we use an array to hold them, and to calculate the address of
- * the register at run-time
-*/
-
-static unsigned long save_extint[3];
-static unsigned long save_eintflt[4];
-static unsigned long save_eintmask;
-
-int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+static int s3c2410_irq_init(void)
{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(save_extint); i++)
- save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
-
- for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
- save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
-
- s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
- save_eintmask = __raw_readl(S3C24XX_EINTMASK);
-
- return 0;
+ return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
}
-int s3c24xx_irq_resume(struct sys_device *dev)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(save_extint); i++)
- __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
-
- for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
- __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
-
- s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
- __raw_writel(save_eintmask, S3C24XX_EINTMASK);
-
- return 0;
-}
-
-#else
-#define s3c24xx_irq_suspend NULL
-#define s3c24xx_irq_resume NULL
-#endif
-
-/* s3c24xx_init_irq
- *
- * Initialise S3C2410 IRQ system
-*/
-
-void __init s3c24xx_init_irq(void)
-{
- unsigned long pend;
- unsigned long last;
- int irqno;
- int i;
-
- irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
-
- /* first, clear all interrupts pending... */
-
- last = 0;
- for (i = 0; i < 4; i++) {
- pend = __raw_readl(S3C24XX_EINTPEND);
-
- if (pend == 0 || pend == last)
- break;
-
- __raw_writel(pend, S3C24XX_EINTPEND);
- printk("irq: clearing pending ext status %08x\n", (int)pend);
- last = pend;
- }
-
- last = 0;
- for (i = 0; i < 4; i++) {
- pend = __raw_readl(S3C2410_INTPND);
-
- if (pend == 0 || pend == last)
- break;
-
- __raw_writel(pend, S3C2410_SRCPND);
- __raw_writel(pend, S3C2410_INTPND);
- printk("irq: clearing pending status %08x\n", (int)pend);
- last = pend;
- }
-
- last = 0;
- for (i = 0; i < 4; i++) {
- pend = __raw_readl(S3C2410_SUBSRCPND);
-
- if (pend == 0 || pend == last)
- break;
-
- printk("irq: clearing subpending status %08x\n", (int)pend);
- __raw_writel(pend, S3C2410_SUBSRCPND);
- last = pend;
- }
-
- /* register the main interrupts */
-
- irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
-
- for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
- /* set all the s3c2410 internal irqs */
-
- switch (irqno) {
- /* deal with the special IRQs (cascaded) */
-
- case IRQ_EINT4t7:
- case IRQ_EINT8t23:
- case IRQ_UART0:
- case IRQ_UART1:
- case IRQ_UART2:
- case IRQ_ADCPARENT:
- set_irq_chip(irqno, &s3c_irq_level_chip);
- set_irq_handler(irqno, handle_level_irq);
- break;
-
- case IRQ_RESERVED6:
- case IRQ_RESERVED24:
- /* no IRQ here */
- break;
-
- default:
- //irqdbf("registering irq %d (s3c irq)\n", irqno);
- set_irq_chip(irqno, &s3c_irq_chip);
- set_irq_handler(irqno, handle_edge_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
- }
-
- /* setup the cascade irq handlers */
-
- set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
- set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
-
- set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
- set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
- set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
- set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
-
- /* external interrupts */
-
- for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
- irqdbf("registering irq %d (ext int)\n", irqno);
- set_irq_chip(irqno, &s3c_irq_eint0t4);
- set_irq_handler(irqno, handle_edge_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
-
- for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
- irqdbf("registering irq %d (extended s3c irq)\n", irqno);
- set_irq_chip(irqno, &s3c_irqext_chip);
- set_irq_handler(irqno, handle_edge_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
-
- /* register the uart interrupts */
-
- irqdbf("s3c2410: registering external interrupts\n");
-
- for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
- irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
- set_irq_chip(irqno, &s3c_irq_uart0);
- set_irq_handler(irqno, handle_level_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
-
- for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
- irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
- set_irq_chip(irqno, &s3c_irq_uart1);
- set_irq_handler(irqno, handle_level_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
-
- for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
- irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
- set_irq_chip(irqno, &s3c_irq_uart2);
- set_irq_handler(irqno, handle_level_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
-
- for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
- irqdbf("registering irq %d (s3c adc irq)\n", irqno);
- set_irq_chip(irqno, &s3c_irq_adc);
- set_irq_handler(irqno, handle_edge_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
-
- irqdbf("s3c2410: registered interrupt handlers\n");
-}
+arch_initcall(s3c2410_irq_init);
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index 817e2c68441..72f2cc4fcd0 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -1,4 +1,4 @@
-/***********************************************************************
+/* linux/arch/arm/mach-s3c2410/mach-amlm5900.c
*
* linux/arch/arm/mach-s3c2410/mach-amlm5900.c
*
@@ -35,7 +35,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
-
+#include <linux/serial_core.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -52,8 +52,8 @@
#include <asm/arch/regs-lcd.h>
#include <asm/arch/regs-gpio.h>
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
#ifdef CONFIG_MTD_PARTITIONS
@@ -113,12 +113,6 @@ static struct platform_device amlm5900_device_nor = {
#endif
static struct map_desc amlm5900_iodesc[] __initdata = {
- {
- .virtual = (u32)S3C24XX_VA_SPI,
- .pfn = __phys_to_pfn(S3C2410_PA_SPI),
- .length = SZ_1M,
- .type = MT_DEVICE
- }
};
#define UCON S3C2410_UCON_DEFAULT
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index b8b76757ec5..7b81296427e 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -50,9 +50,9 @@
#include <linux/serial_8250.h>
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
#include "usb-simtec.h"
#define COPYRIGHT ", (c) 2004-2005 Simtec Electronics"
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 15b625eae49..01c60d0923c 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -25,23 +25,24 @@
#include <asm/mach/irq.h>
#include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
-
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-clock.h>
#include <asm/arch/h1940.h>
#include <asm/arch/h1940-latch.h>
#include <asm/arch/fb.h>
+#include <asm/arch/udc.h>
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
static struct map_desc h1940_iodesc[] __initdata = {
[0] = {
@@ -102,6 +103,32 @@ void h1940_latch_control(unsigned int clear, unsigned int set)
EXPORT_SYMBOL_GPL(h1940_latch_control);
+static void h1940_udc_pullup(enum s3c2410_udc_cmd_e cmd)
+{
+ printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
+
+ switch (cmd)
+ {
+ case S3C2410_UDC_P_ENABLE :
+ h1940_latch_control(0, H1940_LATCH_USB_DP);
+ break;
+ case S3C2410_UDC_P_DISABLE :
+ h1940_latch_control(H1940_LATCH_USB_DP, 0);
+ break;
+ case S3C2410_UDC_P_RESET :
+ break;
+ default:
+ break;
+ }
+}
+
+static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
+ .udc_command = h1940_udc_pullup,
+ .vbus_pin = S3C2410_GPG5,
+ .vbus_pin_inverted = 1,
+};
+
+
/**
* Set lcd on or off
@@ -146,12 +173,19 @@ static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = {
.bpp= {16,16,16},
};
+static struct platform_device s3c_device_leds = {
+ .name = "h1940-leds",
+ .id = -1,
+};
+
static struct platform_device *h1940_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
+ &s3c_device_usbgadget,
+ &s3c_device_leds,
};
static struct s3c24xx_board h1940_board __initdata = {
@@ -179,7 +213,23 @@ static void __init h1940_init_irq(void)
static void __init h1940_init(void)
{
+ u32 tmp;
+
s3c24xx_fb_set_platdata(&h1940_lcdcfg);
+ s3c24xx_udc_set_platdata(&h1940_udc_cfg);
+
+ /* Turn off suspend on both USB ports, and switch the
+ * selectable USB port to USB device mode. */
+
+ s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
+ S3C2410_MISCCR_USBSUSPND0 |
+ S3C2410_MISCCR_USBSUSPND1, 0x0);
+
+ tmp = (
+ 0x78 << S3C2410_PLLCON_MDIVSHIFT)
+ | (0x02 << S3C2410_PLLCON_PDIVSHIFT)
+ | (0x03 << S3C2410_PLLCON_SDIVSHIFT);
+ writel(tmp, S3C2410_UPLLCON);
}
MACHINE_START(H1940, "IPAQ-H1940")
@@ -189,6 +239,6 @@ MACHINE_START(H1940, "IPAQ-H1940")
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = h1940_map_io,
.init_irq = h1940_init_irq,
- .init_machine = h1940_init,
+ .init_machine = h1940_init,
.timer = &s3c24xx_timer,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 0411e9adb54..261aa4cc077 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -29,7 +29,6 @@
#include <asm/mach/irq.h>
#include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
@@ -38,10 +37,10 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/iic.h>
-#include "s3c2410.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
static struct map_desc n30_iodesc[] __initdata = {
/* nothing here yet */
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index 2c738b375e4..c78ab75b44f 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -32,10 +32,10 @@
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
-#include "s3c2410.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
static struct map_desc otom11_iodesc[] __initdata = {
/* Device area */
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
new file mode 100644
index 00000000000..c6a41593de2
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -0,0 +1,448 @@
+/* linux/arch/arm/mach-s3c2410/mach-qt2410.c
+ *
+ * Copyright (C) 2006 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/mmc/protocol.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/leds-gpio.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/fb.h>
+#include <asm/arch/nand.h>
+#include <asm/arch/udc.h>
+#include <asm/arch/spi.h>
+#include <asm/arch/spi-gpio.h>
+
+#include <asm/plat-s3c24xx/common-smdk.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+
+static struct map_desc qt2410_iodesc[] __initdata = {
+ { 0xe0000000, __phys_to_pfn(S3C2410_CS3+0x01000000), SZ_1M, MT_DEVICE }
+};
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk2410_uartcfgs[] = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ }
+};
+
+/* LCD driver info */
+
+/* Configuration for 640x480 SHARP LQ080V3DG01 */
+static struct s3c2410fb_mach_info qt2410_biglcd_cfg __initdata = {
+ .regs = {
+
+ .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
+ S3C2410_LCDCON1_TFT |
+ S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */
+
+ .lcdcon2 = S3C2410_LCDCON2_VBPD(18) | /* 19 */
+ S3C2410_LCDCON2_LINEVAL(479) |
+ S3C2410_LCDCON2_VFPD(10) | /* 11 */
+ S3C2410_LCDCON2_VSPW(14), /* 15 */
+
+ .lcdcon3 = S3C2410_LCDCON3_HBPD(43) | /* 44 */
+ S3C2410_LCDCON3_HOZVAL(639) | /* 640 */
+ S3C2410_LCDCON3_HFPD(115), /* 116 */
+
+ .lcdcon4 = S3C2410_LCDCON4_MVAL(0) |
+ S3C2410_LCDCON4_HSPW(95), /* 96 */
+
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN |
+ S3C2410_LCDCON5_HWSWP,
+ },
+
+ .lpcsel = ((0xCE6) & ~7) | 1<<4,
+
+ .width = 640,
+ .height = 480,
+
+ .xres = {
+ .min = 640,
+ .max = 640,
+ .defval = 640,
+ },
+
+ .yres = {
+ .min = 480,
+ .max = 480,
+ .defval = 480,
+ },
+
+ .bpp = {
+ .min = 16,
+ .max = 16,
+ .defval = 16,
+ },
+};
+
+/* Configuration for 480x640 toppoly TD028TTEC1 */
+static struct s3c2410fb_mach_info qt2410_prodlcd_cfg __initdata = {
+ .regs = {
+
+ .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
+ S3C2410_LCDCON1_TFT |
+ S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */
+
+ .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | /* 2 */
+ S3C2410_LCDCON2_LINEVAL(639) |/* 640 */
+ S3C2410_LCDCON2_VFPD(3) | /* 4 */
+ S3C2410_LCDCON2_VSPW(1), /* 2 */
+
+ .lcdcon3 = S3C2410_LCDCON3_HBPD(7) | /* 8 */
+ S3C2410_LCDCON3_HOZVAL(479) | /* 479 */
+ S3C2410_LCDCON3_HFPD(23), /* 24 */
+
+ .lcdcon4 = S3C2410_LCDCON4_MVAL(0) |
+ S3C2410_LCDCON4_HSPW(7), /* 8 */
+
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN |
+ S3C2410_LCDCON5_HWSWP,
+ },
+
+ .lpcsel = ((0xCE6) & ~7) | 1<<4,
+
+ .width = 480,
+ .height = 640,
+
+ .xres = {
+ .min = 480,
+ .max = 480,
+ .defval = 480,
+ },
+
+ .yres = {
+ .min = 640,
+ .max = 640,
+ .defval = 640,
+ },
+
+ .bpp = {
+ .min = 16,
+ .max = 16,
+ .defval = 16,
+ },
+};
+
+/* Config for 240x320 LCD */
+static struct s3c2410fb_mach_info qt2410_lcd_cfg __initdata = {
+ .regs = {
+
+ .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
+ S3C2410_LCDCON1_TFT |
+ S3C2410_LCDCON1_CLKVAL(0x04),
+
+ .lcdcon2 = S3C2410_LCDCON2_VBPD(1) |
+ S3C2410_LCDCON2_LINEVAL(319) |
+ S3C2410_LCDCON2_VFPD(6) |
+ S3C2410_LCDCON2_VSPW(3),
+
+ .lcdcon3 = S3C2410_LCDCON3_HBPD(12) |
+ S3C2410_LCDCON3_HOZVAL(239) |
+ S3C2410_LCDCON3_HFPD(7),
+
+ .lcdcon4 = S3C2410_LCDCON4_MVAL(0) |
+ S3C2410_LCDCON4_HSPW(3),
+
+ .lcdcon5 = S3C2410_LCDCON5_FRM565 |
+ S3C2410_LCDCON5_INVVLINE |
+ S3C2410_LCDCON5_INVVFRAME |
+ S3C2410_LCDCON5_PWREN |
+ S3C2410_LCDCON5_HWSWP,
+ },
+
+ .lpcsel = ((0xCE6) & ~7) | 1<<4,
+
+ .width = 240,
+ .height = 320,
+
+ .xres = {
+ .min = 240,
+ .max = 240,
+ .defval = 240,
+ },
+
+ .yres = {
+ .min = 320,
+ .max = 320,
+ .defval = 320,
+ },
+
+ .bpp = {
+ .min = 16,
+ .max = 16,
+ .defval = 16,
+ },
+};
+
+/* CS8900 */
+
+static struct resource qt2410_cs89x0_resources[] = {
+ [0] = {
+ .start = 0x19000000,
+ .end = 0x19000000 + 16,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_EINT9,
+ .end = IRQ_EINT9,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device qt2410_cs89x0 = {
+ .name = "cirrus-cs89x0",
+ .num_resources = ARRAY_SIZE(qt2410_cs89x0_resources),
+ .resource = qt2410_cs89x0_resources,
+};
+
+/* LED */
+
+static struct s3c24xx_led_platdata qt2410_pdata_led = {
+ .gpio = S3C2410_GPB0,
+ .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+ .name = "led",
+ .def_trigger = "timer",
+};
+
+static struct platform_device qt2410_led = {
+ .name = "s3c24xx_led",
+ .id = 0,
+ .dev = {
+ .platform_data = &qt2410_pdata_led,
+ },
+};
+
+/* SPI */
+
+static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
+{
+ switch (cs) {
+ case BITBANG_CS_ACTIVE:
+ s3c2410_gpio_setpin(S3C2410_GPB5, 0);
+ break;
+ case BITBANG_CS_INACTIVE:
+ s3c2410_gpio_setpin(S3C2410_GPB5, 1);
+ break;
+ }
+}
+
+static struct s3c2410_spigpio_info spi_gpio_cfg = {
+ .pin_clk = S3C2410_GPG7,
+ .pin_mosi = S3C2410_GPG6,
+ .pin_miso = S3C2410_GPG5,
+ .chip_select = &spi_gpio_cs,
+};
+
+
+static struct platform_device qt2410_spi = {
+ .name = "s3c24xx-spi-gpio",
+ .id = 1,
+ .dev = {
+ .platform_data = &spi_gpio_cfg,
+ },
+};
+
+/* Board devices */
+
+static struct platform_device *qt2410_devices[] __initdata = {
+ &s3c_device_usb,
+ &s3c_device_lcd,
+ &s3c_device_wdt,
+ &s3c_device_i2c,
+ &s3c_device_iis,
+ &s3c_device_sdi,
+ &s3c_device_usbgadget,
+ &qt2410_spi,
+ &qt2410_cs89x0,
+ &qt2410_led,
+};
+
+static struct s3c24xx_board qt2410_board __initdata = {
+ .devices = qt2410_devices,
+ .devices_count = ARRAY_SIZE(qt2410_devices)
+};
+
+static struct mtd_partition qt2410_nand_part[] = {
+ [0] = {
+ .name = "U-Boot",
+ .size = 0x30000,
+ .offset = 0,
+ },
+ [1] = {
+ .name = "U-Boot environment",
+ .offset = 0x30000,
+ .size = 0x4000,
+ },
+ [2] = {
+ .name = "kernel",
+ .offset = 0x34000,
+ .size = SZ_2M,
+ },
+ [3] = {
+ .name = "initrd",
+ .offset = 0x234000,
+ .size = SZ_4M,
+ },
+ [4] = {
+ .name = "jffs2",
+ .offset = 0x634000,
+ .size = 0x39cc000,
+ },
+};
+
+static struct s3c2410_nand_set qt2410_nand_sets[] = {
+ [0] = {
+ .name = "NAND",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(qt2410_nand_part),
+ .partitions = qt2410_nand_part,
+ },
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+ */
+
+static struct s3c2410_platform_nand qt2410_nand_info = {
+ .tacls = 20,
+ .twrph0 = 60,
+ .twrph1 = 20,
+ .nr_sets = ARRAY_SIZE(qt2410_nand_sets),
+ .sets = qt2410_nand_sets,
+};
+
+/* UDC */
+
+static struct s3c2410_udc_mach_info qt2410_udc_cfg = {
+};
+
+static char tft_type = 's';
+
+static int __init qt2410_tft_setup(char *str)
+{
+ tft_type = str[0];
+ return 1;
+}
+
+__setup("tft=", qt2410_tft_setup);
+
+static void __init qt2410_map_io(void)
+{
+ s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
+ s3c24xx_init_clocks(12*1000*1000);
+ s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
+ s3c24xx_set_board(&qt2410_board);
+}
+
+static void __init qt2410_machine_init(void)
+{
+ s3c_device_nand.dev.platform_data = &qt2410_nand_info;
+
+ switch (tft_type) {
+ case 'p': /* production */
+ s3c24xx_fb_set_platdata(&qt2410_prodlcd_cfg);
+ break;
+ case 'b': /* big */
+ s3c24xx_fb_set_platdata(&qt2410_biglcd_cfg);
+ break;
+ case 's': /* small */
+ default:
+ s3c24xx_fb_set_platdata(&qt2410_lcd_cfg);
+ break;
+ }
+
+ s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT);
+ s3c2410_gpio_setpin(S3C2410_GPB0, 1);
+
+ s3c24xx_udc_set_platdata(&qt2410_udc_cfg);
+
+ s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT);
+
+ s3c2410_pm_init();
+}
+
+MACHINE_START(QT2410, "QT2410")
+ .phys_io = S3C2410_PA_UART,
+ .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+ .boot_params = S3C2410_SDRAM_PA + 0x100,
+ .map_io = qt2410_map_io,
+ .init_irq = s3c24xx_init_irq,
+ .init_machine = qt2410_machine_init,
+ .timer = &s3c24xx_timer,
+MACHINE_END
+
+
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 01c0c986d82..57b8a80f33d 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -1,4 +1,4 @@
-/***********************************************************************
+/* linux/arch/arm/mach-s3c2410/mach-smdk2410.c
*
* linux/arch/arm/mach-s3c2410/mach-smdk2410.c
*
@@ -49,10 +49,10 @@
#include <asm/arch/regs-serial.h>
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
-#include "common-smdk.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
static struct map_desc smdk2410_iodesc[] __initdata = {
/* nothing here yet */
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index a382fc09511..c947c75bcbf 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -43,9 +43,9 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/leds-gpio.h>
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
#include "usb-simtec.h"
/* macros for virtual address mods for the io space entries */
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index ebf294dd31d..3b3a7db4e0d 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -1,11 +1,9 @@
/* linux/arch/arm/mach-s3c2410/pm.c
*
- * Copyright (c) 2004,2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
- * S3C24XX Power Manager (Suspend-To-RAM) support
- *
- * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
+ * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
*
* 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
@@ -20,640 +18,139 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Parts based on arch/arm/mach-pxa/pm.c
- *
- * Thanks to Dimitry Andric for debugging
*/
#include <linux/init.h>
#include <linux/suspend.h>
#include <linux/errno.h>
#include <linux/time.h>
-#include <linux/interrupt.h>
-#include <linux/crc32.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/serial_core.h>
+#include <linux/sysdev.h>
-#include <asm/cacheflush.h>
#include <asm/hardware.h>
#include <asm/io.h>
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-irq.h>
-
-#include <asm/mach/time.h>
-
-#include "pm.h"
-
-/* for external use */
-
-unsigned long s3c_pm_flags;
-
-#define PFX "s3c24xx-pm: "
-
-static struct sleep_save core_save[] = {
- SAVE_ITEM(S3C2410_LOCKTIME),
- SAVE_ITEM(S3C2410_CLKCON),
-
- /* we restore the timings here, with the proviso that the board
- * brings the system up in an slower, or equal frequency setting
- * to the original system.
- *
- * if we cannot guarantee this, then things are going to go very
- * wrong here, as we modify the refresh and both pll settings.
- */
-
- SAVE_ITEM(S3C2410_BWSCON),
- SAVE_ITEM(S3C2410_BANKCON0),
- SAVE_ITEM(S3C2410_BANKCON1),
- SAVE_ITEM(S3C2410_BANKCON2),
- SAVE_ITEM(S3C2410_BANKCON3),
- SAVE_ITEM(S3C2410_BANKCON4),
- SAVE_ITEM(S3C2410_BANKCON5),
-
- SAVE_ITEM(S3C2410_CLKDIVN),
- SAVE_ITEM(S3C2410_MPLLCON),
- SAVE_ITEM(S3C2410_UPLLCON),
- SAVE_ITEM(S3C2410_CLKSLOW),
- SAVE_ITEM(S3C2410_REFRESH),
-};
-
-static struct sleep_save gpio_save[] = {
- SAVE_ITEM(S3C2410_GPACON),
- SAVE_ITEM(S3C2410_GPADAT),
-
- SAVE_ITEM(S3C2410_GPBCON),
- SAVE_ITEM(S3C2410_GPBDAT),
- SAVE_ITEM(S3C2410_GPBUP),
-
- SAVE_ITEM(S3C2410_GPCCON),
- SAVE_ITEM(S3C2410_GPCDAT),
- SAVE_ITEM(S3C2410_GPCUP),
-
- SAVE_ITEM(S3C2410_GPDCON),
- SAVE_ITEM(S3C2410_GPDDAT),
- SAVE_ITEM(S3C2410_GPDUP),
-
- SAVE_ITEM(S3C2410_GPECON),
- SAVE_ITEM(S3C2410_GPEDAT),
- SAVE_ITEM(S3C2410_GPEUP),
-
- SAVE_ITEM(S3C2410_GPFCON),
- SAVE_ITEM(S3C2410_GPFDAT),
- SAVE_ITEM(S3C2410_GPFUP),
+#include <asm/mach-types.h>
- SAVE_ITEM(S3C2410_GPGCON),
- SAVE_ITEM(S3C2410_GPGDAT),
- SAVE_ITEM(S3C2410_GPGUP),
-
- SAVE_ITEM(S3C2410_GPHCON),
- SAVE_ITEM(S3C2410_GPHDAT),
- SAVE_ITEM(S3C2410_GPHUP),
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/h1940.h>
- SAVE_ITEM(S3C2410_DCLKCON),
-};
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
#ifdef CONFIG_S3C2410_PM_DEBUG
-
-#define SAVE_UART(va) \
- SAVE_ITEM((va) + S3C2410_ULCON), \
- SAVE_ITEM((va) + S3C2410_UCON), \
- SAVE_ITEM((va) + S3C2410_UFCON), \
- SAVE_ITEM((va) + S3C2410_UMCON), \
- SAVE_ITEM((va) + S3C2410_UBRDIV)
-
-static struct sleep_save uart_save[] = {
- SAVE_UART(S3C24XX_VA_UART0),
- SAVE_UART(S3C24XX_VA_UART1),
-#ifndef CONFIG_CPU_S3C2400
- SAVE_UART(S3C24XX_VA_UART2),
-#endif
-};
-
-/* debug
- *
- * we send the debug to printascii() to allow it to be seen if the
- * system never wakes up from the sleep
-*/
-
-extern void printascii(const char *);
-
-void pm_dbg(const char *fmt, ...)
-{
- va_list va;
- char buff[256];
-
- va_start(va, fmt);
- vsprintf(buff, fmt, va);
- va_end(va);
-
- printascii(buff);
-}
-
-static void s3c2410_pm_debug_init(void)
-{
- unsigned long tmp = __raw_readl(S3C2410_CLKCON);
-
- /* re-start uart clocks */
- tmp |= S3C2410_CLKCON_UART0;
- tmp |= S3C2410_CLKCON_UART1;
- tmp |= S3C2410_CLKCON_UART2;
-
- __raw_writel(tmp, S3C2410_CLKCON);
- udelay(10);
-}
-
+extern void pm_dbg(const char *fmt, ...);
#define DBG(fmt...) pm_dbg(fmt)
#else
#define DBG(fmt...) printk(KERN_DEBUG fmt)
-
-#define s3c2410_pm_debug_init() do { } while(0)
-
-static struct sleep_save uart_save[] = {};
#endif
-#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
-
-/* suspend checking code...
- *
- * this next area does a set of crc checks over all the installed
- * memory, so the system can verify if the resume was ok.
- *
- * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
- * increasing it will mean that the area corrupted will be less easy to spot,
- * and reducing the size will cause the CRC save area to grow
-*/
-
-#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
-
-static u32 crc_size; /* size needed for the crc block */
-static u32 *crcs; /* allocated over suspend/resume */
-
-typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
-
-/* s3c2410_pm_run_res
- *
- * go thorugh the given resource list, and look for system ram
-*/
-
-static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
-{
- while (ptr != NULL) {
- if (ptr->child != NULL)
- s3c2410_pm_run_res(ptr->child, fn, arg);
-
- if ((ptr->flags & IORESOURCE_MEM) &&
- strcmp(ptr->name, "System RAM") == 0) {
- DBG("Found system RAM at %08lx..%08lx\n",
- ptr->start, ptr->end);
- arg = (fn)(ptr, arg);
- }
-
- ptr = ptr->sibling;
- }
-}
-
-static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
-{
- s3c2410_pm_run_res(&iomem_resource, fn, arg);
-}
-
-static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
-{
- u32 size = (u32)(res->end - res->start)+1;
-
- size += CHECK_CHUNKSIZE-1;
- size /= CHECK_CHUNKSIZE;
-
- DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
-
- *val += size * sizeof(u32);
- return val;
-}
-
-/* s3c2410_pm_prepare_check
- *
- * prepare the necessary information for creating the CRCs. This
- * must be done before the final save, as it will require memory
- * allocating, and thus touching bits of the kernel we do not
- * know about.
-*/
-
-static void s3c2410_pm_check_prepare(void)
+static void s3c2410_pm_prepare(void)
{
- crc_size = 0;
+ /* ensure at least GSTATUS3 has the resume address */
- s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
+ __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
- DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
+ DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
+ DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
- crcs = kmalloc(crc_size+4, GFP_KERNEL);
- if (crcs == NULL)
- printk(KERN_ERR "Cannot allocated CRC save area\n");
-}
+ if (machine_is_h1940()) {
+ void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+ unsigned long ptr;
+ unsigned long calc = 0;
-static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
-{
- unsigned long addr, left;
+ /* generate check for the bootloader to check on resume */
- for (addr = res->start; addr < res->end;
- addr += CHECK_CHUNKSIZE) {
- left = res->end - addr;
+ for (ptr = 0; ptr < 0x40000; ptr += 0x400)
+ calc += __raw_readl(base+ptr);
- if (left > CHECK_CHUNKSIZE)
- left = CHECK_CHUNKSIZE;
-
- *val = crc32_le(~0, phys_to_virt(addr), left);
- val++;
+ __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
}
- return val;
-}
-
-/* s3c2410_pm_check_store
- *
- * compute the CRC values for the memory blocks before the final
- * sleep.
-*/
-
-static void s3c2410_pm_check_store(void)
-{
- if (crcs != NULL)
- s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
-}
-
-/* in_region
- *
- * return TRUE if the area defined by ptr..ptr+size contatins the
- * what..what+whatsz
-*/
-
-static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
-{
- if ((what+whatsz) < ptr)
- return 0;
-
- if (what > (ptr+size))
- return 0;
-
- return 1;
-}
-
-static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
-{
- void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
- unsigned long addr;
- unsigned long left;
- void *ptr;
- u32 calc;
-
- for (addr = res->start; addr < res->end;
- addr += CHECK_CHUNKSIZE) {
- left = res->end - addr;
+ /* the RX3715 uses similar code and the same H1940 and the
+ * same offsets for resume and checksum pointers */
- if (left > CHECK_CHUNKSIZE)
- left = CHECK_CHUNKSIZE;
+ if (machine_is_rx3715()) {
+ void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+ unsigned long ptr;
+ unsigned long calc = 0;
- ptr = phys_to_virt(addr);
+ /* generate check for the bootloader to check on resume */
- if (in_region(ptr, left, crcs, crc_size)) {
- DBG("skipping %08lx, has crc block in\n", addr);
- goto skip_check;
- }
+ for (ptr = 0; ptr < 0x40000; ptr += 0x4)
+ calc += __raw_readl(base+ptr);
- if (in_region(ptr, left, save_at, 32*4 )) {
- DBG("skipping %08lx, has save block in\n", addr);
- goto skip_check;
- }
-
- /* calculate and check the checksum */
-
- calc = crc32_le(~0, ptr, left);
- if (calc != *val) {
- printk(KERN_ERR PFX "Restore CRC error at "
- "%08lx (%08x vs %08x)\n", addr, calc, *val);
-
- DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
- addr, calc, *val);
- }
-
- skip_check:
- val++;
+ __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
}
- return val;
-}
+ if ( machine_is_aml_m5900() )
+ s3c2410_gpio_setpin(S3C2410_GPF2, 1);
-/* s3c2410_pm_check_restore
- *
- * check the CRCs after the restore event and free the memory used
- * to hold them
-*/
-
-static void s3c2410_pm_check_restore(void)
-{
- if (crcs != NULL) {
- s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
- kfree(crcs);
- crcs = NULL;
- }
}
-#else
-
-#define s3c2410_pm_check_prepare() do { } while(0)
-#define s3c2410_pm_check_restore() do { } while(0)
-#define s3c2410_pm_check_store() do { } while(0)
-#endif
-
-/* helper functions to save and restore register state */
-
-void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
+static int s3c2410_pm_resume(struct sys_device *dev)
{
- for (; count > 0; count--, ptr++) {
- ptr->val = __raw_readl(ptr->reg);
- DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
- }
-}
+ unsigned long tmp;
-/* s3c2410_pm_do_restore
- *
- * restore the system from the given list of saved registers
- *
- * Note, we do not use DBG() in here, as the system may not have
- * restore the UARTs state yet
-*/
+ /* unset the return-from-sleep flag, to ensure reset */
-void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
-{
- for (; count > 0; count--, ptr++) {
- printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
- ptr->reg, ptr->val, __raw_readl(ptr->reg));
-
- __raw_writel(ptr->val, ptr->reg);
- }
-}
+ tmp = __raw_readl(S3C2410_GSTATUS2);
+ tmp &= S3C2410_GSTATUS2_OFFRESET;
+ __raw_writel(tmp, S3C2410_GSTATUS2);
-/* s3c2410_pm_do_restore_core
- *
- * similar to s3c2410_pm_do_restore_core
- *
- * WARNING: Do not put any debug in here that may effect memory or use
- * peripherals, as things may be changing!
-*/
+ if ( machine_is_aml_m5900() )
+ s3c2410_gpio_setpin(S3C2410_GPF2, 0);
-static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
-{
- for (; count > 0; count--, ptr++) {
- __raw_writel(ptr->val, ptr->reg);
- }
+ return 0;
}
-/* s3c2410_pm_show_resume_irqs
- *
- * print any IRQs asserted at resume time (ie, we woke from)
-*/
-
-static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
- unsigned long mask)
+static int s3c2410_pm_add(struct sys_device *dev)
{
- int i;
+ pm_cpu_prep = s3c2410_pm_prepare;
+ pm_cpu_sleep = s3c2410_cpu_suspend;
- which &= ~mask;
-
- for (i = 0; i <= 31; i++) {
- if ((which) & (1L<<i)) {
- DBG("IRQ %d asserted at resume\n", start+i);
- }
- }
+ return 0;
}
-/* s3c2410_pm_check_resume_pin
- *
- * check to see if the pin is configured correctly for sleep mode, and
- * make any necessary adjustments if it is not
-*/
-
-static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
-{
- unsigned long irqstate;
- unsigned long pinstate;
- int irq = s3c2410_gpio_getirq(pin);
-
- if (irqoffs < 4)
- irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
- else
- irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
-
- pinstate = s3c2410_gpio_getcfg(pin);
-
- if (!irqstate) {
- if (pinstate == S3C2410_GPIO_IRQ)
- DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
- } else {
- if (pinstate == S3C2410_GPIO_IRQ) {
- DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
- s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
- }
- }
-}
+#if defined(CONFIG_CPU_S3C2410)
+static struct sysdev_driver s3c2410_pm_driver = {
+ .add = s3c2410_pm_add,
+ .resume = s3c2410_pm_resume,
+};
-/* s3c2410_pm_configure_extint
- *
- * configure all external interrupt pins
-*/
+/* register ourselves */
-static void s3c2410_pm_configure_extint(void)
+static int __init s3c2410_pm_drvinit(void)
{
- int pin;
-
- /* for each of the external interrupts (EINT0..EINT15) we
- * need to check wether it is an external interrupt source,
- * and then configure it as an input if it is not
- */
-
- for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
- s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
- }
-
- for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
- s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
- }
+ return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
}
-void (*pm_cpu_prep)(void);
-void (*pm_cpu_sleep)(void);
-
-#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
-
-/* s3c2410_pm_enter
- *
- * central control for sleep/resume process
-*/
-
-static int s3c2410_pm_enter(suspend_state_t state)
-{
- unsigned long regs_save[16];
-
- /* ensure the debug is initialised (if enabled) */
-
- s3c2410_pm_debug_init();
-
- DBG("s3c2410_pm_enter(%d)\n", state);
-
- if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
- printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
- return -EINVAL;
- }
-
- if (state != PM_SUSPEND_MEM) {
- printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
- return -EINVAL;
- }
-
- /* check if we have anything to wake-up with... bad things seem
- * to happen if you suspend with no wakeup (system will often
- * require a full power-cycle)
- */
-
- if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
- !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
- printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
- printk(KERN_ERR PFX "Aborting sleep\n");
- return -EINVAL;
- }
-
- /* prepare check area if configured */
-
- s3c2410_pm_check_prepare();
-
- /* store the physical address of the register recovery block */
-
- s3c2410_sleep_save_phys = virt_to_phys(regs_save);
-
- DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
-
- /* save all necessary core registers not covered by the drivers */
-
- s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
- s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
- s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
-
- /* set the irq configuration for wake */
-
- s3c2410_pm_configure_extint();
-
- DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
- s3c_irqwake_intmask, s3c_irqwake_eintmask);
-
- __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
- __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
-
- /* ack any outstanding external interrupts before we go to sleep */
-
- __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
- __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
- __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
-
- /* call cpu specific preperation */
-
- pm_cpu_prep();
-
- /* flush cache back to ram */
-
- flush_cache_all();
-
- s3c2410_pm_check_store();
-
- /* send the cpu to sleep... */
-
- __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
-
- /* s3c2410_cpu_save will also act as our return point from when
- * we resume as it saves its own register state, so use the return
- * code to differentiate return from save and return from sleep */
-
- if (s3c2410_cpu_save(regs_save) == 0) {
- flush_cache_all();
- pm_cpu_sleep();
- }
-
- /* restore the cpu state */
-
- cpu_init();
-
- /* restore the system state */
-
- s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
- s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
- s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
-
- s3c2410_pm_debug_init();
-
- /* check what irq (if any) restored the system */
-
- DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
- __raw_readl(S3C2410_SRCPND),
- __raw_readl(S3C2410_EINTPEND));
-
- s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
- s3c_irqwake_intmask);
-
- s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
- s3c_irqwake_eintmask);
-
- DBG("post sleep, preparing to return\n");
-
- s3c2410_pm_check_restore();
-
- /* ok, let's return from sleep */
+arch_initcall(s3c2410_pm_drvinit);
+#endif
- DBG("S3C2410 PM Resume (post-restore)\n");
- return 0;
-}
+#if defined(CONFIG_CPU_S3C2440)
+static struct sysdev_driver s3c2440_pm_driver = {
+ .add = s3c2410_pm_add,
+ .resume = s3c2410_pm_resume,
+};
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-static int s3c2410_pm_prepare(suspend_state_t state)
+static int __init s3c2440_pm_drvinit(void)
{
- return 0;
+ return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
}
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-static int s3c2410_pm_finish(suspend_state_t state)
-{
- return 0;
-}
+arch_initcall(s3c2440_pm_drvinit);
+#endif
-/*
- * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
- */
-static struct pm_ops s3c2410_pm_ops = {
- .pm_disk_mode = PM_DISK_FIRMWARE,
- .prepare = s3c2410_pm_prepare,
- .enter = s3c2410_pm_enter,
- .finish = s3c2410_pm_finish,
+#if defined(CONFIG_CPU_S3C2442)
+static struct sysdev_driver s3c2442_pm_driver = {
+ .add = s3c2410_pm_add,
+ .resume = s3c2410_pm_resume,
};
-/* s3c2410_pm_init
- *
- * Attach the power management functions. This should be called
- * from the board specific initialisation if the board supports
- * it.
-*/
-
-int __init s3c2410_pm_init(void)
+static int __init s3c2442_pm_drvinit(void)
{
- printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
-
- pm_set_ops(&s3c2410_pm_ops);
- return 0;
+ return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
}
+
+arch_initcall(s3c2442_pm_drvinit);
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c
deleted file mode 100644
index 992cc6af230..00000000000
--- a/arch/arm/mach-s3c2410/s3c2410-clock.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-clock.c
- *
- * Copyright (c) 2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410,S3C2440,S3C2442 Clock control support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/sysdev.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/serial_core.h>
-
-#include <asm/mach/map.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "s3c2410.h"
-#include "clock.h"
-#include "cpu.h"
-
-int s3c2410_clkcon_enable(struct clk *clk, int enable)
-{
- unsigned int clocks = clk->ctrlbit;
- unsigned long clkcon;
-
- clkcon = __raw_readl(S3C2410_CLKCON);
-
- if (enable)
- clkcon |= clocks;
- else
- clkcon &= ~clocks;
-
- /* ensure none of the special function bits set */
- clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
-
- __raw_writel(clkcon, S3C2410_CLKCON);
-
- return 0;
-}
-
-static int s3c2410_upll_enable(struct clk *clk, int enable)
-{
- unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
- unsigned long orig = clkslow;
-
- if (enable)
- clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
- else
- clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
-
- __raw_writel(clkslow, S3C2410_CLKSLOW);
-
- /* if we started the UPLL, then allow to settle */
-
- if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
- udelay(200);
-
- return 0;
-}
-
-/* standard clock definitions */
-
-static struct clk init_clocks_disable[] = {
- {
- .name = "nand",
- .id = -1,
- .parent = &clk_h,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_NAND,
- }, {
- .name = "sdi",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_SDI,
- }, {
- .name = "adc",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_ADC,
- }, {
- .name = "i2c",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_IIC,
- }, {
- .name = "iis",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_IIS,
- }, {
- .name = "spi",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_SPI,
- }
-};
-
-static struct clk init_clocks[] = {
- {
- .name = "lcd",
- .id = -1,
- .parent = &clk_h,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_LCDC,
- }, {
- .name = "gpio",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_GPIO,
- }, {
- .name = "usb-host",
- .id = -1,
- .parent = &clk_h,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_USBH,
- }, {
- .name = "usb-device",
- .id = -1,
- .parent = &clk_h,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_USBD,
- }, {
- .name = "timers",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_PWMT,
- }, {
- .name = "uart",
- .id = 0,
- .parent = &clk_p,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_UART0,
- }, {
- .name = "uart",
- .id = 1,
- .parent = &clk_p,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_UART1,
- }, {
- .name = "uart",
- .id = 2,
- .parent = &clk_p,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_UART2,
- }, {
- .name = "rtc",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c2410_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_RTC,
- }, {
- .name = "watchdog",
- .id = -1,
- .parent = &clk_p,
- .ctrlbit = 0,
- }, {
- .name = "usb-bus-host",
- .id = -1,
- .parent = &clk_usb_bus,
- }, {
- .name = "usb-bus-gadget",
- .id = -1,
- .parent = &clk_usb_bus,
- },
-};
-
-/* s3c2410_baseclk_add()
- *
- * Add all the clocks used by the s3c2410 or compatible CPUs
- * such as the S3C2440 and S3C2442.
- *
- * We cannot use a system device as we are needed before any
- * of the init-calls that initialise the devices are actually
- * done.
-*/
-
-int __init s3c2410_baseclk_add(void)
-{
- unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
- unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
- struct clk *clkp;
- struct clk *xtal;
- int ret;
- int ptr;
-
- clk_upll.enable = s3c2410_upll_enable;
-
- if (s3c24xx_register_clock(&clk_usb_bus) < 0)
- printk(KERN_ERR "failed to register usb bus clock\n");
-
- /* register clocks from clock array */
-
- clkp = init_clocks;
- for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
- /* ensure that we note the clock state */
-
- clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
-
- ret = s3c24xx_register_clock(clkp);
- if (ret < 0) {
- printk(KERN_ERR "Failed to register clock %s (%d)\n",
- clkp->name, ret);
- }
- }
-
- /* We must be careful disabling the clocks we are not intending to
- * be using at boot time, as subsytems such as the LCD which do
- * their own DMA requests to the bus can cause the system to lockup
- * if they where in the middle of requesting bus access.
- *
- * Disabling the LCD clock if the LCD is active is very dangerous,
- * and therefore the bootloader should be careful to not enable
- * the LCD clock if it is not needed.
- */
-
- /* install (and disable) the clocks we do not need immediately */
-
- clkp = init_clocks_disable;
- for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
- ret = s3c24xx_register_clock(clkp);
- if (ret < 0) {
- printk(KERN_ERR "Failed to register clock %s (%d)\n",
- clkp->name, ret);
- }
-
- s3c2410_clkcon_enable(clkp, 0);
- }
-
- /* show the clock-slow value */
-
- xtal = clk_get(NULL, "xtal");
-
- printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
- print_mhz(clk_get_rate(xtal) /
- ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
- (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
- (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
- (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
-
- return 0;
-}
diff --git a/arch/arm/mach-s3c2410/s3c2410-dma.c b/arch/arm/mach-s3c2410/s3c2410-dma.c
deleted file mode 100644
index e67ba3911f1..00000000000
--- a/arch/arm/mach-s3c2410/s3c2410-dma.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-dma.c
- *
- * Copyright (c) 2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 DMA selection
- *
- * http://armlinux.simtec.co.uk/
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/sysdev.h>
-#include <linux/serial_core.h>
-
-#include <asm/dma.h>
-#include <asm/arch/dma.h>
-#include "dma.h"
-
-#include "cpu.h"
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-ac97.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-lcd.h>
-#include <asm/arch/regs-sdi.h>
-#include <asm/arch/regs-iis.h>
-#include <asm/arch/regs-spi.h>
-
-static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
- [DMACH_XD0] = {
- .name = "xdreq0",
- .channels[0] = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
- },
- [DMACH_XD1] = {
- .name = "xdreq1",
- .channels[1] = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
- },
- [DMACH_SDI] = {
- .name = "sdi",
- .channels[0] = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
- .channels[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
- .channels[3] = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
- .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
- },
- [DMACH_SPI0] = {
- .name = "spi0",
- .channels[1] = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT,
- .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT,
- },
- [DMACH_SPI1] = {
- .name = "spi1",
- .channels[3] = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
- .hw_addr.from = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
- },
- [DMACH_UART0] = {
- .name = "uart0",
- .channels[0] = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
- },
- [DMACH_UART1] = {
- .name = "uart1",
- .channels[1] = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
- },
- [DMACH_UART2] = {
- .name = "uart2",
- .channels[3] = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
- .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
- },
- [DMACH_TIMER] = {
- .name = "timer",
- .channels[0] = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
- .channels[2] = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
- .channels[3] = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
- },
- [DMACH_I2S_IN] = {
- .name = "i2s-sdi",
- .channels[1] = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
- .channels[2] = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
- .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
- },
- [DMACH_I2S_OUT] = {
- .name = "i2s-sdo",
- .channels[2] = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
- .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
- },
- [DMACH_USB_EP1] = {
- .name = "usb-ep1",
- .channels[0] = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
- },
- [DMACH_USB_EP2] = {
- .name = "usb-ep2",
- .channels[1] = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
- },
- [DMACH_USB_EP3] = {
- .name = "usb-ep3",
- .channels[2] = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
- },
- [DMACH_USB_EP4] = {
- .name = "usb-ep4",
- .channels[3] =S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
- },
-};
-
-static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
- struct s3c24xx_dma_map *map)
-{
- chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
-}
-
-static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
- .select = s3c2410_dma_select,
- .dcon_mask = 7 << 24,
- .map = s3c2410_dma_mappings,
- .map_size = ARRAY_SIZE(s3c2410_dma_mappings),
-};
-
-static int s3c2410_dma_add(struct sys_device *sysdev)
-{
- return s3c24xx_dma_init_map(&s3c2410_dma_sel);
-}
-
-#if defined(CONFIG_CPU_S3C2410)
-static struct sysdev_driver s3c2410_dma_driver = {
- .add = s3c2410_dma_add,
-};
-
-static int __init s3c2410_dma_init(void)
-{
- return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
-}
-
-arch_initcall(s3c2410_dma_init);
-#endif
-
-#if defined(CONFIG_CPU_S3C2442)
-/* S3C2442 DMA contains the same selection table as the S3C2410 */
-static struct sysdev_driver s3c2442_dma_driver = {
- .add = s3c2410_dma_add,
-};
-
-static int __init s3c2442_dma_init(void)
-{
- return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
-}
-
-arch_initcall(s3c2442_dma_init);
-#endif
-
diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c
deleted file mode 100644
index ec3a276cc3c..00000000000
--- a/arch/arm/mach-s3c2410/s3c2410-gpio.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-gpio.c
- *
- * Copyright (c) 2004-2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-gpio.h>
-
-int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
- unsigned int config)
-{
- void __iomem *reg = S3C24XX_EINFLT0;
- unsigned long flags;
- unsigned long val;
-
- if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
- return -1;
-
- config &= 0xff;
-
- pin -= S3C2410_GPG8;
- reg += pin & ~3;
-
- local_irq_save(flags);
-
- /* update filter width and clock source */
-
- val = __raw_readl(reg);
- val &= ~(0xff << ((pin & 3) * 8));
- val |= config << ((pin & 3) * 8);
- __raw_writel(val, reg);
-
- /* update filter enable */
-
- val = __raw_readl(S3C24XX_EXTINT2);
- val &= ~(1 << ((pin * 4) + 3));
- val |= on << ((pin * 4) + 3);
- __raw_writel(val, S3C24XX_EXTINT2);
-
- local_irq_restore(flags);
-
- return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/s3c2410-irq.c b/arch/arm/mach-s3c2410/s3c2410-irq.c
deleted file mode 100644
index c796c9c76e7..00000000000
--- a/arch/arm/mach-s3c2410/s3c2410-irq.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-irq.c
- *
- * Copyright (c) 2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/sysdev.h>
-
-#include "cpu.h"
-#include "pm.h"
-
-static int s3c2410_irq_add(struct sys_device *sysdev)
-{
- return 0;
-}
-
-static struct sysdev_driver s3c2410_irq_driver = {
- .add = s3c2410_irq_add,
- .suspend = s3c24xx_irq_suspend,
- .resume = s3c24xx_irq_resume,
-};
-
-static int s3c2410_irq_init(void)
-{
- return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
-}
-
-arch_initcall(s3c2410_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c2410-pm.c b/arch/arm/mach-s3c2410/s3c2410-pm.c
deleted file mode 100644
index 8bb6e5e21f5..00000000000
--- a/arch/arm/mach-s3c2410/s3c2410-pm.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-pm.c
- *
- * Copyright (c) 2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <linux/init.h>
-#include <linux/suspend.h>
-#include <linux/errno.h>
-#include <linux/time.h>
-#include <linux/sysdev.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/h1940.h>
-
-#include "cpu.h"
-#include "pm.h"
-
-#ifdef CONFIG_S3C2410_PM_DEBUG
-extern void pm_dbg(const char *fmt, ...);
-#define DBG(fmt...) pm_dbg(fmt)
-#else
-#define DBG(fmt...) printk(KERN_DEBUG fmt)
-#endif
-
-static void s3c2410_pm_prepare(void)
-{
- /* ensure at least GSTATUS3 has the resume address */
-
- __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
-
- DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
- DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
-
- if (machine_is_h1940()) {
- void *base = phys_to_virt(H1940_SUSPEND_CHECK);
- unsigned long ptr;
- unsigned long calc = 0;
-
- /* generate check for the bootloader to check on resume */
-
- for (ptr = 0; ptr < 0x40000; ptr += 0x400)
- calc += __raw_readl(base+ptr);
-
- __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
- }
-
- /* the RX3715 uses similar code and the same H1940 and the
- * same offsets for resume and checksum pointers */
-
- if (machine_is_rx3715()) {
- void *base = phys_to_virt(H1940_SUSPEND_CHECK);
- unsigned long ptr;
- unsigned long calc = 0;
-
- /* generate check for the bootloader to check on resume */
-
- for (ptr = 0; ptr < 0x40000; ptr += 0x4)
- calc += __raw_readl(base+ptr);
-
- __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
- }
-
- if ( machine_is_aml_m5900() )
- s3c2410_gpio_setpin(S3C2410_GPF2, 1);
-
-}
-
-static int s3c2410_pm_resume(struct sys_device *dev)
-{
- unsigned long tmp;
-
- /* unset the return-from-sleep flag, to ensure reset */
-
- tmp = __raw_readl(S3C2410_GSTATUS2);
- tmp &= S3C2410_GSTATUS2_OFFRESET;
- __raw_writel(tmp, S3C2410_GSTATUS2);
-
- if ( machine_is_aml_m5900() )
- s3c2410_gpio_setpin(S3C2410_GPF2, 0);
-
- return 0;
-}
-
-static int s3c2410_pm_add(struct sys_device *dev)
-{
- pm_cpu_prep = s3c2410_pm_prepare;
- pm_cpu_sleep = s3c2410_cpu_suspend;
-
- return 0;
-}
-
-#if defined(CONFIG_CPU_S3C2410)
-static struct sysdev_driver s3c2410_pm_driver = {
- .add = s3c2410_pm_add,
- .resume = s3c2410_pm_resume,
-};
-
-/* register ourselves */
-
-static int __init s3c2410_pm_drvinit(void)
-{
- return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
-}
-
-arch_initcall(s3c2410_pm_drvinit);
-#endif
-
-#if defined(CONFIG_CPU_S3C2440)
-static struct sysdev_driver s3c2440_pm_driver = {
- .add = s3c2410_pm_add,
- .resume = s3c2410_pm_resume,
-};
-
-static int __init s3c2440_pm_drvinit(void)
-{
- return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
-}
-
-arch_initcall(s3c2440_pm_drvinit);
-#endif
-
-#if defined(CONFIG_CPU_S3C2442)
-static struct sysdev_driver s3c2442_pm_driver = {
- .add = s3c2410_pm_add,
- .resume = s3c2410_pm_resume,
-};
-
-static int __init s3c2442_pm_drvinit(void)
-{
- return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
-}
-
-arch_initcall(s3c2442_pm_drvinit);
-#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-sleep.S b/arch/arm/mach-s3c2410/s3c2410-sleep.S
deleted file mode 100644
index 9179a102458..00000000000
--- a/arch/arm/mach-s3c2410/s3c2410-sleep.S
+++ /dev/null
@@ -1,68 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
- *
- * Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 Power Manager (Suspend-To-RAM) support
- *
- * Based on PXA/SA1100 sleep code by:
- * Nicolas Pitre, (c) 2002 Monta Vista Software Inc
- * Cliff Brake, (c) 2001
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/hardware.h>
-#include <asm/arch/map.h>
-
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-serial.h>
-
- /* s3c2410_cpu_suspend
- *
- * put the cpu into sleep mode
- */
-
-ENTRY(s3c2410_cpu_suspend)
- @@ prepare cpu to sleep
-
- ldr r4, =S3C2410_REFRESH
- ldr r5, =S3C24XX_MISCCR
- ldr r6, =S3C2410_CLKCON
- ldr r7, [ r4 ] @ get REFRESH (and ensure in TLB)
- ldr r8, [ r5 ] @ get MISCCR (and ensure in TLB)
- ldr r9, [ r6 ] @ get CLKCON (and ensure in TLB)
-
- orr r7, r7, #S3C2410_REFRESH_SELF @ SDRAM sleep command
- orr r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
- orr r9, r9, #S3C2410_CLKCON_POWER @ power down command
-
- teq pc, #0 @ first as a trial-run to load cache
- bl s3c2410_do_sleep
- teq r0, r0 @ now do it for real
- b s3c2410_do_sleep @
-
- @@ align next bit of code to cache line
- .align 8
-s3c2410_do_sleep:
- streq r7, [ r4 ] @ SDRAM sleep command
- streq r8, [ r5 ] @ SDRAM power-down config
- streq r9, [ r6 ] @ CPU sleep
-1: beq 1b
- mov pc, r14
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index 4cdc0d70c19..1a86a980375 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -31,10 +31,10 @@
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-serial.h>
-#include "s3c2410.h"
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
/* Initial IO mappings */
@@ -110,7 +110,7 @@ static struct sys_device s3c2410_sysdev = {
/* need to register class before we actually register the device, and
* we also need to ensure that it has been initialised before any of the
- * drivers even try to use it (even if not on an s3c2440 based system)
+ * drivers even try to use it (even if not on an s3c2410 based system)
* as a driver which may support both 2410 and 2440 may try and use it.
*/
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
index 2018c2e1dcc..637aaba6539 100644
--- a/arch/arm/mach-s3c2410/sleep.S
+++ b/arch/arm/mach-s3c2410/sleep.S
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/sleep.S
+/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -34,126 +34,35 @@
#include <asm/arch/regs-mem.h>
#include <asm/arch/regs-serial.h>
-/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
- * reset the UART configuration, only enable if you really need this!
-*/
-//#define CONFIG_DEBUG_RESUME
-
- .text
-
- /* s3c2410_cpu_save
- *
- * save enough of the CPU state to allow us to re-start
- * pm.c code. as we store items like the sp/lr, we will
- * end up returning from this function when the cpu resumes
- * so the return value is set to mark this.
- *
- * This arangement means we avoid having to flush the cache
- * from this code.
- *
- * entry:
- * r0 = pointer to save block
- *
- * exit:
- * r0 = 0 => we stored everything
- * 1 => resumed from sleep
- */
-
-ENTRY(s3c2410_cpu_save)
- stmfd sp!, { r4 - r12, lr }
-
- @@ store co-processor registers
-
- mrc p15, 0, r4, c15, c1, 0 @ CP access register
- mrc p15, 0, r5, c13, c0, 0 @ PID
- mrc p15, 0, r6, c3, c0, 0 @ Domain ID
- mrc p15, 0, r7, c2, c0, 0 @ translation table base address
- mrc p15, 0, r8, c1, c0, 0 @ control register
-
- stmia r0, { r4 - r13 }
-
- mov r0, #0
- ldmfd sp, { r4 - r12, pc }
-
- @@ return to the caller, after having the MMU
- @@ turned on, this restores the last bits from the
- @@ stack
-resume_with_mmu:
- mov r0, #1
- ldmfd sp!, { r4 - r12, pc }
-
- .ltorg
-
- @@ the next bits sit in the .data segment, even though they
- @@ happen to be code... the s3c2410_sleep_save_phys needs to be
- @@ accessed by the resume code before it can restore the MMU.
- @@ This means that the variable has to be close enough for the
- @@ code to read it... since the .text segment needs to be RO,
- @@ the data segment can be the only place to put this code.
-
- .data
-
- .global s3c2410_sleep_save_phys
-s3c2410_sleep_save_phys:
- .word 0
-
- /* s3c2410_cpu_resume
+ /* s3c2410_cpu_suspend
*
- * resume code entry for bootloader to call
- *
- * we must put this code here in the data segment as we have no
- * other way of restoring the stack pointer after sleep, and we
- * must not write to the code segment (code is read-only)
+ * put the cpu into sleep mode
*/
-ENTRY(s3c2410_cpu_resume)
- mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
- msr cpsr_c, r0
-
- @@ load UART to allow us to print the two characters for
- @@ resume debug
-
- mov r2, #S3C24XX_PA_UART & 0xff000000
- orr r2, r2, #S3C24XX_PA_UART & 0xff000
-
-#if 0
- /* SMDK2440 LED set */
- mov r14, #S3C24XX_PA_GPIO
- ldr r12, [ r14, #0x54 ]
- bic r12, r12, #3<<4
- orr r12, r12, #1<<7
- str r12, [ r14, #0x54 ]
-#endif
-
-#ifdef CONFIG_DEBUG_RESUME
- mov r3, #'L'
- strb r3, [ r2, #S3C2410_UTXH ]
-1001:
- ldrb r14, [ r3, #S3C2410_UTRSTAT ]
- tst r14, #S3C2410_UTRSTAT_TXE
- beq 1001b
-#endif /* CONFIG_DEBUG_RESUME */
-
- mov r1, #0
- mcr p15, 0, r1, c8, c7, 0 @@ invalidate I & D TLBs
- mcr p15, 0, r1, c7, c7, 0 @@ invalidate I & D caches
-
- ldr r0, s3c2410_sleep_save_phys @ address of restore block
- ldmia r0, { r4 - r13 }
-
- mcr p15, 0, r4, c15, c1, 0 @ CP access register
- mcr p15, 0, r5, c13, c0, 0 @ PID
- mcr p15, 0, r6, c3, c0, 0 @ Domain ID
- mcr p15, 0, r7, c2, c0, 0 @ translation table base
-
-#ifdef CONFIG_DEBUG_RESUME
- mov r3, #'R'
- strb r3, [ r2, #S3C2410_UTXH ]
-#endif
-
- ldr r2, =resume_with_mmu
- mcr p15, 0, r8, c1, c0, 0 @ turn on MMU, etc
- nop @ second-to-last before mmu
- mov pc, r2 @ go back to virtual address
-
- .ltorg
+ENTRY(s3c2410_cpu_suspend)
+ @@ prepare cpu to sleep
+
+ ldr r4, =S3C2410_REFRESH
+ ldr r5, =S3C24XX_MISCCR
+ ldr r6, =S3C2410_CLKCON
+ ldr r7, [ r4 ] @ get REFRESH (and ensure in TLB)
+ ldr r8, [ r5 ] @ get MISCCR (and ensure in TLB)
+ ldr r9, [ r6 ] @ get CLKCON (and ensure in TLB)
+
+ orr r7, r7, #S3C2410_REFRESH_SELF @ SDRAM sleep command
+ orr r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
+ orr r9, r9, #S3C2410_CLKCON_POWER @ power down command
+
+ teq pc, #0 @ first as a trial-run to load cache
+ bl s3c2410_do_sleep
+ teq r0, r0 @ now do it for real
+ b s3c2410_do_sleep @
+
+ @@ align next bit of code to cache line
+ .align 5
+s3c2410_do_sleep:
+ streq r7, [ r4 ] @ SDRAM sleep command
+ streq r8, [ r5 ] @ SDRAM power-down config
+ streq r9, [ r6 ] @ CPU sleep
+1: beq 1b
+ mov pc, r14
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
index 22b0e1cdd4b..bcd562ac1d3 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.c
+++ b/arch/arm/mach-s3c2410/usb-simtec.c
@@ -35,7 +35,7 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include "devs.h"
+#include <asm/plat-s3c24xx/devs.h>
#include "usb-simtec.h"
/* control power and monitor over-current events on various Simtec
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
new file mode 100644
index 00000000000..befc5fdbb61
--- /dev/null
+++ b/arch/arm/mach-s3c2412/Kconfig
@@ -0,0 +1,58 @@
+# arch/arm/mach-s3c2412/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2412
+ bool
+ depends on ARCH_S3C2410
+ select S3C2412_PM if PM
+ select S3C2412_DMA if S3C2410_DMA
+ help
+ Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
+
+config CPU_S3C2412_ONLY
+ bool
+ depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
+ !CPU_S3C2440 && !CPU_S3C2442 && !CPU_S3C2443 && CPU_S3C2412
+ default y if CPU_S3C2412
+
+config S3C2412_DMA
+ bool
+ depends on CPU_S3C2412
+ help
+ Internal config node for S3C2412 DMA support
+
+config S3C2412_PM
+ bool
+ help
+ Internal config node to apply S3C2412 power management
+
+
+menu "S3C2412 Machines"
+
+config MACH_SMDK2413
+ bool "SMDK2413"
+ select CPU_S3C2412
+ select MACH_S3C2413
+ select MACH_SMDK
+ help
+ Say Y here if you are using an SMDK2413
+
+config MACH_S3C2413
+ bool
+ help
+ Internal node for S3C2413 version of SMDK2413, so that
+ machine_is_s3c2413() will work when MACH_SMDK2413 is
+ selected
+
+config MACH_VSTMS
+ bool "VMSTMS"
+ select CPU_S3C2412
+ help
+ Say Y here if you are using an VSTMS board
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile
new file mode 100644
index 00000000000..f8e011691b3
--- /dev/null
+++ b/arch/arm/mach-s3c2412/Makefile
@@ -0,0 +1,21 @@
+# arch/arm/mach-s3c2412/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_CPU_S3C2412) += s3c2412.o
+obj-$(CONFIG_CPU_S3C2412) += irq.o
+obj-$(CONFIG_CPU_S3C2412) += clock.o
+obj-$(CONFIG_S3C2412_DMA) += dma.o
+obj-$(CONFIG_S3C2412_PM) += pm.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_SMDK2413) += mach-smdk2413.o
+obj-$(CONFIG_MACH_VSTMS) += mach-vstms.o
diff --git a/arch/arm/mach-s3c2410/s3c2412-clock.c b/arch/arm/mach-s3c2412/clock.c
index 8f94ad83901..6a8e4448770 100644
--- a/arch/arm/mach-s3c2410/s3c2412-clock.c
+++ b/arch/arm/mach-s3c2412/clock.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c
+/* linux/arch/arm/mach-s3c2412/clock.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -41,9 +41,9 @@
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-gpio.h>
-#include "s3c2412.h"
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
/* We currently have to assume that the system is running
* from the XTPll input, and that all ***REFCLKs are being
diff --git a/arch/arm/mach-s3c2410/s3c2412-dma.c b/arch/arm/mach-s3c2412/dma.c
index 138f726ac6b..d0f4695c09d 100644
--- a/arch/arm/mach-s3c2410/s3c2412-dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-dma.c
+/* linux/arch/arm/mach-s3c2412/dma.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -21,8 +21,8 @@
#include <asm/arch/dma.h>
#include <asm/io.h>
-#include "dma.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/dma.h>
+#include <asm/plat-s3c24xx/cpu.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
@@ -146,6 +146,7 @@ static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
static int s3c2412_dma_add(struct sys_device *sysdev)
{
+ s3c2410_dma_init();
return s3c24xx_dma_init_map(&s3c2412_dma_sel);
}
diff --git a/arch/arm/mach-s3c2410/s3c2412-irq.c b/arch/arm/mach-s3c2412/irq.c
index ffcc30b23a8..e89dbdcb1b7 100644
--- a/arch/arm/mach-s3c2410/s3c2412-irq.c
+++ b/arch/arm/mach-s3c2412/irq.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2412/s3c2412-irq.c
+/* linux/arch/arm/mach-s3c2412/irq.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
#include <asm/arch/regs-irq.h>
#include <asm/arch/regs-gpio.h>
-#include "cpu.h"
-#include "irq.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/irq.h>
+#include <asm/plat-s3c24xx/pm.h>
/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
* having them turn up in both the INT* and the EINT* registers. Whilst
diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c
index 4f89abd7a6d..b5befce6c8d 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2413.c
+++ b/arch/arm/mach-s3c2412/mach-smdk2413.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c
+/* linux/arch/arm/mach-s3c2412/mach-smdk2413.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -37,15 +37,16 @@
#include <asm/arch/regs-lcd.h>
#include <asm/arch/idle.h>
+#include <asm/arch/udc.h>
#include <asm/arch/fb.h>
-#include "s3c2410.h"
-#include "s3c2412.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
-#include "common-smdk.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
static struct map_desc smdk2413_iodesc[] __initdata = {
};
@@ -75,12 +76,38 @@ static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
}
};
+static void smdk2413_udc_pullup(enum s3c2410_udc_cmd_e cmd)
+{
+ printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
+
+ switch (cmd)
+ {
+ case S3C2410_UDC_P_ENABLE :
+ s3c2410_gpio_setpin(S3C2410_GPF2, 1);
+ break;
+ case S3C2410_UDC_P_DISABLE :
+ s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+ break;
+ case S3C2410_UDC_P_RESET :
+ break;
+ default:
+ break;
+ }
+}
+
+
+static struct s3c2410_udc_mach_info smdk2413_udc_cfg __initdata = {
+ .udc_command = smdk2413_udc_pullup,
+};
+
+
static struct platform_device *smdk2413_devices[] __initdata = {
&s3c_device_usb,
//&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
+ &s3c_device_usbgadget,
};
static struct s3c24xx_board smdk2413_board __initdata = {
@@ -109,7 +136,19 @@ static void __init smdk2413_map_io(void)
}
static void __init smdk2413_machine_init(void)
-{
+{ /* Turn off suspend on both USB ports, and switch the
+ * selectable USB port to USB device mode. */
+
+ s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+ s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPIO_OUTPUT);
+
+ s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
+ S3C2410_MISCCR_USBSUSPND0 |
+ S3C2410_MISCCR_USBSUSPND1, 0x0);
+
+
+ s3c24xx_udc_set_platdata(&smdk2413_udc_cfg);
+
smdk_machine_init();
}
@@ -126,6 +165,19 @@ MACHINE_START(S3C2413, "S3C2413")
.timer = &s3c24xx_timer,
MACHINE_END
+MACHINE_START(SMDK2412, "SMDK2412")
+ /* Maintainer: Ben Dooks <ben@fluff.org> */
+ .phys_io = S3C2410_PA_UART,
+ .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+ .boot_params = S3C2410_SDRAM_PA + 0x100,
+
+ .fixup = smdk2413_fixup,
+ .init_irq = s3c24xx_init_irq,
+ .map_io = smdk2413_map_io,
+ .init_machine = smdk2413_machine_init,
+ .timer = &s3c24xx_timer,
+MACHINE_END
+
MACHINE_START(SMDK2413, "SMDK2413")
/* Maintainer: Ben Dooks <ben@fluff.org> */
.phys_io = S3C2410_PA_UART,
diff --git a/arch/arm/mach-s3c2410/mach-vstms.c b/arch/arm/mach-s3c2412/mach-vstms.c
index 0360e1055bc..4231b549d79 100644
--- a/arch/arm/mach-s3c2410/mach-vstms.c
+++ b/arch/arm/mach-s3c2412/mach-vstms.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-vstms.c
+/* linux/arch/arm/mach-s3c2412/mach-vstms.c
*
* (C) 2006 Thomas Gleixner <tglx@linutronix.de>
*
@@ -28,7 +28,6 @@
#include <asm/mach/irq.h>
#include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
#include <asm/setup.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -43,11 +42,11 @@
#include <asm/arch/nand.h>
-#include "s3c2410.h"
-#include "s3c2412.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
static struct map_desc vstms_iodesc[] __initdata = {
diff --git a/arch/arm/mach-s3c2410/s3c2412-pm.c b/arch/arm/mach-s3c2412/pm.c
index 19b63322d25..8988dac388a 100644
--- a/arch/arm/mach-s3c2410/s3c2412-pm.c
+++ b/arch/arm/mach-s3c2412/pm.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-pm.c
+/* linux/arch/arm/mach-s3c2412/pm.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -28,10 +28,10 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-dsc.h>
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
-#include "s3c2412.h"
+#include <asm/plat-s3c24xx/s3c2412.h>
static void s3c2412_cpu_suspend(void)
{
diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
index 2f651a811ec..aafe0bc593f 100644
--- a/arch/arm/mach-s3c2410/s3c2412.c
+++ b/arch/arm/mach-s3c2412/s3c2412.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412.c
+/* linux/arch/arm/mach-s3c2412/s3c2412.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -38,11 +38,11 @@
#include <asm/arch/regs-gpioj.h>
#include <asm/arch/regs-dsc.h>
-#include "s3c2412.h"
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/pm.h>
#ifndef CONFIG_CPU_S3C2412_ONLY
void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
new file mode 100644
index 00000000000..e3bfda098c0
--- /dev/null
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -0,0 +1,71 @@
+# arch/arm/mach-s3c2440/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2440
+ bool
+ depends on ARCH_S3C2410
+ select S3C2410_CLOCK
+ select S3C2410_PM if PM
+ select S3C2410_GPIO
+ select S3C2440_DMA if S3C2410_DMA
+ select CPU_S3C244X
+ help
+ Support for S3C2440 Samsung Mobile CPU based systems.
+
+config S3C2440_DMA
+ bool
+ depends on ARCH_S3C2410 && CPU_S3C24405B
+ help
+ Support for S3C2440 specific DMA code5A
+
+
+menu "S3C2440 Machines"
+
+config MACH_ANUBIS
+ bool "Simtec Electronics ANUBIS"
+ select CPU_S3C2440
+ select PM_SIMTEC if PM
+ help
+ Say Y here if you are using the Simtec Electronics ANUBIS
+ development system
+
+config MACH_OSIRIS
+ bool "Simtec IM2440D20 (OSIRIS) module"
+ select CPU_S3C2440
+ select PM_SIMTEC if PM
+ help
+ Say Y here if you are using the Simtec IM2440D20 module, also
+ known as the Osiris.
+
+config MACH_RX3715
+ bool "HP iPAQ rx3715"
+ select CPU_S3C2440
+ select PM_H1940 if PM
+ help
+ Say Y here if you are using the HP iPAQ rx3715.
+
+config ARCH_S3C2440
+ bool "SMDK2440"
+ select CPU_S3C2440
+ select MACH_SMDK
+ help
+ Say Y here if you are using the SMDK2440.
+
+config MACH_NEXCODER_2440
+ bool "NexVision NEXCODER 2440 Light Board"
+ select CPU_S3C2440
+ help
+ Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
+
+config SMDK2440_CPU2440
+ bool "SMDK2440 with S3C2440 CPU module"
+ depends on ARCH_S3C2440
+ default y if ARCH_S3C2440
+ select CPU_S3C2440
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
new file mode 100644
index 00000000000..c81ed6248dc
--- /dev/null
+++ b/arch/arm/mach-s3c2440/Makefile
@@ -0,0 +1,23 @@
+# arch/arm/mach-s3c2440/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_CPU_S3C2440) += s3c2440.o dsc.o
+obj-$(CONFIG_CPU_S3C2440) += irq.o
+obj-$(CONFIG_CPU_S3C2440) += clock.o
+obj-$(CONFIG_S3C2440_DMA) += dma.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o
+obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o
+obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
+obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
+obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2440/clock.c
index ba13c1d079d..79e2ea4adaf 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2440/clock.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-clock.c
+/* linux/arch/arm/mach-s3c2440/clock.c
*
* Copyright (c) 2004-2005 Simtec Electronics
* http://armlinux.simtec.co.uk/
@@ -41,8 +41,8 @@
#include <asm/arch/regs-clock.h>
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
/* S3C2440 extended clock support */
diff --git a/arch/arm/mach-s3c2410/s3c2440-dma.c b/arch/arm/mach-s3c2440/dma.c
index 47b861b9443..cd035a3ec87 100644
--- a/arch/arm/mach-s3c2410/s3c2440-dma.c
+++ b/arch/arm/mach-s3c2440/dma.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-dma.c
+/* linux/arch/arm/mach-s3c2440/dma.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -19,9 +19,9 @@
#include <asm/dma.h>
#include <asm/arch/dma.h>
-#include "dma.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/dma.h>
+#include <asm/plat-s3c24xx/cpu.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
@@ -147,8 +147,53 @@ static struct s3c24xx_dma_selection __initdata s3c2440_dma_sel = {
.map_size = ARRAY_SIZE(s3c2440_dma_mappings),
};
+static struct s3c24xx_dma_order __initdata s3c2440_dma_order = {
+ .channels = {
+ [DMACH_SDI] = {
+ .list = {
+ [0] = 3 | DMA_CH_VALID,
+ [1] = 2 | DMA_CH_VALID,
+ [2] = 1 | DMA_CH_VALID,
+ [3] = 0 | DMA_CH_VALID,
+ },
+ },
+ [DMACH_I2S_IN] = {
+ .list = {
+ [0] = 1 | DMA_CH_VALID,
+ [1] = 2 | DMA_CH_VALID,
+ },
+ },
+ [DMACH_I2S_OUT] = {
+ .list = {
+ [0] = 2 | DMA_CH_VALID,
+ [1] = 1 | DMA_CH_VALID,
+ },
+ },
+ [DMACH_PCM_IN] = {
+ .list = {
+ [0] = 2 | DMA_CH_VALID,
+ [1] = 1 | DMA_CH_VALID,
+ },
+ },
+ [DMACH_PCM_OUT] = {
+ .list = {
+ [0] = 1 | DMA_CH_VALID,
+ [1] = 3 | DMA_CH_VALID,
+ },
+ },
+ [DMACH_MIC_IN] = {
+ .list = {
+ [0] = 3 | DMA_CH_VALID,
+ [1] = 2 | DMA_CH_VALID,
+ },
+ },
+ },
+};
+
static int s3c2440_dma_add(struct sys_device *sysdev)
{
+ s3c2410_dma_init();
+ s3c24xx_dma_order_set(&s3c2440_dma_order);
return s3c24xx_dma_init_map(&s3c2440_dma_sel);
}
diff --git a/arch/arm/mach-s3c2410/s3c2440-dsc.c b/arch/arm/mach-s3c2440/dsc.c
index c92ea66ba45..2995ff5681b 100644
--- a/arch/arm/mach-s3c2410/s3c2440-dsc.c
+++ b/arch/arm/mach-s3c2440/dsc.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-dsc.c
+/* linux/arch/arm/mach-s3c2440/dsc.c
*
* Copyright (c) 2004-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -27,8 +27,8 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-dsc.h>
-#include "cpu.h"
-#include "s3c2440.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
int s3c2440_set_dsc(unsigned int pin, unsigned int value)
{
diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2440/irq.c
index 1ba19b27ab0..1069d13d8c5 100644
--- a/arch/arm/mach-s3c2410/s3c2440-irq.c
+++ b/arch/arm/mach-s3c2440/irq.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c
+/* linux/arch/arm/mach-s3c2440/irq.c
*
* Copyright (c) 2003,2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
#include <asm/arch/regs-irq.h>
#include <asm/arch/regs-gpio.h>
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
/* WDT/AC97 */
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index 0fad0c2fe07..3f0288eb1ed 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-anubis.c
+/* linux/arch/arm/mach-s3c2440/mach-anubis.c
*
* Copyright (c) 2003-2005 Simtec Electronics
* http://armlinux.simtec.co.uk/
@@ -42,9 +42,9 @@
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
#define COPYRIGHT ", (c) 2005 Simtec Electronics"
diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2440/mach-nexcoder.c
index d6dfdad8c90..6d551d88330 100644
--- a/arch/arm/mach-s3c2410/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2440/mach-nexcoder.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-nexcoder.c
+/* linux/arch/arm/mach-s3c2440/mach-nexcoder.c
*
* Copyright (c) 2004 Nex Vision
* Guillaume GOURAT <guillaume.gourat@nexvision.tv>
@@ -38,11 +38,11 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-serial.h>
-#include "s3c2410.h"
-#include "s3c2440.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
static struct map_desc nexcoder_iodesc[] __initdata = {
/* nothing here yet */
diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index 37b40850c9b..2ed8e51f20c 100644
--- a/arch/arm/mach-s3c2410/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-osiris.c
+/* linux/arch/arm/mach-s3c2440/mach-osiris.c
*
* Copyright (c) 2005 Simtec Electronics
* http://armlinux.simtec.co.uk/
@@ -41,9 +41,9 @@
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
/* onboard perihpheral map */
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index ecbcdf79d73..480ccde63fb 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-rx3715.c
+/* linux/arch/arm/mach-s3c2440/mach-rx3715.c
*
* Copyright (c) 2003,2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -33,7 +33,6 @@
#include <asm/mach/irq.h>
#include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
@@ -46,10 +45,10 @@
#include <asm/arch/nand.h>
#include <asm/arch/fb.h>
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
static struct map_desc rx3715_iodesc[] __initdata = {
/* dump ISA space somewhere unused */
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c
index 2b61f4ed1da..c17eb5b1f6b 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2440/mach-smdk2440.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-smdk2440.c
+/* linux/arch/arm/mach-s3c2440/mach-smdk2440.c
*
* Copyright (c) 2004,2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -27,12 +27,10 @@
#include <asm/mach/irq.h>
#include <asm/hardware.h>
-#include <asm/hardware/iomd.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
-//#include <asm/debug-ll.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-lcd.h>
@@ -40,13 +38,13 @@
#include <asm/arch/idle.h>
#include <asm/arch/fb.h>
-#include "s3c2410.h"
-#include "s3c2440.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
-#include "common-smdk.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
static struct map_desc smdk2440_iodesc[] __initdata = {
/* ISA IO Space map (memory space selected by A24) */
@@ -144,6 +142,7 @@ static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {
#endif
.lpcsel = ((0xCE6) & ~7) | 1<<4,
+ .type = S3C2410_LCDCON1_TFT16BPP,
.width = 240,
.height = 320,
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2440/s3c2440.c
index 344eb27cca4..90e1da61fbc 100644
--- a/arch/arm/mach-s3c2410/s3c2440.c
+++ b/arch/arm/mach-s3c2440/s3c2440.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440.c
+/* linux/arch/arm/mach-s3c2440/s3c2440.c
*
* Copyright (c) 2004-2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -29,9 +29,9 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include "s3c2440.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
static struct sys_device s3c2440_sysdev = {
.cls = &s3c2440_sysclass,
diff --git a/arch/arm/mach-s3c2442/Kconfig b/arch/arm/mach-s3c2442/Kconfig
new file mode 100644
index 00000000000..bf8d87abfab
--- /dev/null
+++ b/arch/arm/mach-s3c2442/Kconfig
@@ -0,0 +1,27 @@
+# arch/arm/mach-s3c2442/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2442
+ bool
+ depends on ARCH_S3C2420
+ select S3C2410_CLOCK
+ select S3C2410_GPIO
+ select S3C2410_PM if PM
+ select CPU_S3C244X
+ help
+ Support for S3C2442 Samsung Mobile CPU based systems.
+
+
+menu "S3C2442 Machines"
+
+config SMDK2440_CPU2442
+ bool "SMDM2440 with S3C2442 CPU module"
+ depends on ARCH_S3C2440
+ select CPU_S3C2442
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2442/Makefile b/arch/arm/mach-s3c2442/Makefile
new file mode 100644
index 00000000000..2a909c6c579
--- /dev/null
+++ b/arch/arm/mach-s3c2442/Makefile
@@ -0,0 +1,16 @@
+# arch/arm/mach-s3c2442/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_CPU_S3C2442) += s3c2442.o
+obj-$(CONFIG_CPU_S3C2442) += clock.o
+
+# Machine support
+
diff --git a/arch/arm/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2442/clock.c
index 4e292ca7c9b..5b9e830ac4d 100644
--- a/arch/arm/mach-s3c2410/s3c2442-clock.c
+++ b/arch/arm/mach-s3c2442/clock.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2442-clock.c
+/* linux/arch/arm/mach-s3c2442/clock.c
*
* Copyright (c) 2004-2005 Simtec Electronics
* http://armlinux.simtec.co.uk/
@@ -41,8 +41,8 @@
#include <asm/arch/regs-clock.h>
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
/* S3C2442 extended clock support */
diff --git a/arch/arm/mach-s3c2410/s3c2442.c b/arch/arm/mach-s3c2442/s3c2442.c
index 428732ee68c..fbf8264249d 100644
--- a/arch/arm/mach-s3c2410/s3c2442.c
+++ b/arch/arm/mach-s3c2442/s3c2442.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2442.c
+/* linux/arch/arm/mach-s3c2442/s3c2442.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -19,8 +19,8 @@
#include <linux/serial_core.h>
#include <linux/sysdev.h>
-#include "s3c2442.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2442.h>
+#include <asm/plat-s3c24xx/cpu.h>
static struct sys_device s3c2442_sysdev = {
.cls = &s3c2442_sysclass,
diff --git a/arch/arm/mach-s3c2443/Kconfig b/arch/arm/mach-s3c2443/Kconfig
new file mode 100644
index 00000000000..c649bb2e7ce
--- /dev/null
+++ b/arch/arm/mach-s3c2443/Kconfig
@@ -0,0 +1,29 @@
+# arch/arm/mach-s3c2443/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2443
+ bool
+ depends on ARCH_S3C2410
+ select S3C2443_DMA if S3C2410_DMA
+ help
+ Support for the S3C2443 SoC from the S3C24XX line
+
+config S3C2443_DMA
+ bool
+ depends on CPU_S3C2443
+ help
+ Internal config node for S3C2443 DMA support
+
+menu "S3C2443 Machines"
+
+config MACH_SMDK2443
+ bool "SMDK2443"
+ select CPU_S3C2443
+ select MACH_SMDK
+ help
+ Say Y here if you are using an SMDK2443
+
+endmenu
diff --git a/arch/arm/mach-s3c2443/Makefile b/arch/arm/mach-s3c2443/Makefile
new file mode 100644
index 00000000000..d1843c9eb8b
--- /dev/null
+++ b/arch/arm/mach-s3c2443/Makefile
@@ -0,0 +1,20 @@
+# arch/arm/mach-s3c2443/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-$(CONFIG_CPU_S3C2443) += s3c2443.o
+obj-$(CONFIG_CPU_S3C2443) += irq.o
+obj-$(CONFIG_CPU_S3C2443) += clock.o
+
+obj-$(CONFIG_S3C2443_DMA) += dma.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_SMDK2443) += mach-smdk2443.o
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
new file mode 100644
index 00000000000..dd2272fb113
--- /dev/null
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -0,0 +1,1007 @@
+/* linux/arch/arm/mach-s3c2443/clock.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2443 Clock control support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/map.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-s3c2443-clock.h>
+
+#include <asm/plat-s3c24xx/s3c2443.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* We currently have to assume that the system is running
+ * from the XTPll input, and that all ***REFCLKs are being
+ * fed from it, as we cannot read the state of OM[4] from
+ * software.
+ *
+ * It would be possible for each board initialisation to
+ * set the correct muxing at initialisation
+*/
+
+static int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
+{
+ unsigned int clocks = clk->ctrlbit;
+ unsigned long clkcon;
+
+ clkcon = __raw_readl(S3C2443_HCLKCON);
+
+ if (enable)
+ clkcon |= clocks;
+ else
+ clkcon &= ~clocks;
+
+ __raw_writel(clkcon, S3C2443_HCLKCON);
+
+ return 0;
+}
+
+static int s3c2443_clkcon_enable_p(struct clk *clk, int enable)
+{
+ unsigned int clocks = clk->ctrlbit;
+ unsigned long clkcon;
+
+ clkcon = __raw_readl(S3C2443_PCLKCON);
+
+ if (enable)
+ clkcon |= clocks;
+ else
+ clkcon &= ~clocks;
+
+ __raw_writel(clkcon, S3C2443_HCLKCON);
+
+ return 0;
+}
+
+static int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
+{
+ unsigned int clocks = clk->ctrlbit;
+ unsigned long clkcon;
+
+ clkcon = __raw_readl(S3C2443_SCLKCON);
+
+ if (enable)
+ clkcon |= clocks;
+ else
+ clkcon &= ~clocks;
+
+ __raw_writel(clkcon, S3C2443_SCLKCON);
+
+ return 0;
+}
+
+static unsigned long s3c2443_roundrate_clksrc(struct clk *clk,
+ unsigned long rate,
+ unsigned int max)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ int div;
+
+ if (rate > parent_rate)
+ return parent_rate;
+
+ /* note, we remove the +/- 1 calculations as they cancel out */
+
+ div = (rate / parent_rate);
+
+ if (div < 1)
+ div = 1;
+ else if (div > max)
+ div = max;
+
+ return parent_rate / div;
+}
+
+static unsigned long s3c2443_roundrate_clksrc4(struct clk *clk,
+ unsigned long rate)
+{
+ return s3c2443_roundrate_clksrc(clk, rate, 4);
+}
+
+static unsigned long s3c2443_roundrate_clksrc16(struct clk *clk,
+ unsigned long rate)
+{
+ return s3c2443_roundrate_clksrc(clk, rate, 16);
+}
+
+static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk,
+ unsigned long rate)
+{
+ return s3c2443_roundrate_clksrc(clk, rate, 256);
+}
+
+/* clock selections */
+
+/* CPU EXTCLK input */
+static struct clk clk_ext = {
+ .name = "ext",
+ .id = -1,
+};
+
+static struct clk clk_mpllref = {
+ .name = "mpllref",
+ .parent = &clk_xtal,
+ .id = -1,
+};
+
+#if 0
+static struct clk clk_mpll = {
+ .name = "mpll",
+ .parent = &clk_mpllref,
+ .id = -1,
+};
+#endif
+
+static struct clk clk_epllref;
+
+static struct clk clk_epll = {
+ .name = "epll",
+ .parent = &clk_epllref,
+ .id = -1,
+};
+
+static struct clk clk_i2s_ext = {
+ .name = "i2s-ext",
+ .id = -1,
+};
+
+static int s3c2443_setparent_epllref(struct clk *clk, struct clk *parent)
+{
+ unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+ clksrc &= ~S3C2443_CLKSRC_EPLLREF_MASK;
+
+ if (parent == &clk_xtal)
+ clksrc |= S3C2443_CLKSRC_EPLLREF_XTAL;
+ else if (parent == &clk_ext)
+ clksrc |= S3C2443_CLKSRC_EPLLREF_EXTCLK;
+ else if (parent != &clk_mpllref)
+ return -EINVAL;
+
+ __raw_writel(clksrc, S3C2443_CLKSRC);
+ clk->parent = parent;
+
+ return 0;
+}
+
+static struct clk clk_epllref = {
+ .name = "epllref",
+ .id = -1,
+ .set_parent = s3c2443_setparent_epllref,
+};
+
+static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long div = __raw_readl(S3C2443_CLKDIV0);
+
+ div &= S3C2443_CLKDIV0_EXTDIV_MASK;
+ div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1); /* x2 */
+
+ return parent_rate / (div + 1);
+}
+
+static struct clk clk_mdivclk = {
+ .name = "mdivclk",
+ .parent = &clk_mpllref,
+ .id = -1,
+ .get_rate = s3c2443_getrate_mdivclk,
+};
+
+
+static int s3c2443_setparent_msysclk(struct clk *clk, struct clk *parent)
+{
+ unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+ clksrc &= ~(S3C2443_CLKSRC_MSYSCLK_MPLL |
+ S3C2443_CLKSRC_EXTCLK_DIV);
+
+ if (parent == &clk_mpll)
+ clksrc |= S3C2443_CLKSRC_MSYSCLK_MPLL;
+ else if (parent == &clk_mdivclk)
+ clksrc |= S3C2443_CLKSRC_EXTCLK_DIV;
+ else if (parent != &clk_mpllref)
+ return -EINVAL;
+
+ __raw_writel(clksrc, S3C2443_CLKSRC);
+ clk->parent = parent;
+
+ return 0;
+}
+
+static struct clk clk_msysclk = {
+ .name = "msysclk",
+ .parent = &clk_xtal,
+ .id = -1,
+ .set_parent = s3c2443_setparent_msysclk,
+};
+
+
+/* esysclk
+ *
+ * this is sourced from either the EPLL or the EPLLref clock
+*/
+
+static int s3c2443_setparent_esysclk(struct clk *clk, struct clk *parent)
+{
+ unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+ if (parent == &clk_epll)
+ clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL;
+ else if (parent == &clk_epllref)
+ clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL;
+ else
+ return -EINVAL;
+
+ __raw_writel(clksrc, S3C2443_CLKSRC);
+ clk->parent = parent;
+
+ return 0;
+}
+
+static struct clk clk_esysclk = {
+ .name = "esysclk",
+ .parent = &clk_epll,
+ .id = -1,
+ .set_parent = s3c2443_setparent_esysclk,
+};
+
+/* uartclk
+ *
+ * UART baud-rate clock sourced from esysclk via a divisor
+*/
+
+static unsigned long s3c2443_getrate_uart(struct clk *clk)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+ div &= S3C2443_CLKDIV1_UARTDIV_MASK;
+ div >>= S3C2443_CLKDIV1_UARTDIV_SHIFT;
+
+ return parent_rate / (div + 1);
+}
+
+
+static int s3c2443_setrate_uart(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+ rate = s3c2443_roundrate_clksrc16(clk, rate);
+ rate = parent_rate / rate;
+
+ clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
+ clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
+
+ __raw_writel(clkdivn, S3C2443_CLKDIV1);
+ return 0;
+}
+
+static struct clk clk_uart = {
+ .name = "uartclk",
+ .id = -1,
+ .parent = &clk_esysclk,
+ .get_rate = s3c2443_getrate_uart,
+ .set_rate = s3c2443_setrate_uart,
+ .round_rate = s3c2443_roundrate_clksrc16,
+};
+
+/* hsspi
+ *
+ * high-speed spi clock, sourced from esysclk
+*/
+
+static unsigned long s3c2443_getrate_hsspi(struct clk *clk)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+ div &= S3C2443_CLKDIV1_HSSPIDIV_MASK;
+ div >>= S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
+
+ return parent_rate / (div + 1);
+}
+
+
+static int s3c2443_setrate_hsspi(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+ rate = s3c2443_roundrate_clksrc4(clk, rate);
+ rate = parent_rate / rate;
+
+ clkdivn &= ~S3C2443_CLKDIV1_HSSPIDIV_MASK;
+ clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
+
+ __raw_writel(clkdivn, S3C2443_CLKDIV1);
+ return 0;
+}
+
+static struct clk clk_hsspi = {
+ .name = "hsspi",
+ .id = -1,
+ .parent = &clk_esysclk,
+ .ctrlbit = S3C2443_SCLKCON_HSSPICLK,
+ .enable = s3c2443_clkcon_enable_s,
+ .get_rate = s3c2443_getrate_hsspi,
+ .set_rate = s3c2443_setrate_hsspi,
+ .round_rate = s3c2443_roundrate_clksrc4,
+};
+
+/* usbhost
+ *
+ * usb host bus-clock, usually 48MHz to provide USB bus clock timing
+*/
+
+static unsigned long s3c2443_getrate_usbhost(struct clk *clk)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+ div &= S3C2443_CLKDIV1_USBHOSTDIV_MASK;
+ div >>= S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
+
+ return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_usbhost(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+ rate = s3c2443_roundrate_clksrc4(clk, rate);
+ rate = parent_rate / rate;
+
+ clkdivn &= ~S3C2443_CLKDIV1_USBHOSTDIV_MASK;
+ clkdivn |= (rate - 1) << S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
+
+ __raw_writel(clkdivn, S3C2443_CLKDIV1);
+ return 0;
+}
+
+struct clk clk_usb_bus_host = {
+ .name = "usb-bus-host-parent",
+ .id = -1,
+ .parent = &clk_esysclk,
+ .ctrlbit = S3C2443_SCLKCON_USBHOST,
+ .enable = s3c2443_clkcon_enable_s,
+ .get_rate = s3c2443_getrate_usbhost,
+ .set_rate = s3c2443_setrate_usbhost,
+ .round_rate = s3c2443_roundrate_clksrc4,
+};
+
+/* clk_hsmcc_div
+ *
+ * this clock is sourced from epll, and is fed through a divider,
+ * to a mux controlled by sclkcon where either it or a extclk can
+ * be fed to the hsmmc block
+*/
+
+static unsigned long s3c2443_getrate_hsmmc_div(struct clk *clk)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+ div &= S3C2443_CLKDIV1_HSMMCDIV_MASK;
+ div >>= S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
+
+ return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_hsmmc_div(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+ rate = s3c2443_roundrate_clksrc4(clk, rate);
+ rate = parent_rate / rate;
+
+ clkdivn &= ~S3C2443_CLKDIV1_HSMMCDIV_MASK;
+ clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
+
+ __raw_writel(clkdivn, S3C2443_CLKDIV1);
+ return 0;
+}
+
+static struct clk clk_hsmmc_div = {
+ .name = "hsmmc-div",
+ .id = -1,
+ .parent = &clk_esysclk,
+ .get_rate = s3c2443_getrate_hsmmc_div,
+ .set_rate = s3c2443_setrate_hsmmc_div,
+ .round_rate = s3c2443_roundrate_clksrc4,
+};
+
+static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
+{
+ unsigned long clksrc = __raw_readl(S3C2443_SCLKCON);
+
+ clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT |
+ S3C2443_SCLKCON_HSMMCCLK_EPLL);
+
+ if (parent == &clk_epll)
+ clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL;
+ else if (parent == &clk_ext)
+ clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT;
+ else
+ return -EINVAL;
+
+ if (clk->usage > 0) {
+ __raw_writel(clksrc, S3C2443_SCLKCON);
+ }
+
+ clk->parent = parent;
+ return 0;
+}
+
+static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
+{
+ return s3c2443_setparent_hsmmc(clk, clk->parent);
+}
+
+static struct clk clk_hsmmc = {
+ .name = "hsmmc-if",
+ .id = -1,
+ .parent = &clk_hsmmc_div,
+ .enable = s3c2443_enable_hsmmc,
+ .set_parent = s3c2443_setparent_hsmmc,
+};
+
+/* i2s_eplldiv
+ *
+ * this clock is the output from the i2s divisor of esysclk
+*/
+
+static unsigned long s3c2443_getrate_i2s_eplldiv(struct clk *clk)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+ div &= S3C2443_CLKDIV1_I2SDIV_MASK;
+ div >>= S3C2443_CLKDIV1_I2SDIV_SHIFT;
+
+ return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_i2s_eplldiv(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+ rate = s3c2443_roundrate_clksrc16(clk, rate);
+ rate = parent_rate / rate;
+
+ clkdivn &= ~S3C2443_CLKDIV1_I2SDIV_MASK;
+ clkdivn |= (rate - 1) << S3C2443_CLKDIV1_I2SDIV_SHIFT;
+
+ __raw_writel(clkdivn, S3C2443_CLKDIV1);
+ return 0;
+}
+
+static struct clk clk_i2s_eplldiv = {
+ .name = "i2s-eplldiv",
+ .id = -1,
+ .parent = &clk_esysclk,
+ .get_rate = s3c2443_getrate_i2s_eplldiv,
+ .set_rate = s3c2443_setrate_i2s_eplldiv,
+ .round_rate = s3c2443_roundrate_clksrc16,
+};
+
+/* i2s-ref
+ *
+ * i2s bus reference clock, selectable from external, esysclk or epllref
+*/
+
+static int s3c2443_setparent_i2s(struct clk *clk, struct clk *parent)
+{
+ unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+
+ clksrc &= ~S3C2443_CLKSRC_I2S_MASK;
+
+ if (parent == &clk_epllref)
+ clksrc |= S3C2443_CLKSRC_I2S_EPLLREF;
+ else if (parent == &clk_i2s_ext)
+ clksrc |= S3C2443_CLKSRC_I2S_EXT;
+ else if (parent != &clk_i2s_eplldiv)
+ return -EINVAL;
+
+ clk->parent = parent;
+ __raw_writel(clksrc, S3C2443_CLKSRC);
+
+ return 0;
+}
+
+static struct clk clk_i2s = {
+ .name = "i2s-if",
+ .id = -1,
+ .parent = &clk_i2s_eplldiv,
+ .ctrlbit = S3C2443_SCLKCON_I2SCLK,
+ .enable = s3c2443_clkcon_enable_s,
+ .set_parent = s3c2443_setparent_i2s,
+};
+
+/* cam-if
+ *
+ * camera interface bus-clock, divided down from esysclk
+*/
+
+static unsigned long s3c2443_getrate_cam(struct clk *clk)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+ div &= S3C2443_CLKDIV1_CAMDIV_MASK;
+ div >>= S3C2443_CLKDIV1_CAMDIV_SHIFT;
+
+ return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_cam(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long clkdiv1 = __raw_readl(S3C2443_CLKDIV1);
+
+ rate = s3c2443_roundrate_clksrc16(clk, rate);
+ rate = parent_rate / rate;
+
+ clkdiv1 &= ~S3C2443_CLKDIV1_CAMDIV_MASK;
+ clkdiv1 |= (rate - 1) << S3C2443_CLKDIV1_CAMDIV_SHIFT;
+
+ __raw_writel(clkdiv1, S3C2443_CLKDIV1);
+ return 0;
+}
+
+static struct clk clk_cam = {
+ .name = "camif-upll", /* same as 2440 name */
+ .id = -1,
+ .parent = &clk_esysclk,
+ .ctrlbit = S3C2443_SCLKCON_CAMCLK,
+ .enable = s3c2443_clkcon_enable_s,
+ .get_rate = s3c2443_getrate_cam,
+ .set_rate = s3c2443_setrate_cam,
+ .round_rate = s3c2443_roundrate_clksrc16,
+};
+
+/* display-if
+ *
+ * display interface clock, divided from esysclk
+*/
+
+static unsigned long s3c2443_getrate_display(struct clk *clk)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long div = __raw_readl(S3C2443_CLKDIV1);
+
+ div &= S3C2443_CLKDIV1_DISPDIV_MASK;
+ div >>= S3C2443_CLKDIV1_DISPDIV_SHIFT;
+
+ return parent_rate / (div + 1);
+}
+
+static int s3c2443_setrate_display(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+ unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
+
+ rate = s3c2443_roundrate_clksrc256(clk, rate);
+ rate = parent_rate / rate;
+
+ clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
+ clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
+
+ __raw_writel(clkdivn, S3C2443_CLKDIV1);
+ return 0;
+}
+
+static struct clk clk_display = {
+ .name = "display-if",
+ .id = -1,
+ .parent = &clk_esysclk,
+ .ctrlbit = S3C2443_SCLKCON_DISPCLK,
+ .enable = s3c2443_clkcon_enable_s,
+ .get_rate = s3c2443_getrate_display,
+ .set_rate = s3c2443_setrate_display,
+ .round_rate = s3c2443_roundrate_clksrc256,
+};
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+ {
+ .name = "nand",
+ .id = -1,
+ .parent = &clk_h,
+ }, {
+ .name = "sdi",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_SDI,
+ }, {
+ .name = "adc",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_ADC,
+ }, {
+ .name = "i2c",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_IIC,
+ }, {
+ .name = "iis",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_IIS,
+ }, {
+ .name = "spi",
+ .id = 0,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_SPI0,
+ }, {
+ .name = "spi",
+ .id = 1,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_SPI1,
+ }
+};
+
+static struct clk init_clocks[] = {
+ {
+ .name = "dma",
+ .id = 0,
+ .parent = &clk_h,
+ .enable = s3c2443_clkcon_enable_h,
+ .ctrlbit = S3C2443_HCLKCON_DMA0,
+ }, {
+ .name = "dma",
+ .id = 1,
+ .parent = &clk_h,
+ .enable = s3c2443_clkcon_enable_h,
+ .ctrlbit = S3C2443_HCLKCON_DMA1,
+ }, {
+ .name = "dma",
+ .id = 2,
+ .parent = &clk_h,
+ .enable = s3c2443_clkcon_enable_h,
+ .ctrlbit = S3C2443_HCLKCON_DMA2,
+ }, {
+ .name = "dma",
+ .id = 3,
+ .parent = &clk_h,
+ .enable = s3c2443_clkcon_enable_h,
+ .ctrlbit = S3C2443_HCLKCON_DMA3,
+ }, {
+ .name = "dma",
+ .id = 4,
+ .parent = &clk_h,
+ .enable = s3c2443_clkcon_enable_h,
+ .ctrlbit = S3C2443_HCLKCON_DMA4,
+ }, {
+ .name = "dma",
+ .id = 5,
+ .parent = &clk_h,
+ .enable = s3c2443_clkcon_enable_h,
+ .ctrlbit = S3C2443_HCLKCON_DMA5,
+ }, {
+ .name = "lcd",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c2443_clkcon_enable_h,
+ .ctrlbit = S3C2443_HCLKCON_LCDC,
+ }, {
+ .name = "gpio",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_GPIO,
+ }, {
+ .name = "usb-host",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c2443_clkcon_enable_h,
+ .ctrlbit = S3C2443_HCLKCON_USBH,
+ }, {
+ .name = "usb-device",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c2443_clkcon_enable_h,
+ .ctrlbit = S3C2443_HCLKCON_USBD,
+ }, {
+ .name = "timers",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_PWMT,
+ }, {
+ .name = "uart",
+ .id = 0,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_UART0,
+ }, {
+ .name = "uart",
+ .id = 1,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_UART1,
+ }, {
+ .name = "uart",
+ .id = 2,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_UART2,
+ }, {
+ .name = "uart",
+ .id = 3,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_UART3,
+ }, {
+ .name = "rtc",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c2443_clkcon_enable_p,
+ .ctrlbit = S3C2443_PCLKCON_RTC,
+ }, {
+ .name = "watchdog",
+ .id = -1,
+ .parent = &clk_p,
+ .ctrlbit = S3C2443_PCLKCON_WDT,
+ }, {
+ .name = "usb-bus-host",
+ .id = -1,
+ .parent = &clk_usb_bus_host,
+ }
+};
+
+/* clocks to add where we need to check their parentage */
+
+/* s3c2443_clk_initparents
+ *
+ * Initialise the parents for the clocks that we get at start-time
+*/
+
+static int __init clk_init_set_parent(struct clk *clk, struct clk *parent)
+{
+ printk(KERN_DEBUG "clock %s: parent %s\n", clk->name, parent->name);
+ return clk_set_parent(clk, parent);
+}
+
+static void __init s3c2443_clk_initparents(void)
+{
+ unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+ struct clk *parent;
+
+ switch (clksrc & S3C2443_CLKSRC_EPLLREF_MASK) {
+ case S3C2443_CLKSRC_EPLLREF_EXTCLK:
+ parent = &clk_ext;
+ break;
+
+ case S3C2443_CLKSRC_EPLLREF_XTAL:
+ default:
+ parent = &clk_xtal;
+ break;
+
+ case S3C2443_CLKSRC_EPLLREF_MPLLREF:
+ case S3C2443_CLKSRC_EPLLREF_MPLLREF2:
+ parent = &clk_mpllref;
+ break;
+ }
+
+ clk_init_set_parent(&clk_epllref, parent);
+
+ switch (clksrc & S3C2443_CLKSRC_I2S_MASK) {
+ case S3C2443_CLKSRC_I2S_EXT:
+ parent = &clk_i2s_ext;
+ break;
+
+ case S3C2443_CLKSRC_I2S_EPLLDIV:
+ default:
+ parent = &clk_i2s_eplldiv;
+ break;
+
+ case S3C2443_CLKSRC_I2S_EPLLREF:
+ case S3C2443_CLKSRC_I2S_EPLLREF3:
+ parent = &clk_epllref;
+ }
+
+ clk_init_set_parent(&clk_i2s, &clk_epllref);
+
+ /* esysclk source */
+
+ parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ?
+ &clk_epll : &clk_epllref;
+
+ clk_init_set_parent(&clk_esysclk, parent);
+
+ /* msysclk source */
+
+ if (clksrc & S3C2443_CLKSRC_MSYSCLK_MPLL) {
+ parent = &clk_mpll;
+ } else {
+ parent = (clksrc & S3C2443_CLKSRC_EXTCLK_DIV) ?
+ &clk_mdivclk : &clk_mpllref;
+ }
+
+ clk_init_set_parent(&clk_msysclk, parent);
+}
+
+/* armdiv divisor table */
+
+static unsigned int armdiv[16] = {
+ [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1,
+ [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2,
+ [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3,
+ [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4,
+ [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6,
+ [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8,
+ [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12,
+ [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16,
+};
+
+static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
+{
+ clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
+
+ return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
+}
+
+static inline unsigned long s3c2443_get_prediv(unsigned long clkcon0)
+{
+ clkcon0 &= S3C2443_CLKDIV0_PREDIV_MASK;
+ clkcon0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT;
+
+ return clkcon0 + 1;
+}
+
+/* clocks to add straight away */
+
+static struct clk *clks[] __initdata = {
+ &clk_ext,
+ &clk_epll,
+ &clk_usb_bus_host,
+ &clk_usb_bus,
+ &clk_esysclk,
+ &clk_epllref,
+ &clk_mpllref,
+ &clk_msysclk,
+ &clk_uart,
+ &clk_display,
+ &clk_cam,
+ &clk_i2s_eplldiv,
+ &clk_i2s,
+ &clk_hsspi,
+ &clk_hsmmc_div,
+ &clk_hsmmc,
+};
+
+void __init s3c2443_init_clocks(int xtal)
+{
+ unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
+ unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
+ unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
+ unsigned long pll;
+ unsigned long fclk;
+ unsigned long hclk;
+ unsigned long pclk;
+ struct clk *clkp;
+ int ret;
+ int ptr;
+
+ pll = s3c2443_get_mpll(mpllcon, xtal);
+
+ fclk = pll / s3c2443_fclk_div(clkdiv0);
+ hclk = fclk / s3c2443_get_prediv(clkdiv0);
+ hclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_HCLK) ? 2 : 1);
+ pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
+
+ s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+
+ printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",
+ (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on",
+ print_mhz(pll), print_mhz(fclk),
+ print_mhz(hclk), print_mhz(pclk));
+
+ s3c2443_clk_initparents();
+
+ for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
+ clkp = clks[ptr];
+
+ ret = s3c24xx_register_clock(clkp);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register clock %s (%d)\n",
+ clkp->name, ret);
+ }
+ }
+
+ clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
+
+ clk_usb_bus.parent = &clk_usb_bus_host;
+
+ /* ensure usb bus clock is within correct rate of 48MHz */
+
+ if (clk_get_rate(&clk_usb_bus_host) != (48 * 1000 * 1000)) {
+ printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
+ clk_set_rate(&clk_usb_bus_host, 48*1000*1000);
+ }
+
+ printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
+ (epllcon & S3C2443_PLLCON_OFF) ? "off":"on",
+ print_mhz(clk_get_rate(&clk_epll)),
+ print_mhz(clk_get_rate(&clk_usb_bus)));
+
+ /* register clocks from clock array */
+
+ clkp = init_clocks;
+ for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+ ret = s3c24xx_register_clock(clkp);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register clock %s (%d)\n",
+ clkp->name, ret);
+ }
+ }
+
+ /* We must be careful disabling the clocks we are not intending to
+ * be using at boot time, as subsytems such as the LCD which do
+ * their own DMA requests to the bus can cause the system to lockup
+ * if they where in the middle of requesting bus access.
+ *
+ * Disabling the LCD clock if the LCD is active is very dangerous,
+ * and therefore the bootloader should be careful to not enable
+ * the LCD clock if it is not needed.
+ */
+
+ /* install (and disable) the clocks we do not need immediately */
+
+ clkp = init_clocks_disable;
+ for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+ ret = s3c24xx_register_clock(clkp);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register clock %s (%d)\n",
+ clkp->name, ret);
+ }
+
+ (clkp->enable)(clkp, 0);
+ }
+}
diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c
new file mode 100644
index 00000000000..f70e8ccffc3
--- /dev/null
+++ b/arch/arm/mach-s3c2443/dma.c
@@ -0,0 +1,180 @@
+/* linux/arch/arm/mach-s3c2443/dma.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2443 DMA selection
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+#include <asm/io.h>
+
+#include <asm/plat-s3c24xx/dma.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
+
+#define MAP(x) { \
+ [0] = (x) | DMA_CH_VALID, \
+ [1] = (x) | DMA_CH_VALID, \
+ [2] = (x) | DMA_CH_VALID, \
+ [3] = (x) | DMA_CH_VALID, \
+ [4] = (x) | DMA_CH_VALID, \
+ [5] = (x) | DMA_CH_VALID, \
+ }
+
+static struct s3c24xx_dma_map __initdata s3c2443_dma_mappings[] = {
+ [DMACH_XD0] = {
+ .name = "xdreq0",
+ .channels = MAP(S3C2443_DMAREQSEL_XDREQ0),
+ },
+ [DMACH_XD1] = {
+ .name = "xdreq1",
+ .channels = MAP(S3C2443_DMAREQSEL_XDREQ1),
+ },
+ [DMACH_SDI] = {
+ .name = "sdi",
+ .channels = MAP(S3C2443_DMAREQSEL_SDI),
+ .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
+ .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
+ },
+ [DMACH_SPI0] = {
+ .name = "spi0",
+ .channels = MAP(S3C2443_DMAREQSEL_SPI0TX),
+ .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT,
+ .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT,
+ },
+ [DMACH_SPI1] = {
+ .name = "spi1",
+ .channels = MAP(S3C2443_DMAREQSEL_SPI1TX),
+ .hw_addr.to = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+ .hw_addr.from = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+ },
+ [DMACH_UART0] = {
+ .name = "uart0",
+ .channels = MAP(S3C2443_DMAREQSEL_UART0_0),
+ .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
+ .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
+ },
+ [DMACH_UART1] = {
+ .name = "uart1",
+ .channels = MAP(S3C2443_DMAREQSEL_UART1_0),
+ .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
+ .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
+ },
+ [DMACH_UART2] = {
+ .name = "uart2",
+ .channels = MAP(S3C2443_DMAREQSEL_UART2_0),
+ .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
+ .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
+ },
+ [DMACH_UART3] = {
+ .name = "uart3",
+ .channels = MAP(S3C2443_DMAREQSEL_UART3_0),
+ .hw_addr.to = S3C2443_PA_UART3 + S3C2410_UTXH,
+ .hw_addr.from = S3C2443_PA_UART3 + S3C2410_URXH,
+ },
+ [DMACH_UART0_SRC2] = {
+ .name = "uart0",
+ .channels = MAP(S3C2443_DMAREQSEL_UART0_1),
+ .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
+ .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
+ },
+ [DMACH_UART1_SRC2] = {
+ .name = "uart1",
+ .channels = MAP(S3C2443_DMAREQSEL_UART1_1),
+ .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
+ .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
+ },
+ [DMACH_UART2_SRC2] = {
+ .name = "uart2",
+ .channels = MAP(S3C2443_DMAREQSEL_UART2_1),
+ .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
+ .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
+ },
+ [DMACH_UART3_SRC2] = {
+ .name = "uart3",
+ .channels = MAP(S3C2443_DMAREQSEL_UART3_1),
+ .hw_addr.to = S3C2443_PA_UART3 + S3C2410_UTXH,
+ .hw_addr.from = S3C2443_PA_UART3 + S3C2410_URXH,
+ },
+ [DMACH_TIMER] = {
+ .name = "timer",
+ .channels = MAP(S3C2443_DMAREQSEL_TIMER),
+ },
+ [DMACH_I2S_IN] = {
+ .name = "i2s-sdi",
+ .channels = MAP(S3C2443_DMAREQSEL_I2SRX),
+ .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
+ },
+ [DMACH_I2S_OUT] = {
+ .name = "i2s-sdo",
+ .channels = MAP(S3C2443_DMAREQSEL_I2STX),
+ .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
+ },
+ [DMACH_PCM_IN] = {
+ .name = "pcm-in",
+ .channels = MAP(S3C2443_DMAREQSEL_PCMIN),
+ .hw_addr.from = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+ },
+ [DMACH_PCM_OUT] = {
+ .name = "pcm-out",
+ .channels = MAP(S3C2443_DMAREQSEL_PCMOUT),
+ .hw_addr.to = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
+ },
+ [DMACH_MIC_IN] = {
+ .name = "mic-in",
+ .channels = MAP(S3C2443_DMAREQSEL_MICIN),
+ .hw_addr.from = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
+ },
+};
+
+static void s3c2443_dma_select(struct s3c2410_dma_chan *chan,
+ struct s3c24xx_dma_map *map)
+{
+ writel(map->channels[0] | S3C2443_DMAREQSEL_HW,
+ chan->regs + S3C2443_DMA_DMAREQSEL);
+}
+
+static struct s3c24xx_dma_selection __initdata s3c2443_dma_sel = {
+ .select = s3c2443_dma_select,
+ .dcon_mask = 0,
+ .map = s3c2443_dma_mappings,
+ .map_size = ARRAY_SIZE(s3c2443_dma_mappings),
+};
+
+static int s3c2443_dma_add(struct sys_device *sysdev)
+{
+ s3c24xx_dma_init(6, IRQ_S3C2443_DMA0, 0x100);
+ return s3c24xx_dma_init_map(&s3c2443_dma_sel);
+}
+
+static struct sysdev_driver s3c2443_dma_driver = {
+ .add = s3c2443_dma_add,
+};
+
+static int __init s3c2443_dma_init(void)
+{
+ return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_dma_driver);
+}
+
+arch_initcall(s3c2443_dma_init);
diff --git a/arch/arm/mach-s3c2443/irq.c b/arch/arm/mach-s3c2443/irq.c
new file mode 100644
index 00000000000..7a45b6dcb73
--- /dev/null
+++ b/arch/arm/mach-s3c2443/irq.c
@@ -0,0 +1,290 @@
+/* linux/arch/arm/mach-s3c2443/irq.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
+
+#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
+
+static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len)
+{
+ unsigned int subsrc, submsk;
+ unsigned int end;
+ struct irq_desc *mydesc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+ subsrc = __raw_readl(S3C2410_SUBSRCPND);
+ submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+ subsrc &= ~submsk;
+ subsrc >>= (irq - S3C2410_IRQSUB(0));
+ subsrc &= (1 << len)-1;
+
+ end = len + irq;
+ mydesc = irq_desc + irq;
+
+ for (; irq < end && subsrc; irq++) {
+ if (subsrc & 1)
+ desc_handle_irq(irq, mydesc);
+
+ mydesc++;
+ subsrc >>= 1;
+ }
+}
+
+/* WDT/AC97 sub interrupts */
+
+static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2443_irq_demux(IRQ_S3C2443_WDT, 4);
+}
+
+#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0))
+#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
+
+static void s3c2443_irq_wdtac97_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+}
+
+static void s3c2443_irq_wdtac97_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_WDTAC97);
+}
+
+static void s3c2443_irq_wdtac97_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+}
+
+static struct irq_chip s3c2443_irq_wdtac97 = {
+ .mask = s3c2443_irq_wdtac97_mask,
+ .unmask = s3c2443_irq_wdtac97_unmask,
+ .ack = s3c2443_irq_wdtac97_ack,
+};
+
+
+/* LCD sub interrupts */
+
+static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4);
+}
+
+#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))
+#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
+
+static void s3c2443_irq_lcd_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_LCD, SUBMSK_LCD);
+}
+
+static void s3c2443_irq_lcd_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_LCD);
+}
+
+static void s3c2443_irq_lcd_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_LCD, SUBMSK_LCD);
+}
+
+static struct irq_chip s3c2443_irq_lcd = {
+ .mask = s3c2443_irq_lcd_mask,
+ .unmask = s3c2443_irq_lcd_unmask,
+ .ack = s3c2443_irq_lcd_ack,
+};
+
+
+/* DMA sub interrupts */
+
+static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2443_irq_demux(IRQ_S3C2443_DMA1, 6);
+}
+
+#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0))
+#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
+
+
+static void s3c2443_irq_dma_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_DMA, SUBMSK_DMA);
+}
+
+static void s3c2443_irq_dma_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_DMA);
+}
+
+static void s3c2443_irq_dma_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_DMA, SUBMSK_DMA);
+}
+
+static struct irq_chip s3c2443_irq_dma = {
+ .mask = s3c2443_irq_dma_mask,
+ .unmask = s3c2443_irq_dma_unmask,
+ .ack = s3c2443_irq_dma_ack,
+};
+
+
+/* UART3 sub interrupts */
+
+static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2443_irq_demux(IRQ_S3C2443_UART3, 3);
+}
+
+#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
+#define SUBMSK_UART3 (0xf << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
+
+
+static void s3c2443_irq_uart3_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_UART3, SUBMSK_UART3);
+}
+
+static void s3c2443_irq_uart3_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_UART3);
+}
+
+static void s3c2443_irq_uart3_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_UART3, SUBMSK_UART3);
+}
+
+static struct irq_chip s3c2443_irq_uart3 = {
+ .mask = s3c2443_irq_uart3_mask,
+ .unmask = s3c2443_irq_uart3_unmask,
+ .ack = s3c2443_irq_uart3_ack,
+};
+
+
+/* CAM sub interrupts */
+
+static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4);
+}
+
+#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
+#define SUBMSK_CAM INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P)
+
+static void s3c2443_irq_cam_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_CAM, SUBMSK_CAM);
+}
+
+static void s3c2443_irq_cam_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_CAM);
+}
+
+static void s3c2443_irq_cam_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_CAM, SUBMSK_CAM);
+}
+
+static struct irq_chip s3c2443_irq_cam = {
+ .mask = s3c2443_irq_cam_mask,
+ .unmask = s3c2443_irq_cam_unmask,
+ .ack = s3c2443_irq_cam_ack,
+};
+
+/* IRQ initialisation code */
+
+static int __init s3c2443_add_sub(unsigned int base,
+ void (*demux)(unsigned int,
+ struct irq_desc *),
+ struct irq_chip *chip,
+ unsigned int start, unsigned int end)
+{
+ unsigned int irqno;
+
+ set_irq_chip(base, &s3c_irq_level_chip);
+ set_irq_handler(base, handle_level_irq);
+ set_irq_chained_handler(base, demux);
+
+ for (irqno = start; irqno <= end; irqno++) {
+ set_irq_chip(irqno, chip);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ return 0;
+}
+
+static int s3c2443_irq_add(struct sys_device *sysdev)
+{
+ printk("S3C2443: IRQ Support\n");
+
+ s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam,
+ IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P);
+
+ s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd,
+ IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4);
+
+ s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma,
+ &s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5);
+
+ s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3,
+ &s3c2443_irq_uart3,
+ IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3);
+
+ s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97,
+ &s3c2443_irq_wdtac97,
+ IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
+
+ return 0;
+}
+
+static struct sysdev_driver s3c2443_irq_driver = {
+ .add = s3c2443_irq_add,
+};
+
+static int s3c2443_irq_init(void)
+{
+ return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_irq_driver);
+}
+
+arch_initcall(s3c2443_irq_init);
+
diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c
new file mode 100644
index 00000000000..e82aaff7dee
--- /dev/null
+++ b/arch/arm/mach-s3c2443/mach-smdk2443.c
@@ -0,0 +1,137 @@
+/* linux/arch/arm/mach-s3c2443/mach-smdk2443.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.fluff.org/ben/smdk2443/
+ *
+ * Thanks to Samsung for the loan of an SMDK2443
+ *
+ * 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/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+#include <asm/plat-s3c24xx/common-smdk.h>
+
+static struct map_desc smdk2443_iodesc[] __initdata = {
+ /* ISA IO Space map (memory space selected by A24) */
+
+ {
+ .virtual = (u32)S3C24XX_VA_ISA_WORD,
+ .pfn = __phys_to_pfn(S3C2410_CS2),
+ .length = 0x10000,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_WORD + 0x10000,
+ .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+ .length = SZ_4M,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_BYTE,
+ .pfn = __phys_to_pfn(S3C2410_CS2),
+ .length = 0x10000,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
+ .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
+ .length = SZ_4M,
+ .type = MT_DEVICE,
+ }
+};
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk2443_uartcfgs[] __initdata = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+ /* IR port */
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x43,
+ .ufcon = 0x51,
+ }
+};
+
+static struct platform_device *smdk2443_devices[] __initdata = {
+ &s3c_device_wdt,
+ &s3c_device_i2c,
+};
+
+static struct s3c24xx_board smdk2443_board __initdata = {
+ .devices = smdk2443_devices,
+ .devices_count = ARRAY_SIZE(smdk2443_devices)
+};
+
+static void __init smdk2443_map_io(void)
+{
+ s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc));
+ s3c24xx_init_clocks(12000000);
+ s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs));
+ s3c24xx_set_board(&smdk2443_board);
+}
+
+static void __init smdk2443_machine_init(void)
+{
+ smdk_machine_init();
+}
+
+MACHINE_START(SMDK2443, "SMDK2443")
+ /* Maintainer: Ben Dooks <ben@fluff.org> */
+ .phys_io = S3C2410_PA_UART,
+ .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+ .boot_params = S3C2410_SDRAM_PA + 0x100,
+
+ .init_irq = s3c24xx_init_irq,
+ .map_io = smdk2443_map_io,
+ .init_machine = smdk2443_machine_init,
+ .timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2443/s3c2443.c b/arch/arm/mach-s3c2443/s3c2443.c
new file mode 100644
index 00000000000..11b1d0b310c
--- /dev/null
+++ b/arch/arm/mach-s3c2443/s3c2443.c
@@ -0,0 +1,97 @@
+/* linux/arch/arm/mach-s3c2443/s3c2443.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2443 Mobile CPU support
+ *
+ * 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/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-s3c2443-clock.h>
+#include <asm/arch/reset.h>
+
+#include <asm/plat-s3c24xx/s3c2443.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+static struct map_desc s3c2443_iodesc[] __initdata = {
+ IODESC_ENT(WATCHDOG),
+ IODESC_ENT(CLKPWR),
+ IODESC_ENT(TIMER),
+};
+
+struct sysdev_class s3c2443_sysclass = {
+ set_kset_name("s3c2443-core"),
+};
+
+static struct sys_device s3c2443_sysdev = {
+ .cls = &s3c2443_sysclass,
+};
+
+static void s3c2443_hard_reset(void)
+{
+ __raw_writel(S3C2443_SWRST_RESET, S3C2443_SWRST);
+}
+
+int __init s3c2443_init(void)
+{
+ printk("S3C2443: Initialising architecture\n");
+
+ s3c24xx_reset_hook = s3c2443_hard_reset;
+
+ s3c_device_nand.name = "s3c2412-nand";
+
+ return sysdev_register(&s3c2443_sysdev);
+}
+
+void __init s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+ s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
+}
+
+/* s3c2443_map_io
+ *
+ * register the standard cpu IO areas, and any passed in from the
+ * machine specific initialisation.
+ */
+
+void __init s3c2443_map_io(struct map_desc *mach_desc, int mach_size)
+{
+ iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
+ iotable_init(mach_desc, mach_size);
+}
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2443 based system)
+ * as a driver which may support both 2443 and 2440 may try and use it.
+*/
+
+static int __init s3c2443_core_init(void)
+{
+ return sysdev_class_register(&s3c2443_sysclass);
+}
+
+core_initcall(s3c2443_core_init);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 3c2f97938c4..e684e9b3821 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -171,8 +171,8 @@ config CPU_ARM925T
# ARM926T
config CPU_ARM926T
bool "Support ARM926T processor"
- depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261
- default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261
+ depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_NS9XXX
+ default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_NS9XXX
select CPU_32v5
select CPU_ABRT_EV5TJ
select CPU_CACHE_VIVT
@@ -609,3 +609,10 @@ config NEEDS_SYSCALL_FOR_CMPXCHG
Forget about fast user space cmpxchg support.
It is just not possible.
+config OUTER_CACHE
+ bool
+ default n
+
+config CACHE_L2X0
+ bool
+ select OUTER_CACHE
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index d2f5672ecf6..2f8b9594777 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -66,3 +66,5 @@ obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o
obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o
obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o
obj-$(CONFIG_CPU_V6) += proc-v6.o
+
+obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
new file mode 100644
index 00000000000..08a36f1b35d
--- /dev/null
+++ b/arch/arm/mm/cache-l2x0.c
@@ -0,0 +1,104 @@
+/*
+ * arch/arm/mm/cache-l2x0.c - L210/L220 cache controller support
+ *
+ * Copyright (C) 2007 ARM Limited
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#define CACHE_LINE_SIZE 32
+
+static void __iomem *l2x0_base;
+
+static inline void sync_writel(unsigned long val, unsigned long reg,
+ unsigned long complete_mask)
+{
+ writel(val, l2x0_base + reg);
+ /* wait for the operation to complete */
+ while (readl(l2x0_base + reg) & complete_mask)
+ ;
+}
+
+static inline void cache_sync(void)
+{
+ sync_writel(0, L2X0_CACHE_SYNC, 1);
+}
+
+static inline void l2x0_inv_all(void)
+{
+ /* invalidate all ways */
+ sync_writel(0xff, L2X0_INV_WAY, 0xff);
+ cache_sync();
+}
+
+static void l2x0_inv_range(unsigned long start, unsigned long end)
+{
+ unsigned long addr;
+
+ start &= ~(CACHE_LINE_SIZE - 1);
+ for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
+ sync_writel(addr, L2X0_INV_LINE_PA, 1);
+ cache_sync();
+}
+
+static void l2x0_clean_range(unsigned long start, unsigned long end)
+{
+ unsigned long addr;
+
+ start &= ~(CACHE_LINE_SIZE - 1);
+ for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
+ sync_writel(addr, L2X0_CLEAN_LINE_PA, 1);
+ cache_sync();
+}
+
+static void l2x0_flush_range(unsigned long start, unsigned long end)
+{
+ unsigned long addr;
+
+ start &= ~(CACHE_LINE_SIZE - 1);
+ for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
+ sync_writel(addr, L2X0_CLEAN_INV_LINE_PA, 1);
+ cache_sync();
+}
+
+void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
+{
+ __u32 aux;
+
+ l2x0_base = base;
+
+ /* disable L2X0 */
+ writel(0, l2x0_base + L2X0_CTRL);
+
+ aux = readl(l2x0_base + L2X0_AUX_CTRL);
+ aux &= aux_mask;
+ aux |= aux_val;
+ writel(aux, l2x0_base + L2X0_AUX_CTRL);
+
+ l2x0_inv_all();
+
+ /* enable L2X0 */
+ writel(1, l2x0_base + L2X0_CTRL);
+
+ outer_cache.inv_range = l2x0_inv_range;
+ outer_cache.clean_range = l2x0_clean_range;
+ outer_cache.flush_range = l2x0_flush_range;
+
+ printk(KERN_INFO "L2X0 cache controller enabled\n");
+}
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 6a9c362fef5..1f9f94f9af4 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -205,9 +205,10 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
* kernel direct-mapped region for device DMA.
*/
{
- unsigned long kaddr = (unsigned long)page_address(page);
- memset(page_address(page), 0, size);
- dmac_flush_range(kaddr, kaddr + size);
+ void *ptr = page_address(page);
+ memset(ptr, 0, size);
+ dmac_flush_range(ptr, ptr + size);
+ outer_flush_range(__pa(ptr), __pa(ptr) + size);
}
/*
@@ -480,20 +481,24 @@ core_initcall(consistent_init);
* platforms with CONFIG_DMABOUNCE.
* Use the driver DMA support - see dma-mapping.h (dma_sync_*)
*/
-void consistent_sync(void *vaddr, size_t size, int direction)
+void consistent_sync(const void *start, size_t size, int direction)
{
- unsigned long start = (unsigned long)vaddr;
- unsigned long end = start + size;
+ const void *end = start + size;
+
+ BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end - 1));
switch (direction) {
case DMA_FROM_DEVICE: /* invalidate only */
dmac_inv_range(start, end);
+ outer_inv_range(__pa(start), __pa(end));
break;
case DMA_TO_DEVICE: /* writeback only */
dmac_clean_range(start, end);
+ outer_clean_range(__pa(start), __pa(end));
break;
case DMA_BIDIRECTIONAL: /* writeback and invalidate */
dmac_flush_range(start, end);
+ outer_flush_range(__pa(start), __pa(end));
break;
default:
BUG();
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index 79e80020242..9da43a0fdcd 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -19,7 +19,8 @@ unsigned int cpu_last_asid = { 1 << ASID_BITS };
/*
* We fork()ed a process, and we need a new context for the child
* to run in. We reserve version 0 for initial tasks so we will
- * always allocate an ASID.
+ * always allocate an ASID. The ASID 0 is reserved for the TTBR
+ * register changing sequence.
*/
void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
{
@@ -38,8 +39,15 @@ void __new_context(struct mm_struct *mm)
* If we've used up all our ASIDs, we need
* to start a new version and flush the TLB.
*/
- if ((asid & ~ASID_MASK) == 0)
+ if ((asid & ~ASID_MASK) == 0) {
+ asid = ++cpu_last_asid;
+ /* set the reserved ASID before flushing the TLB */
+ asm("mcr p15, 0, %0, c13, c0, 1 @ set reserved context ID\n"
+ :
+ : "r" (0));
+ isb();
flush_tlb_all();
+ }
mm->context.id = asid;
}
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index cf95c5d0ce4..44558d5f931 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -119,8 +119,6 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigne
flush_cache_page(vma, addr, pfn);
}
-void __flush_dcache_page(struct address_space *mapping, struct page *page);
-
/*
* Take care of architecture specific things when placing a new PTE into
* a page table, or changing an existing PTE. Basically, there are two
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 655c8376f0b..94fd4bf5cb9 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -49,8 +49,10 @@ pmd_t *top_pmd;
static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
static unsigned int ecc_mask __initdata = 0;
+pgprot_t pgprot_user;
pgprot_t pgprot_kernel;
+EXPORT_SYMBOL(pgprot_user);
EXPORT_SYMBOL(pgprot_kernel);
struct cachepolicy {
@@ -345,6 +347,7 @@ static void __init build_mem_type_table(void)
mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
}
+ pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
L_PTE_DIRTY | L_PTE_WRITE |
L_PTE_EXEC | kern_pgprot);
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 7b1843befb9..eb42e5b9486 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -14,10 +14,13 @@
#include <asm/assembler.h>
#include <asm/asm-offsets.h>
#include <asm/elf.h>
-#include <asm/hardware/arm_scu.h>
#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
+#ifdef CONFIG_SMP
+#include <asm/hardware/arm_scu.h>
+#endif
+
#include "proc-macros.S"
#define D_CACHE_LINE_SIZE 32
@@ -30,6 +33,12 @@
#define TTB_RGN_WT (2 << 3)
#define TTB_RGN_WB (3 << 3)
+#ifndef CONFIG_SMP
+#define TTB_FLAGS TTB_RGN_WBWA
+#else
+#define TTB_FLAGS TTB_RGN_WBWA|TTB_S
+#endif
+
ENTRY(cpu_v6_proc_init)
mov pc, lr
@@ -92,9 +101,7 @@ ENTRY(cpu_v6_switch_mm)
#ifdef CONFIG_MMU
mov r2, #0
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
-#ifdef CONFIG_SMP
- orr r0, r0, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable
-#endif
+ orr r0, r0, #TTB_FLAGS
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
mcr p15, 0, r2, c7, c10, 4 @ drain write buffer
mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
@@ -183,8 +190,7 @@ __v6_setup:
/* Set up the SCU on core 0 only */
mrc p15, 0, r0, c0, c0, 5 @ CPU core number
ands r0, r0, #15
- moveq r0, #0x10000000 @ SCU_BASE
- orreq r0, r0, #0x00100000
+ ldreq r0, =SCU_BASE
ldreq r5, [r0, #SCU_CTRL]
orreq r5, r5, #1
streq r5, [r0, #SCU_CTRL]
@@ -204,9 +210,7 @@ __v6_setup:
#ifdef CONFIG_MMU
mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
mcr p15, 0, r0, c2, c0, 2 @ TTB control register
-#ifdef CONFIG_SMP
- orr r4, r4, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable
-#endif
+ orr r4, r4, #TTB_FLAGS
mcr p15, 0, r4, c2, c0, 1 @ load TTB1
#endif /* CONFIG_MMU */
adr r5, v6_crval
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index 94a58455f34..d95921a2ab9 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -5,23 +5,23 @@
* Current Maintainer: Lennert Buytenhek <buytenh@wantstofly.org>
*
* Copyright 2004 (C) Intel Corp.
- * Copyright 2005 (c) MontaVista Software, Inc.
+ * Copyright 2005 (C) 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.
*
- * MMU functions for the Intel XScale3 Core (XSC3). The XSC3 core is an
- * extension to Intel's original XScale core that adds the following
+ * MMU functions for the Intel XScale3 Core (XSC3). The XSC3 core is
+ * an extension to Intel's original XScale core that adds the following
* features:
*
* - ARMv6 Supersections
* - Low Locality Reference pages (replaces mini-cache)
* - 36-bit addressing
* - L2 cache
- * - Cache-coherency if chipset supports it
+ * - Cache coherency if chipset supports it
*
- * Based on orignal XScale code by Nicolas Pitre
+ * Based on original XScale code by Nicolas Pitre.
*/
#include <linux/linkage.h>
@@ -42,12 +42,12 @@
#define MAX_AREA_SIZE 32768
/*
- * The cache line size of the I and D cache.
+ * The cache line size of the L1 I, L1 D and unified L2 cache.
*/
#define CACHELINESIZE 32
/*
- * The size of the data cache.
+ * The size of the L1 D cache.
*/
#define CACHESIZE 32768
@@ -57,9 +57,9 @@
#define L2_CACHE_ENABLE 1
/*
- * This macro is used to wait for a CP15 write and is needed
- * when we have to ensure that the last operation to the co-pro
- * was completed before continuing with operation.
+ * This macro is used to wait for a CP15 write and is needed when we
+ * have to ensure that the last operation to the coprocessor was
+ * completed before continuing with operation.
*/
.macro cpwait_ret, lr, rd
mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15
@@ -68,13 +68,13 @@
.endm
/*
- * This macro cleans & invalidates the entire xsc3 dcache by set & way.
+ * This macro cleans and invalidates the entire L1 D cache.
*/
.macro clean_d_cache rd, rs
mov \rd, #0x1f00
orr \rd, \rd, #0x00e0
-1: mcr p15, 0, \rd, c7, c14, 2 @ clean/inv set/way
+1: mcr p15, 0, \rd, c7, c14, 2 @ clean/invalidate L1 D line
adds \rd, \rd, #0x40000000
bcc 1b
subs \rd, \rd, #0x20
@@ -119,15 +119,15 @@ ENTRY(cpu_xsc3_reset)
mov r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
msr cpsr_c, r1 @ reset CPSR
mrc p15, 0, r1, c1, c0, 0 @ ctrl register
- bic r1, r1, #0x0086 @ ........B....CA.
bic r1, r1, #0x3900 @ ..VIZ..S........
+ bic r1, r1, #0x0086 @ ........B....CA.
mcr p15, 0, r1, c1, c0, 0 @ ctrl register
- mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate L1 caches and BTB
bic r1, r1, #0x0001 @ ...............M
mcr p15, 0, r1, c1, c0, 0 @ ctrl register
@ CAUTION: MMU turned off from this point. We count on the pipeline
@ already containing those two last instructions to survive.
- mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I and D TLBs
mov pc, r0
/*
@@ -139,14 +139,12 @@ ENTRY(cpu_xsc3_reset)
*
* XScale supports clock switching, but using idle mode support
* allows external hardware to react to system state changes.
-
- MMG: Come back to this one.
*/
.align 5
ENTRY(cpu_xsc3_do_idle)
mov r0, #1
- mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE
+ mcr p14, 0, r0, c7, c0, 0 @ go to idle
mov pc, lr
/* ================================= CACHE ================================ */
@@ -171,9 +169,9 @@ ENTRY(xsc3_flush_kern_cache_all)
__flush_whole_cache:
clean_d_cache r0, r1
tst r2, #VM_EXEC
- mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
- mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
- mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush
+ mcrne p15, 0, ip, c7, c5, 0 @ invalidate L1 I cache and BTB
+ mcrne p15, 0, ip, c7, c10, 4 @ data write barrier
+ mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush
mov pc, lr
/*
@@ -194,21 +192,21 @@ ENTRY(xsc3_flush_user_cache_range)
bhs __flush_whole_cache
1: tst r2, #VM_EXEC
- mcrne p15, 0, r0, c7, c5, 1 @ Invalidate I cache line
- mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate D cache line
+ mcrne p15, 0, r0, c7, c5, 1 @ invalidate L1 I line
+ mcr p15, 0, r0, c7, c14, 1 @ clean/invalidate L1 D line
add r0, r0, #CACHELINESIZE
cmp r0, r1
blo 1b
tst r2, #VM_EXEC
- mcrne p15, 0, ip, c7, c5, 6 @ Invalidate BTB
- mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
- mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush
+ mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB
+ mcrne p15, 0, ip, c7, c10, 4 @ data write barrier
+ mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush
mov pc, lr
/*
* coherent_kern_range(start, end)
*
- * Ensure coherency between the Icache and the Dcache in the
+ * Ensure coherency between the I cache and the D cache in the
* region described by start. If you have non-snooping
* Harvard caches, you need to implement this function.
*
@@ -222,34 +220,34 @@ ENTRY(xsc3_coherent_kern_range)
/* FALLTHROUGH */
ENTRY(xsc3_coherent_user_range)
bic r0, r0, #CACHELINESIZE - 1
-1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line
add r0, r0, #CACHELINESIZE
cmp r0, r1
blo 1b
mov r0, #0
- mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB
- mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
- mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate L1 I cache and BTB
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
+ mcr p15, 0, r0, c7, c5, 4 @ prefetch flush
mov pc, lr
/*
* flush_kern_dcache_page(void *page)
*
* Ensure no D cache aliasing occurs, either with itself or
- * the I cache
+ * the I cache.
*
* - addr - page aligned address
*/
ENTRY(xsc3_flush_kern_dcache_page)
add r1, r0, #PAGE_SZ
-1: mcr p15, 0, r0, c7, c14, 1 @ Clean/Invalidate D Cache line
+1: mcr p15, 0, r0, c7, c14, 1 @ clean/invalidate L1 D line
add r0, r0, #CACHELINESIZE
cmp r0, r1
blo 1b
mov r0, #0
- mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB
- mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
- mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate L1 I cache and BTB
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
+ mcr p15, 0, r0, c7, c5, 4 @ prefetch flush
mov pc, lr
/*
@@ -266,17 +264,17 @@ ENTRY(xsc3_flush_kern_dcache_page)
ENTRY(xsc3_dma_inv_range)
tst r0, #CACHELINESIZE - 1
bic r0, r0, #CACHELINESIZE - 1
- mcrne p15, 0, r0, c7, c10, 1 @ clean L1 D entry
- mcrne p15, 1, r0, c7, c11, 1 @ clean L2 D entry
+ mcrne p15, 0, r0, c7, c10, 1 @ clean L1 D line
+ mcrne p15, 1, r0, c7, c11, 1 @ clean L2 line
tst r1, #CACHELINESIZE - 1
- mcrne p15, 0, r1, c7, c10, 1 @ clean L1 D entry
- mcrne p15, 1, r1, c7, c11, 1 @ clean L2 D entry
-1: mcr p15, 0, r0, c7, c6, 1 @ invalidate L1 D entry
- mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line
+ mcrne p15, 0, r1, c7, c10, 1 @ clean L1 D line
+ mcrne p15, 1, r1, c7, c11, 1 @ clean L2 line
+1: mcr p15, 0, r0, c7, c6, 1 @ invalidate L1 D line
+ mcr p15, 1, r0, c7, c7, 1 @ invalidate L2 line
add r0, r0, #CACHELINESIZE
cmp r0, r1
blo 1b
- mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
mov pc, lr
/*
@@ -289,12 +287,12 @@ ENTRY(xsc3_dma_inv_range)
*/
ENTRY(xsc3_dma_clean_range)
bic r0, r0, #CACHELINESIZE - 1
-1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D entry
- mcr p15, 1, r0, c7, c11, 1 @ clean L2 D entry
+1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line
+ mcr p15, 1, r0, c7, c11, 1 @ clean L2 line
add r0, r0, #CACHELINESIZE
cmp r0, r1
blo 1b
- mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
mov pc, lr
/*
@@ -307,13 +305,13 @@ ENTRY(xsc3_dma_clean_range)
*/
ENTRY(xsc3_dma_flush_range)
bic r0, r0, #CACHELINESIZE - 1
-1: mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate L1 D cache line
- mcr p15, 1, r0, c7, c11, 1 @ Clean L2 D cache line
- mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line
+1: mcr p15, 0, r0, c7, c14, 1 @ clean/invalidate L1 D line
+ mcr p15, 1, r0, c7, c11, 1 @ clean L2 line
+ mcr p15, 1, r0, c7, c7, 1 @ invalidate L2 line
add r0, r0, #CACHELINESIZE
cmp r0, r1
blo 1b
- mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
mov pc, lr
ENTRY(xsc3_cache_fns)
@@ -328,7 +326,7 @@ ENTRY(xsc3_cache_fns)
.long xsc3_dma_flush_range
ENTRY(cpu_xsc3_dcache_clean_area)
-1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line
add r0, r0, #CACHELINESIZE
subs r1, r1, #CACHELINESIZE
bhi 1b
@@ -346,14 +344,14 @@ ENTRY(cpu_xsc3_dcache_clean_area)
.align 5
ENTRY(cpu_xsc3_switch_mm)
clean_d_cache r1, r2
- mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
- mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
- mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush
+ mcr p15, 0, ip, c7, c5, 0 @ invalidate L1 I cache and BTB
+ mcr p15, 0, ip, c7, c10, 4 @ data write barrier
+ mcr p15, 0, ip, c7, c5, 4 @ prefetch flush
#ifdef L2_CACHE_ENABLE
orr r0, r0, #0x18 @ cache the page table in L2
#endif
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
- mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I and D TLBs
cpwait_ret lr, ip
/*
@@ -366,34 +364,34 @@ ENTRY(cpu_xsc3_switch_mm)
ENTRY(cpu_xsc3_set_pte_ext)
str r1, [r0], #-2048 @ linux version
- bic r2, r1, #0xff0 @ Keep C, B bits
+ bic r2, r1, #0xff0 @ keep C, B bits
orr r2, r2, #PTE_TYPE_EXT @ extended page
- tst r1, #L_PTE_SHARED @ Shared?
+ tst r1, #L_PTE_SHARED @ shared?
orrne r2, r2, #0x200
eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
- tst r3, #L_PTE_USER @ User?
+ tst r3, #L_PTE_USER @ user?
orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w
- tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty?
+ tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ write and dirty?
orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w
@ combined with user -> user r/w
#if L2_CACHE_ENABLE
- @ If its cacheable it needs to be in L2 also.
+ @ If it's cacheable, it needs to be in L2 also.
eor ip, r1, #L_PTE_CACHEABLE
tst ip, #L_PTE_CACHEABLE
orreq r2, r2, #PTE_EXT_TEX(0x5)
#endif
- tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
+ tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young?
movne r2, #0 @ no -> fault
str r2, [r0] @ hardware version
mov ip, #0
- mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line mcr
- mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
+ mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line
+ mcr p15, 0, ip, c7, c10, 4 @ data write barrier
mov pc, lr
.ltorg
@@ -406,17 +404,18 @@ ENTRY(cpu_xsc3_set_pte_ext)
__xsc3_setup:
mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
msr cpsr_c, r0
- mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB
- mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer
- mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush
- mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs
+ mcr p15, 0, ip, c7, c7, 0 @ invalidate L1 caches and BTB
+ mcr p15, 0, ip, c7, c10, 4 @ data write barrier
+ mcr p15, 0, ip, c7, c5, 4 @ prefetch flush
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I and D TLBs
#if L2_CACHE_ENABLE
orr r4, r4, #0x18 @ cache the page table in L2
#endif
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
- mov r0, #1 @ Allow access to CP0 and CP13
- orr r0, r0, #1 << 13 @ Its undefined whether this
- mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes
+
+ mov r0, #0 @ don't allow CP access
+ mcr p15, 0, r0, c15, c1, 0 @ write CP access register
+
mrc p15, 0, r0, c1, c0, 1 @ get auxiliary control reg
and r0, r0, #2 @ preserve bit P bit setting
#if L2_CACHE_ENABLE
@@ -427,9 +426,9 @@ __xsc3_setup:
adr r5, xsc3_crval
ldmia r5, {r5, r6}
mrc p15, 0, r0, c1, c0, 0 @ get control register
- bic r0, r0, r5 @ .... .... .... ..A.
- orr r0, r0, r6 @ .... .... .... .C.M
- orr r0, r0, #0x00000800 @ ..VI Z..S .... ....
+ bic r0, r0, r5 @ ..V. ..R. .... ..A.
+ orr r0, r0, r6 @ ..VI Z..S .... .C.M (mmu)
+ @ ...I Z..S .... .... (uc)
#if L2_CACHE_ENABLE
orr r0, r0, #0x04000000 @ L2 enable
#endif
@@ -439,7 +438,7 @@ __xsc3_setup:
.type xsc3_crval, #object
xsc3_crval:
- crval clear=0x04003b02, mmuset=0x00003105, ucset=0x00001100
+ crval clear=0x04002202, mmuset=0x00003905, ucset=0x00001900
__INITDATA
@@ -474,7 +473,7 @@ cpu_elf_name:
.type cpu_xsc3_name, #object
cpu_xsc3_name:
- .asciz "XScale-Core3"
+ .asciz "XScale-V3 based processor"
.size cpu_xsc3_name, . - cpu_xsc3_name
.align
@@ -490,7 +489,7 @@ __xsc3_proc_info:
PMD_SECT_CACHEABLE | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ
- .long PMD_TYPE_SECT | \
+ .long PMD_TYPE_SECT | \
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ
b __xsc3_setup
diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S
index fd6adde3909..20f84bbaa9b 100644
--- a/arch/arm/mm/tlb-v6.S
+++ b/arch/arm/mm/tlb-v6.S
@@ -53,6 +53,8 @@ ENTRY(v6wbi_flush_user_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
+ mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB
+ mcr p15, 0, ip, c7, c10, 4 @ data synchronization barrier
mov pc, lr
/*
@@ -80,7 +82,9 @@ ENTRY(v6wbi_flush_kern_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
+ mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
mcr p15, 0, r2, c7, c10, 4 @ data synchronization barrier
+ mcr p15, 0, r2, c7, c5, 4 @ prefetch flush
mov pc, lr
.section ".text.init", #alloc, #execinstr
diff --git a/arch/arm/oprofile/Kconfig b/arch/arm/oprofile/Kconfig
index 19d37730b66..afd93ad02fe 100644
--- a/arch/arm/oprofile/Kconfig
+++ b/arch/arm/oprofile/Kconfig
@@ -19,5 +19,24 @@ config OPROFILE
If unsure, say N.
+if OPROFILE
+
+config OPROFILE_ARMV6
+ bool
+ depends on CPU_V6 && !SMP
+ default y
+ select OPROFILE_ARM11_CORE
+
+config OPROFILE_MPCORE
+ bool
+ depends on CPU_V6 && SMP
+ default y
+ select OPROFILE_ARM11_CORE
+
+config OPROFILE_ARM11_CORE
+ bool
+
+endif
+
endmenu
diff --git a/arch/arm/oprofile/Makefile b/arch/arm/oprofile/Makefile
index 6a94e54848f..e61d0cc520b 100644
--- a/arch/arm/oprofile/Makefile
+++ b/arch/arm/oprofile/Makefile
@@ -8,4 +8,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
oprofile-$(CONFIG_CPU_XSCALE) += op_model_xscale.o
-
+oprofile-$(CONFIG_OPROFILE_ARM11_CORE) += op_model_arm11_core.o
+oprofile-$(CONFIG_OPROFILE_ARMV6) += op_model_v6.o
+oprofile-$(CONFIG_OPROFILE_MPCORE) += op_model_mpcore.o
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
index 6f833358cd0..0a007b931f6 100644
--- a/arch/arm/oprofile/common.c
+++ b/arch/arm/oprofile/common.c
@@ -135,6 +135,14 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
spec = &op_xscale_spec;
#endif
+#ifdef CONFIG_OPROFILE_ARMV6
+ spec = &op_armv6_spec;
+#endif
+
+#ifdef CONFIG_OPROFILE_MPCORE
+ spec = &op_mpcore_spec;
+#endif
+
if (spec) {
ret = spec->init();
if (ret < 0)
diff --git a/arch/arm/oprofile/op_arm_model.h b/arch/arm/oprofile/op_arm_model.h
index 38c6ad15854..4899c629aa0 100644
--- a/arch/arm/oprofile/op_arm_model.h
+++ b/arch/arm/oprofile/op_arm_model.h
@@ -24,6 +24,9 @@ struct op_arm_model_spec {
extern struct op_arm_model_spec op_xscale_spec;
#endif
+extern struct op_arm_model_spec op_armv6_spec;
+extern struct op_arm_model_spec op_mpcore_spec;
+
extern void arm_backtrace(struct pt_regs * const regs, unsigned int depth);
extern int __init op_arm_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec);
diff --git a/arch/arm/oprofile/op_model_arm11_core.c b/arch/arm/oprofile/op_model_arm11_core.c
new file mode 100644
index 00000000000..ad80752cb9f
--- /dev/null
+++ b/arch/arm/oprofile/op_model_arm11_core.c
@@ -0,0 +1,162 @@
+/**
+ * @file op_model_arm11_core.c
+ * ARM11 Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+
+#include "op_counter.h"
+#include "op_arm_model.h"
+#include "op_model_arm11_core.h"
+
+/*
+ * ARM11 PMU support
+ */
+static inline void arm11_write_pmnc(u32 val)
+{
+ /* upper 4bits and 7, 11 are write-as-0 */
+ val &= 0x0ffff77f;
+ asm volatile("mcr p15, 0, %0, c15, c12, 0" : : "r" (val));
+}
+
+static inline u32 arm11_read_pmnc(void)
+{
+ u32 val;
+ asm volatile("mrc p15, 0, %0, c15, c12, 0" : "=r" (val));
+ return val;
+}
+
+static void arm11_reset_counter(unsigned int cnt)
+{
+ u32 val = -(u32)counter_config[CPU_COUNTER(smp_processor_id(), cnt)].count;
+ switch (cnt) {
+ case CCNT:
+ asm volatile("mcr p15, 0, %0, c15, c12, 1" : : "r" (val));
+ break;
+
+ case PMN0:
+ asm volatile("mcr p15, 0, %0, c15, c12, 2" : : "r" (val));
+ break;
+
+ case PMN1:
+ asm volatile("mcr p15, 0, %0, c15, c12, 3" : : "r" (val));
+ break;
+ }
+}
+
+int arm11_setup_pmu(void)
+{
+ unsigned int cnt;
+ u32 pmnc;
+
+ if (arm11_read_pmnc() & PMCR_E) {
+ printk(KERN_ERR "oprofile: CPU%u PMU still enabled when setup new event counter.\n", smp_processor_id());
+ return -EBUSY;
+ }
+
+ /* initialize PMNC, reset overflow, D bit, C bit and P bit. */
+ arm11_write_pmnc(PMCR_OFL_PMN0 | PMCR_OFL_PMN1 | PMCR_OFL_CCNT |
+ PMCR_C | PMCR_P);
+
+ for (pmnc = 0, cnt = PMN0; cnt <= CCNT; cnt++) {
+ unsigned long event;
+
+ if (!counter_config[CPU_COUNTER(smp_processor_id(), cnt)].enabled)
+ continue;
+
+ event = counter_config[CPU_COUNTER(smp_processor_id(), cnt)].event & 255;
+
+ /*
+ * Set event (if destined for PMNx counters)
+ */
+ if (cnt == PMN0) {
+ pmnc |= event << 20;
+ } else if (cnt == PMN1) {
+ pmnc |= event << 12;
+ }
+
+ /*
+ * We don't need to set the event if it's a cycle count
+ * Enable interrupt for this counter
+ */
+ pmnc |= PMCR_IEN_PMN0 << cnt;
+ arm11_reset_counter(cnt);
+ }
+ arm11_write_pmnc(pmnc);
+
+ return 0;
+}
+
+int arm11_start_pmu(void)
+{
+ arm11_write_pmnc(arm11_read_pmnc() | PMCR_E);
+ return 0;
+}
+
+int arm11_stop_pmu(void)
+{
+ unsigned int cnt;
+
+ arm11_write_pmnc(arm11_read_pmnc() & ~PMCR_E);
+
+ for (cnt = PMN0; cnt <= CCNT; cnt++)
+ arm11_reset_counter(cnt);
+
+ return 0;
+}
+
+/*
+ * CPU counters' IRQ handler (one IRQ per CPU)
+ */
+static irqreturn_t arm11_pmu_interrupt(int irq, void *arg)
+{
+ struct pt_regs *regs = get_irq_regs();
+ unsigned int cnt;
+ u32 pmnc;
+
+ pmnc = arm11_read_pmnc();
+
+ for (cnt = PMN0; cnt <= CCNT; cnt++) {
+ if ((pmnc & (PMCR_OFL_PMN0 << cnt)) && (pmnc & (PMCR_IEN_PMN0 << cnt))) {
+ arm11_reset_counter(cnt);
+ oprofile_add_sample(regs, CPU_COUNTER(smp_processor_id(), cnt));
+ }
+ }
+ /* Clear counter flag(s) */
+ arm11_write_pmnc(pmnc);
+ return IRQ_HANDLED;
+}
+
+int arm11_request_interrupts(int *irqs, int nr)
+{
+ unsigned int i;
+ int ret = 0;
+
+ for(i = 0; i < nr; i++) {
+ ret = request_irq(irqs[i], arm11_pmu_interrupt, IRQF_DISABLED, "CP15 PMU", NULL);
+ if (ret != 0) {
+ printk(KERN_ERR "oprofile: unable to request IRQ%u for MPCORE-EM\n",
+ irqs[i]);
+ break;
+ }
+ }
+
+ if (i != nr)
+ while (i-- != 0)
+ free_irq(irqs[i], NULL);
+
+ return ret;
+}
+
+void arm11_release_interrupts(int *irqs, int nr)
+{
+ unsigned int i;
+
+ for (i = 0; i < nr; i++)
+ free_irq(irqs[i], NULL);
+}
diff --git a/arch/arm/oprofile/op_model_arm11_core.h b/arch/arm/oprofile/op_model_arm11_core.h
new file mode 100644
index 00000000000..6f8538e5a96
--- /dev/null
+++ b/arch/arm/oprofile/op_model_arm11_core.h
@@ -0,0 +1,45 @@
+/**
+ * @file op_model_arm11_core.h
+ * ARM11 Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 Oprofile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Zwane Mwaikambo
+ */
+#ifndef OP_MODEL_ARM11_CORE_H
+#define OP_MODEL_ARM11_CORE_H
+
+/*
+ * Per-CPU PMCR
+ */
+#define PMCR_E (1 << 0) /* Enable */
+#define PMCR_P (1 << 1) /* Count reset */
+#define PMCR_C (1 << 2) /* Cycle counter reset */
+#define PMCR_D (1 << 3) /* Cycle counter counts every 64th cpu cycle */
+#define PMCR_IEN_PMN0 (1 << 4) /* Interrupt enable count reg 0 */
+#define PMCR_IEN_PMN1 (1 << 5) /* Interrupt enable count reg 1 */
+#define PMCR_IEN_CCNT (1 << 6) /* Interrupt enable cycle counter */
+#define PMCR_OFL_PMN0 (1 << 8) /* Count reg 0 overflow */
+#define PMCR_OFL_PMN1 (1 << 9) /* Count reg 1 overflow */
+#define PMCR_OFL_CCNT (1 << 10) /* Cycle counter overflow */
+
+#define PMN0 0
+#define PMN1 1
+#define CCNT 2
+
+#define CPU_COUNTER(cpu, counter) ((cpu) * 3 + (counter))
+
+int arm11_setup_pmu(void);
+int arm11_start_pmu(void);
+int arm11_stop_pmu(void);
+int arm11_request_interrupts(int *, int);
+void arm11_release_interrupts(int *, int);
+
+#endif
diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c
new file mode 100644
index 00000000000..89850071824
--- /dev/null
+++ b/arch/arm/oprofile/op_model_mpcore.c
@@ -0,0 +1,296 @@
+/**
+ * @file op_model_mpcore.c
+ * MPCORE Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 Oprofile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Zwane Mwaikambo
+ *
+ * Counters:
+ * 0: PMN0 on CPU0, per-cpu configurable event counter
+ * 1: PMN1 on CPU0, per-cpu configurable event counter
+ * 2: CCNT on CPU0
+ * 3: PMN0 on CPU1
+ * 4: PMN1 on CPU1
+ * 5: CCNT on CPU1
+ * 6: PMN0 on CPU1
+ * 7: PMN1 on CPU1
+ * 8: CCNT on CPU1
+ * 9: PMN0 on CPU1
+ * 10: PMN1 on CPU1
+ * 11: CCNT on CPU1
+ * 12-19: configurable SCU event counters
+ */
+
+/* #define DEBUG */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/hardware.h>
+#include <asm/system.h>
+
+#include "op_counter.h"
+#include "op_arm_model.h"
+#include "op_model_arm11_core.h"
+#include "op_model_mpcore.h"
+
+/*
+ * MPCore SCU event monitor support
+ */
+#define SCU_EVENTMONITORS_VA_BASE __io_address(REALVIEW_MPCORE_SCU_BASE + 0x10)
+
+/*
+ * Bitmask of used SCU counters
+ */
+static unsigned int scu_em_used;
+
+/*
+ * 2 helper fns take a counter number from 0-7 (not the userspace-visible counter number)
+ */
+static inline void scu_reset_counter(struct eventmonitor __iomem *emc, unsigned int n)
+{
+ writel(-(u32)counter_config[SCU_COUNTER(n)].count, &emc->MC[n]);
+}
+
+static inline void scu_set_event(struct eventmonitor __iomem *emc, unsigned int n, u32 event)
+{
+ event &= 0xff;
+ writeb(event, &emc->MCEB[n]);
+}
+
+/*
+ * SCU counters' IRQ handler (one IRQ per counter => 2 IRQs per CPU)
+ */
+static irqreturn_t scu_em_interrupt(int irq, void *arg)
+{
+ struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+ unsigned int cnt;
+
+ cnt = irq - IRQ_PMU_SCU0;
+ oprofile_add_sample(get_irq_regs(), SCU_COUNTER(cnt));
+ scu_reset_counter(emc, cnt);
+
+ /* Clear overflow flag for this counter */
+ writel(1 << (cnt + 16), &emc->PMCR);
+
+ return IRQ_HANDLED;
+}
+
+/* Configure just the SCU counters that the user has requested */
+static void scu_setup(void)
+{
+ struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+ unsigned int i;
+
+ scu_em_used = 0;
+
+ for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+ if (counter_config[SCU_COUNTER(i)].enabled &&
+ counter_config[SCU_COUNTER(i)].event) {
+ scu_set_event(emc, i, 0); /* disable counter for now */
+ scu_em_used |= 1 << i;
+ }
+ }
+}
+
+static int scu_start(void)
+{
+ struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+ unsigned int temp, i;
+ unsigned long event;
+ int ret = 0;
+
+ /*
+ * request the SCU counter interrupts that we need
+ */
+ for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+ if (scu_em_used & (1 << i)) {
+ ret = request_irq(IRQ_PMU_SCU0 + i, scu_em_interrupt, IRQF_DISABLED, "SCU PMU", NULL);
+ if (ret) {
+ printk(KERN_ERR "oprofile: unable to request IRQ%u for SCU Event Monitor\n",
+ IRQ_PMU_SCU0 + i);
+ goto err_free_scu;
+ }
+ }
+ }
+
+ /*
+ * clear overflow and enable interrupt for all used counters
+ */
+ temp = readl(&emc->PMCR);
+ for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+ if (scu_em_used & (1 << i)) {
+ scu_reset_counter(emc, i);
+ event = counter_config[SCU_COUNTER(i)].event;
+ scu_set_event(emc, i, event);
+
+ /* clear overflow/interrupt */
+ temp |= 1 << (i + 16);
+ /* enable interrupt*/
+ temp |= 1 << (i + 8);
+ }
+ }
+
+ /* Enable all 8 counters */
+ temp |= PMCR_E;
+ writel(temp, &emc->PMCR);
+
+ return 0;
+
+ err_free_scu:
+ while (i--)
+ free_irq(IRQ_PMU_SCU0 + i, NULL);
+ return ret;
+}
+
+static void scu_stop(void)
+{
+ struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
+ unsigned int temp, i;
+
+ /* Disable counter interrupts */
+ /* Don't disable all 8 counters (with the E bit) as they may be in use */
+ temp = readl(&emc->PMCR);
+ for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+ if (scu_em_used & (1 << i))
+ temp &= ~(1 << (i + 8));
+ }
+ writel(temp, &emc->PMCR);
+
+ /* Free counter interrupts and reset counters */
+ for (i = 0; i < NUM_SCU_COUNTERS; i++) {
+ if (scu_em_used & (1 << i)) {
+ scu_reset_counter(emc, i);
+ free_irq(IRQ_PMU_SCU0 + i, NULL);
+ }
+ }
+}
+
+struct em_function_data {
+ int (*fn)(void);
+ int ret;
+};
+
+static void em_func(void *data)
+{
+ struct em_function_data *d = data;
+ int ret = d->fn();
+ if (ret)
+ d->ret = ret;
+}
+
+static int em_call_function(int (*fn)(void))
+{
+ struct em_function_data data;
+
+ data.fn = fn;
+ data.ret = 0;
+
+ smp_call_function(em_func, &data, 1, 1);
+ em_func(&data);
+
+ return data.ret;
+}
+
+/*
+ * Glue to stick the individual ARM11 PMUs and the SCU
+ * into the oprofile framework.
+ */
+static int em_setup_ctrs(void)
+{
+ int ret;
+
+ /* Configure CPU counters by cross-calling to the other CPUs */
+ ret = em_call_function(arm11_setup_pmu);
+ if (ret == 0)
+ scu_setup();
+
+ return 0;
+}
+
+static int arm11_irqs[] = {
+ [0] = IRQ_PMU_CPU0,
+ [1] = IRQ_PMU_CPU1,
+ [2] = IRQ_PMU_CPU2,
+ [3] = IRQ_PMU_CPU3
+};
+
+static int em_start(void)
+{
+ int ret;
+
+ ret = arm11_request_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs));
+ if (ret == 0) {
+ em_call_function(arm11_start_pmu);
+
+ ret = scu_start();
+ if (ret)
+ arm11_release_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs));
+ }
+ return ret;
+}
+
+static void em_stop(void)
+{
+ em_call_function(arm11_stop_pmu);
+ arm11_release_interrupts(arm11_irqs, ARRAY_SIZE(arm11_irqs));
+ scu_stop();
+}
+
+/*
+ * Why isn't there a function to route an IRQ to a specific CPU in
+ * genirq?
+ */
+static void em_route_irq(int irq, unsigned int cpu)
+{
+ irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+ irq_desc[irq].chip->set_affinity(irq, cpumask_of_cpu(cpu));
+}
+
+static int em_setup(void)
+{
+ /*
+ * Send SCU PMU interrupts to the "owner" CPU.
+ */
+ em_route_irq(IRQ_PMU_SCU0, 0);
+ em_route_irq(IRQ_PMU_SCU1, 0);
+ em_route_irq(IRQ_PMU_SCU2, 1);
+ em_route_irq(IRQ_PMU_SCU3, 1);
+ em_route_irq(IRQ_PMU_SCU4, 2);
+ em_route_irq(IRQ_PMU_SCU5, 2);
+ em_route_irq(IRQ_PMU_SCU6, 3);
+ em_route_irq(IRQ_PMU_SCU7, 3);
+
+ /*
+ * Send CP15 PMU interrupts to the owner CPU.
+ */
+ em_route_irq(IRQ_PMU_CPU0, 0);
+ em_route_irq(IRQ_PMU_CPU1, 1);
+ em_route_irq(IRQ_PMU_CPU2, 2);
+ em_route_irq(IRQ_PMU_CPU3, 3);
+
+ return 0;
+}
+
+struct op_arm_model_spec op_mpcore_spec = {
+ .init = em_setup,
+ .num_counters = MPCORE_NUM_COUNTERS,
+ .setup_ctrs = em_setup_ctrs,
+ .start = em_start,
+ .stop = em_stop,
+ .name = "arm/mpcore",
+};
diff --git a/arch/arm/oprofile/op_model_mpcore.h b/arch/arm/oprofile/op_model_mpcore.h
new file mode 100644
index 00000000000..73d81102368
--- /dev/null
+++ b/arch/arm/oprofile/op_model_mpcore.h
@@ -0,0 +1,61 @@
+/**
+ * @file op_model_mpcore.c
+ * MPCORE Event Monitor Driver
+ * @remark Copyright 2004 ARM SMP Development Team
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 Oprofile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Zwane Mwaikambo
+ */
+#ifndef OP_MODEL_MPCORE_H
+#define OP_MODEL_MPCORE_H
+
+struct eventmonitor {
+ unsigned long PMCR;
+ unsigned char MCEB[8];
+ unsigned long MC[8];
+};
+
+/*
+ * List of userspace counter numbers: note that the structure is important.
+ * The code relies on CPUn's counters being CPU0's counters + 3n
+ * and on CPU0's counters starting at 0
+ */
+
+#define COUNTER_CPU0_PMN0 0
+#define COUNTER_CPU0_PMN1 1
+#define COUNTER_CPU0_CCNT 2
+
+#define COUNTER_CPU1_PMN0 3
+#define COUNTER_CPU1_PMN1 4
+#define COUNTER_CPU1_CCNT 5
+
+#define COUNTER_CPU2_PMN0 6
+#define COUNTER_CPU2_PMN1 7
+#define COUNTER_CPU2_CCNT 8
+
+#define COUNTER_CPU3_PMN0 9
+#define COUNTER_CPU3_PMN1 10
+#define COUNTER_CPU3_CCNT 11
+
+#define COUNTER_SCU_MN0 12
+#define COUNTER_SCU_MN1 13
+#define COUNTER_SCU_MN2 14
+#define COUNTER_SCU_MN3 15
+#define COUNTER_SCU_MN4 16
+#define COUNTER_SCU_MN5 17
+#define COUNTER_SCU_MN6 18
+#define COUNTER_SCU_MN7 19
+#define NUM_SCU_COUNTERS 8
+
+#define SCU_COUNTER(number) ((number) + COUNTER_SCU_MN0)
+
+#define MPCORE_NUM_COUNTERS SCU_COUNTER(NUM_SCU_COUNTERS)
+
+#endif
diff --git a/arch/arm/oprofile/op_model_v6.c b/arch/arm/oprofile/op_model_v6.c
new file mode 100644
index 00000000000..fe581383d3e
--- /dev/null
+++ b/arch/arm/oprofile/op_model_v6.c
@@ -0,0 +1,67 @@
+/**
+ * @file op_model_v6.c
+ * ARM11 Performance Monitor Driver
+ *
+ * Based on op_model_xscale.c
+ *
+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
+ * @remark Copyright 2000-2004 MontaVista Software Inc
+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
+ * @remark Copyright 2004 Intel Corporation
+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ * @remark Copyright 2004 OProfile Authors
+ *
+ * @remark Read the file COPYING
+ *
+ * @author Tony Lindgren <tony@atomide.com>
+ */
+
+/* #define DEBUG */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "op_counter.h"
+#include "op_arm_model.h"
+#include "op_model_arm11_core.h"
+
+static int irqs[] = {
+#ifdef CONFIG_ARCH_OMAP2
+ 3,
+#endif
+};
+
+static void armv6_pmu_stop(void)
+{
+ arm11_stop_pmu();
+ arm11_release_interrupts(irqs, ARRAY_SIZE(irqs));
+}
+
+static int armv6_pmu_start(void)
+{
+ int ret;
+
+ ret = arm11_request_interrupts(irqs, ARRAY_SIZE(irqs));
+ if (ret >= 0)
+ ret = arm11_start_pmu();
+
+ return ret;
+}
+
+static int armv6_detect_pmu(void)
+{
+ return 0;
+}
+
+struct op_arm_model_spec op_armv6_spec = {
+ .init = armv6_detect_pmu,
+ .num_counters = 3,
+ .setup_ctrs = arm11_setup_pmu,
+ .start = armv6_pmu_start,
+ .stop = armv6_pmu_stop,
+ .name = "arm/armv6",
+};
diff --git a/arch/arm/plat-iop/Makefile b/arch/arm/plat-iop/Makefile
index 23da00b1151..3250d732a17 100644
--- a/arch/arm/plat-iop/Makefile
+++ b/arch/arm/plat-iop/Makefile
@@ -2,7 +2,29 @@
# Makefile for the linux kernel.
#
-obj-y := gpio.o i2c.o pci.o setup.o time.o
-obj-m :=
-obj-n :=
-obj- :=
+obj-y :=
+
+# IOP32X
+obj-$(CONFIG_ARCH_IOP32X) += gpio.o
+obj-$(CONFIG_ARCH_IOP32X) += i2c.o
+obj-$(CONFIG_ARCH_IOP32X) += pci.o
+obj-$(CONFIG_ARCH_IOP32X) += setup.o
+obj-$(CONFIG_ARCH_IOP32X) += time.o
+obj-$(CONFIG_ARCH_IOP32X) += io.o
+obj-$(CONFIG_ARCH_IOP32X) += cp6.o
+
+# IOP33X
+obj-$(CONFIG_ARCH_IOP33X) += gpio.o
+obj-$(CONFIG_ARCH_IOP33X) += i2c.o
+obj-$(CONFIG_ARCH_IOP33X) += pci.o
+obj-$(CONFIG_ARCH_IOP33X) += setup.o
+obj-$(CONFIG_ARCH_IOP33X) += time.o
+obj-$(CONFIG_ARCH_IOP33X) += io.o
+obj-$(CONFIG_ARCH_IOP33X) += cp6.o
+
+# IOP13XX
+obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
+
+obj-m :=
+obj-n :=
+obj- :=
diff --git a/arch/arm/plat-iop/cp6.c b/arch/arm/plat-iop/cp6.c
new file mode 100644
index 00000000000..9612a87e2a8
--- /dev/null
+++ b/arch/arm/plat-iop/cp6.c
@@ -0,0 +1,50 @@
+/*
+ * IOP Coprocessor-6 access handler
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#include <linux/init.h>
+#include <asm/traps.h>
+
+static int cp6_trap(struct pt_regs *regs, unsigned int instr)
+{
+ u32 temp;
+
+ /* enable cp6 access */
+ asm volatile (
+ "mrc p15, 0, %0, c15, c1, 0\n\t"
+ "orr %0, %0, #(1 << 6)\n\t"
+ "mcr p15, 0, %0, c15, c1, 0\n\t"
+ : "=r"(temp));
+
+ return 0;
+}
+
+/* permit kernel space cp6 access
+ * deny user space cp6 access
+ */
+static struct undef_hook cp6_hook = {
+ .instr_mask = 0x0f000ff0,
+ .instr_val = 0x0e000610,
+ .cpsr_mask = MODE_MASK,
+ .cpsr_val = SVC_MODE,
+ .fn = cp6_trap,
+};
+
+void __init iop_init_cp6_handler(void)
+{
+ register_undef_hook(&cp6_hook);
+}
diff --git a/arch/arm/plat-iop/io.c b/arch/arm/plat-iop/io.c
new file mode 100644
index 00000000000..f7eccecf2e4
--- /dev/null
+++ b/arch/arm/plat-iop/io.c
@@ -0,0 +1,58 @@
+/*
+ * iop3xx custom ioremap implementation
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+void * __iomem __iop3xx_ioremap(unsigned long cookie, size_t size,
+ unsigned long flags)
+{
+ void __iomem * retval;
+
+ switch (cookie) {
+ case IOP3XX_PCI_LOWER_IO_PA ... IOP3XX_PCI_UPPER_IO_PA:
+ retval = (void *) IOP3XX_PCI_IO_PHYS_TO_VIRT(cookie);
+ break;
+ case IOP3XX_PERIPHERAL_PHYS_BASE ... IOP3XX_PERIPHERAL_UPPER_PA:
+ retval = (void *) IOP3XX_PMMR_PHYS_TO_VIRT(cookie);
+ break;
+ default:
+ retval = __ioremap(cookie, size, flags);
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(__iop3xx_ioremap);
+
+void __iop3xx_iounmap(void __iomem *addr)
+{
+ extern void __iounmap(volatile void __iomem *addr);
+
+ switch ((u32) addr) {
+ case IOP3XX_PCI_LOWER_IO_VA ... IOP3XX_PCI_UPPER_IO_VA:
+ case IOP3XX_PERIPHERAL_VIRT_BASE ... IOP3XX_PERIPHERAL_UPPER_VA:
+ goto skip;
+ }
+ __iounmap(addr);
+
+skip:
+ return;
+}
+EXPORT_SYMBOL(__iop3xx_iounmap);
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
index e647812654f..b5f6ec35aaf 100644
--- a/arch/arm/plat-iop/pci.c
+++ b/arch/arm/plat-iop/pci.c
@@ -196,8 +196,8 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
if (!res)
panic("PCI: unable to alloc resources");
- res[0].start = IOP3XX_PCI_LOWER_IO_VA;
- res[0].end = IOP3XX_PCI_LOWER_IO_VA + IOP3XX_PCI_IO_WINDOW_SIZE - 1;
+ res[0].start = IOP3XX_PCI_LOWER_IO_PA;
+ res[0].end = IOP3XX_PCI_LOWER_IO_PA + IOP3XX_PCI_IO_WINDOW_SIZE - 1;
res[0].name = "IOP3XX PCI I/O Space";
res[0].flags = IORESOURCE_IO;
request_resource(&ioport_resource, &res[0]);
@@ -209,7 +209,7 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
request_resource(&iomem_resource, &res[1]);
sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - IOP3XX_PCI_LOWER_MEM_BA;
- sys->io_offset = IOP3XX_PCI_LOWER_IO_VA - IOP3XX_PCI_LOWER_IO_BA;
+ sys->io_offset = IOP3XX_PCI_LOWER_IO_PA - IOP3XX_PCI_LOWER_IO_BA;
sys->resource[0] = &res[0];
sys->resource[1] = &res[1];
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
new file mode 100644
index 00000000000..e2234316063
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -0,0 +1,99 @@
+# arch/arm/plat-s3c24xx/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config PLAT_S3C24XX
+ bool
+ depends on ARCH_S3C2410
+ default y if ARCH_S3C2410
+ help
+ Base platform code for any Samsung S3C device
+
+if PLAT_S3C24XX
+
+config CPU_S3C244X
+ bool
+ depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
+ help
+ Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
+
+config PM_SIMTEC
+ bool
+ help
+ Common power management code for systems that are
+ compatible with the Simtec style of power management
+
+config S3C2410_BOOT_WATCHDOG
+ bool "S3C2410 Initialisation watchdog"
+ depends on ARCH_S3C2410 && S3C2410_WATCHDOG
+ help
+ Say y to enable the watchdog during the kernel decompression
+ stage. If the kernel fails to uncompress, then the watchdog
+ will trigger a reset and the system should restart.
+
+config S3C2410_BOOT_ERROR_RESET
+ bool "S3C2410 Reboot on decompression error"
+ depends on ARCH_S3C2410
+ help
+ Say y here to use the watchdog to reset the system if the
+ kernel decompressor detects an error during decompression.
+
+config S3C2410_PM_DEBUG
+ bool "S3C2410 PM Suspend debug"
+ depends on ARCH_S3C2410 && PM
+ help
+ Say Y here if you want verbose debugging from the PM Suspend and
+ Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
+ for more information.
+
+config S3C2410_PM_CHECK
+ bool "S3C2410 PM Suspend Memory CRC"
+ depends on ARCH_S3C2410 && PM && CRC32
+ help
+ Enable the PM code's memory area checksum over sleep. This option
+ will generate CRCs of all blocks of memory, and store them before
+ going to sleep. The blocks are then checked on resume for any
+ errors.
+
+config S3C2410_PM_CHECK_CHUNKSIZE
+ int "S3C2410 PM Suspend CRC Chunksize (KiB)"
+ depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
+ default 64
+ help
+ Set the chunksize in Kilobytes of the CRC for checking memory
+ corruption over suspend and resume. A smaller value will mean that
+ the CRC data block will take more memory, but wil identify any
+ faults with better precision.
+
+config S3C2410_LOWLEVEL_UART_PORT
+ int "S3C2410 UART to use for low-level messages"
+ default 0
+ help
+ Choice of which UART port to use for the low-level messages,
+ such as the `Uncompressing...` at start time. The value of
+ this configuration should be between zero and two. The port
+ must have been initialised by the boot-loader before use.
+
+config S3C2410_DMA
+ bool "S3C2410 DMA support"
+ depends on ARCH_S3C2410
+ help
+ S3C2410 DMA support. This is needed for drivers like sound which
+ use the S3C2410's DMA system to move data to and from the
+ peripheral blocks.
+
+config S3C2410_DMA_DEBUG
+ bool "S3C2410 DMA support debug"
+ depends on ARCH_S3C2410 && S3C2410_DMA
+ help
+ Enable debugging output for the DMA code. This option sends info
+ to the kernel log, at priority KERN_DEBUG.
+
+config MACH_SMDK
+ bool
+ help
+ Common machine code for SMDK2410 and SMDK2440
+
+endif
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
new file mode 100644
index 00000000000..8e5ccaa1f03
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -0,0 +1,30 @@
+# arch/arm/plat-s3c24xx/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
+
+
+# Core files
+
+obj-y += cpu.o
+obj-y += irq.o
+obj-y += devs.o
+obj-y += gpio.o
+obj-y += time.o
+obj-y += clock.o
+
+# Architecture dependant builds
+
+obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
+obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o
+obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
+obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_PM) += sleep.o
+obj-$(CONFIG_S3C2410_DMA) += dma.o
+obj-$(CONFIG_MACH_SMDK) += common-smdk.o
diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c
new file mode 100644
index 00000000000..d3dc03a7383
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/clock.c
@@ -0,0 +1,449 @@
+/* linux/arch/arm/plat-s3c24xx/clock.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX Core clock control support
+ *
+ * Based on, and code from linux/arch/arm/mach-versatile/clock.c
+ **
+ ** Copyright (C) 2004 ARM Limited.
+ ** Written by Deep Blue Solutions Limited.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* clock information */
+
+static LIST_HEAD(clocks);
+
+DEFINE_MUTEX(clocks_mutex);
+
+/* enable and disable calls for use with the clk struct */
+
+static int clk_null_enable(struct clk *clk, int enable)
+{
+ return 0;
+}
+
+/* Clock API calls */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ struct clk *p;
+ struct clk *clk = ERR_PTR(-ENOENT);
+ int idno;
+
+ if (dev == NULL || dev->bus != &platform_bus_type)
+ idno = -1;
+ else
+ idno = to_platform_device(dev)->id;
+
+ mutex_lock(&clocks_mutex);
+
+ list_for_each_entry(p, &clocks, list) {
+ if (p->id == idno &&
+ strcmp(id, p->name) == 0 &&
+ try_module_get(p->owner)) {
+ clk = p;
+ break;
+ }
+ }
+
+ /* check for the case where a device was supplied, but the
+ * clock that was being searched for is not device specific */
+
+ if (IS_ERR(clk)) {
+ list_for_each_entry(p, &clocks, list) {
+ if (p->id == -1 && strcmp(id, p->name) == 0 &&
+ try_module_get(p->owner)) {
+ clk = p;
+ break;
+ }
+ }
+ }
+
+ mutex_unlock(&clocks_mutex);
+ return clk;
+}
+
+void clk_put(struct clk *clk)
+{
+ module_put(clk->owner);
+}
+
+int clk_enable(struct clk *clk)
+{
+ if (IS_ERR(clk) || clk == NULL)
+ return -EINVAL;
+
+ clk_enable(clk->parent);
+
+ mutex_lock(&clocks_mutex);
+
+ if ((clk->usage++) == 0)
+ (clk->enable)(clk, 1);
+
+ mutex_unlock(&clocks_mutex);
+ return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+ if (IS_ERR(clk) || clk == NULL)
+ return;
+
+ mutex_lock(&clocks_mutex);
+
+ if ((--clk->usage) == 0)
+ (clk->enable)(clk, 0);
+
+ mutex_unlock(&clocks_mutex);
+ clk_disable(clk->parent);
+}
+
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (IS_ERR(clk))
+ return 0;
+
+ if (clk->rate != 0)
+ return clk->rate;
+
+ if (clk->get_rate != NULL)
+ return (clk->get_rate)(clk);
+
+ if (clk->parent != NULL)
+ return clk_get_rate(clk->parent);
+
+ return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (!IS_ERR(clk) && clk->round_rate)
+ return (clk->round_rate)(clk, rate);
+
+ return rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret;
+
+ if (IS_ERR(clk))
+ return -EINVAL;
+
+ mutex_lock(&clocks_mutex);
+ ret = (clk->set_rate)(clk, rate);
+ mutex_unlock(&clocks_mutex);
+
+ return ret;
+}
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ return clk->parent;
+}
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ int ret = 0;
+
+ if (IS_ERR(clk))
+ return -EINVAL;
+
+ mutex_lock(&clocks_mutex);
+
+ if (clk->set_parent)
+ ret = (clk->set_parent)(clk, parent);
+
+ mutex_unlock(&clocks_mutex);
+
+ return ret;
+}
+
+EXPORT_SYMBOL(clk_get);
+EXPORT_SYMBOL(clk_put);
+EXPORT_SYMBOL(clk_enable);
+EXPORT_SYMBOL(clk_disable);
+EXPORT_SYMBOL(clk_get_rate);
+EXPORT_SYMBOL(clk_round_rate);
+EXPORT_SYMBOL(clk_set_rate);
+EXPORT_SYMBOL(clk_get_parent);
+EXPORT_SYMBOL(clk_set_parent);
+
+/* base clocks */
+
+struct clk clk_xtal = {
+ .name = "xtal",
+ .id = -1,
+ .rate = 0,
+ .parent = NULL,
+ .ctrlbit = 0,
+};
+
+struct clk clk_mpll = {
+ .name = "mpll",
+ .id = -1,
+};
+
+struct clk clk_upll = {
+ .name = "upll",
+ .id = -1,
+ .parent = NULL,
+ .ctrlbit = 0,
+};
+
+struct clk clk_f = {
+ .name = "fclk",
+ .id = -1,
+ .rate = 0,
+ .parent = &clk_mpll,
+ .ctrlbit = 0,
+};
+
+struct clk clk_h = {
+ .name = "hclk",
+ .id = -1,
+ .rate = 0,
+ .parent = NULL,
+ .ctrlbit = 0,
+};
+
+struct clk clk_p = {
+ .name = "pclk",
+ .id = -1,
+ .rate = 0,
+ .parent = NULL,
+ .ctrlbit = 0,
+};
+
+struct clk clk_usb_bus = {
+ .name = "usb-bus",
+ .id = -1,
+ .rate = 0,
+ .parent = &clk_upll,
+};
+
+/* clocks that could be registered by external code */
+
+static int s3c24xx_dclk_enable(struct clk *clk, int enable)
+{
+ unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
+
+ if (enable)
+ dclkcon |= clk->ctrlbit;
+ else
+ dclkcon &= ~clk->ctrlbit;
+
+ __raw_writel(dclkcon, S3C24XX_DCLKCON);
+
+ return 0;
+}
+
+static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
+{
+ unsigned long dclkcon;
+ unsigned int uclk;
+
+ if (parent == &clk_upll)
+ uclk = 1;
+ else if (parent == &clk_p)
+ uclk = 0;
+ else
+ return -EINVAL;
+
+ clk->parent = parent;
+
+ dclkcon = __raw_readl(S3C24XX_DCLKCON);
+
+ if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
+ if (uclk)
+ dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
+ else
+ dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
+ } else {
+ if (uclk)
+ dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
+ else
+ dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
+ }
+
+ __raw_writel(dclkcon, S3C24XX_DCLKCON);
+
+ return 0;
+}
+
+
+static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
+{
+ unsigned long mask;
+ unsigned long source;
+
+ /* calculate the MISCCR setting for the clock */
+
+ if (parent == &clk_xtal)
+ source = S3C2410_MISCCR_CLK0_MPLL;
+ else if (parent == &clk_upll)
+ source = S3C2410_MISCCR_CLK0_UPLL;
+ else if (parent == &clk_f)
+ source = S3C2410_MISCCR_CLK0_FCLK;
+ else if (parent == &clk_h)
+ source = S3C2410_MISCCR_CLK0_HCLK;
+ else if (parent == &clk_p)
+ source = S3C2410_MISCCR_CLK0_PCLK;
+ else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
+ source = S3C2410_MISCCR_CLK0_DCLK0;
+ else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1)
+ source = S3C2410_MISCCR_CLK0_DCLK0;
+ else
+ return -EINVAL;
+
+ clk->parent = parent;
+
+ if (clk == &s3c24xx_dclk0)
+ mask = S3C2410_MISCCR_CLK0_MASK;
+ else {
+ source <<= 4;
+ mask = S3C2410_MISCCR_CLK1_MASK;
+ }
+
+ s3c2410_modify_misccr(mask, source);
+ return 0;
+}
+
+/* external clock definitions */
+
+struct clk s3c24xx_dclk0 = {
+ .name = "dclk0",
+ .id = -1,
+ .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
+ .enable = s3c24xx_dclk_enable,
+ .set_parent = s3c24xx_dclk_setparent,
+};
+
+struct clk s3c24xx_dclk1 = {
+ .name = "dclk1",
+ .id = -1,
+ .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
+ .enable = s3c24xx_dclk_enable,
+ .set_parent = s3c24xx_dclk_setparent,
+};
+
+struct clk s3c24xx_clkout0 = {
+ .name = "clkout0",
+ .id = -1,
+ .set_parent = s3c24xx_clkout_setparent,
+};
+
+struct clk s3c24xx_clkout1 = {
+ .name = "clkout1",
+ .id = -1,
+ .set_parent = s3c24xx_clkout_setparent,
+};
+
+struct clk s3c24xx_uclk = {
+ .name = "uclk",
+ .id = -1,
+};
+
+/* initialise the clock system */
+
+int s3c24xx_register_clock(struct clk *clk)
+{
+ clk->owner = THIS_MODULE;
+
+ if (clk->enable == NULL)
+ clk->enable = clk_null_enable;
+
+ /* add to the list of available clocks */
+
+ mutex_lock(&clocks_mutex);
+ list_add(&clk->list, &clocks);
+ mutex_unlock(&clocks_mutex);
+
+ return 0;
+}
+
+/* initalise all the clocks */
+
+int __init s3c24xx_setup_clocks(unsigned long xtal,
+ unsigned long fclk,
+ unsigned long hclk,
+ unsigned long pclk)
+{
+ printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
+
+ /* initialise the main system clocks */
+
+ clk_xtal.rate = xtal;
+ clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
+
+ clk_mpll.rate = fclk;
+ clk_h.rate = hclk;
+ clk_p.rate = pclk;
+ clk_f.rate = fclk;
+
+ /* assume uart clocks are correctly setup */
+
+ /* register our clocks */
+
+ if (s3c24xx_register_clock(&clk_xtal) < 0)
+ printk(KERN_ERR "failed to register master xtal\n");
+
+ if (s3c24xx_register_clock(&clk_mpll) < 0)
+ printk(KERN_ERR "failed to register mpll clock\n");
+
+ if (s3c24xx_register_clock(&clk_upll) < 0)
+ printk(KERN_ERR "failed to register upll clock\n");
+
+ if (s3c24xx_register_clock(&clk_f) < 0)
+ printk(KERN_ERR "failed to register cpu fclk\n");
+
+ if (s3c24xx_register_clock(&clk_h) < 0)
+ printk(KERN_ERR "failed to register cpu hclk\n");
+
+ if (s3c24xx_register_clock(&clk_p) < 0)
+ printk(KERN_ERR "failed to register cpu pclk\n");
+
+ return 0;
+}
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c
index a40eaa65617..908efa7d745 100644
--- a/arch/arm/mach-s3c2410/common-smdk.c
+++ b/arch/arm/plat-s3c24xx/common-smdk.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/common-smdk.c
+/* linux/arch/arm/plat-s3c24xx/common-smdk.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -38,9 +38,9 @@
#include <asm/arch/nand.h>
-#include "common-smdk.h"
-#include "devs.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/pm.h>
/* LED devices */
diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
index ae1f5bb63f7..6a2d1070e5a 100644
--- a/arch/arm/mach-s3c2410/cpu.c
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/cpu.c
+/* linux/arch/arm/plat-s3c24xx/cpu.c
*
* Copyright (c) 2004-2005 Simtec Electronics
* http://www.simtec.co.uk/products/SWLINUX/
@@ -40,15 +40,16 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-serial.h>
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
-#include "s3c2400.h"
-#include "s3c2410.h"
-#include "s3c2412.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/s3c2400.h>
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
#include "s3c244x.h"
-#include "s3c2440.h"
-#include "s3c2442.h"
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/s3c2442.h>
+#include <asm/plat-s3c24xx/s3c2443.h>
struct cpu_table {
unsigned long idcode;
@@ -67,6 +68,7 @@ static const char name_s3c2410[] = "S3C2410";
static const char name_s3c2412[] = "S3C2412";
static const char name_s3c2440[] = "S3C2440";
static const char name_s3c2442[] = "S3C2442";
+static const char name_s3c2443[] = "S3C2443";
static const char name_s3c2410a[] = "S3C2410A";
static const char name_s3c2440a[] = "S3C2440A";
@@ -135,6 +137,15 @@ static struct cpu_table cpu_ids[] __initdata = {
.name = name_s3c2412,
},
{
+ .idcode = 0x32443001,
+ .idmask = 0xffffffff,
+ .map_io = s3c2443_map_io,
+ .init_clocks = s3c2443_init_clocks,
+ .init_uarts = s3c2443_init_uarts,
+ .init = s3c2443_init,
+ .name = name_s3c2443,
+ },
+ {
.idcode = 0x0, /* S3C2400 doesn't have an idcode */
.idmask = 0xffffffff,
.map_io = s3c2400_map_io,
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/plat-s3c24xx/devs.c
index faccde2092d..0fe53b39cb2 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/devs.c
+/* linux/arch/arm/plat-s3c24xx/devs.c
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -29,9 +29,10 @@
#include <asm/irq.h>
#include <asm/arch/regs-serial.h>
+#include <asm/arch/udc.h>
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
/* Serial port registrations */
@@ -230,6 +231,20 @@ struct platform_device s3c_device_usbgadget = {
EXPORT_SYMBOL(s3c_device_usbgadget);
+void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
+{
+ struct s3c2410_udc_mach_info *npd;
+
+ npd = kmalloc(sizeof(*npd), GFP_KERNEL);
+ if (npd) {
+ memcpy(npd, pd, sizeof(*npd));
+ s3c_device_usbgadget.dev.platform_data = npd;
+ } else {
+ printk(KERN_ERR "no memory for udc platform data\n");
+ }
+}
+
+
/* Watchdog */
static struct resource s3c_wdt_resource[] = {
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
new file mode 100644
index 00000000000..4540a806f52
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -0,0 +1,1499 @@
+/* linux/arch/arm/plat-s3c24xx/dma.c
+ *
+ * Copyright (c) 2003-2005,2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 DMA core
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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.
+*/
+
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <asm/mach/dma.h>
+#include <asm/arch/map.h>
+
+#include <asm/plat-s3c24xx/dma.h>
+
+/* io map for dma */
+static void __iomem *dma_base;
+static struct kmem_cache *dma_kmem;
+
+static int dma_channels;
+
+struct s3c24xx_dma_selection dma_sel;
+
+/* dma channel state information */
+struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
+
+/* debugging functions */
+
+#define BUF_MAGIC (0xcafebabe)
+
+#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
+
+#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
+
+#if 1
+#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
+#else
+static inline void
+dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
+{
+ pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
+ writel(val, dma_regaddr(chan, reg));
+}
+#endif
+
+#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
+
+/* captured register state for debug */
+
+struct s3c2410_dma_regstate {
+ unsigned long dcsrc;
+ unsigned long disrc;
+ unsigned long dstat;
+ unsigned long dcon;
+ unsigned long dmsktrig;
+};
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+
+/* dmadbg_showregs
+ *
+ * simple debug routine to print the current state of the dma registers
+*/
+
+static void
+dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
+{
+ regs->dcsrc = dma_rdreg(chan, S3C2410_DMA_DCSRC);
+ regs->disrc = dma_rdreg(chan, S3C2410_DMA_DISRC);
+ regs->dstat = dma_rdreg(chan, S3C2410_DMA_DSTAT);
+ regs->dcon = dma_rdreg(chan, S3C2410_DMA_DCON);
+ regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+}
+
+static void
+dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
+ struct s3c2410_dma_regstate *regs)
+{
+ printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
+ chan->number, fname, line,
+ regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
+ regs->dcon);
+}
+
+static void
+dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
+{
+ struct s3c2410_dma_regstate state;
+
+ dmadbg_capture(chan, &state);
+
+ printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
+ chan->number, fname, line, chan->load_state,
+ chan->curr, chan->next, chan->end);
+
+ dmadbg_dumpregs(fname, line, chan, &state);
+}
+
+static void
+dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
+{
+ struct s3c2410_dma_regstate state;
+
+ dmadbg_capture(chan, &state);
+ dmadbg_dumpregs(fname, line, chan, &state);
+}
+
+#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
+#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
+#else
+#define dbg_showregs(chan) do { } while(0)
+#define dbg_showchan(chan) do { } while(0)
+#endif /* CONFIG_S3C2410_DMA_DEBUG */
+
+static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
+
+/* lookup_dma_channel
+ *
+ * change the dma channel number given into a real dma channel id
+*/
+
+static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
+{
+ if (channel & DMACH_LOW_LEVEL)
+ return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
+ else
+ return dma_chan_map[channel];
+}
+
+/* s3c2410_dma_stats_timeout
+ *
+ * Update DMA stats from timeout info
+*/
+
+static void
+s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
+{
+ if (stats == NULL)
+ return;
+
+ if (val > stats->timeout_longest)
+ stats->timeout_longest = val;
+ if (val < stats->timeout_shortest)
+ stats->timeout_shortest = val;
+
+ stats->timeout_avg += val;
+}
+
+/* s3c2410_dma_waitforload
+ *
+ * wait for the DMA engine to load a buffer, and update the state accordingly
+*/
+
+static int
+s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
+{
+ int timeout = chan->load_timeout;
+ int took;
+
+ if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
+ printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
+ return 0;
+ }
+
+ if (chan->stats != NULL)
+ chan->stats->loads++;
+
+ while (--timeout > 0) {
+ if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
+ took = chan->load_timeout - timeout;
+
+ s3c2410_dma_stats_timeout(chan->stats, took);
+
+ switch (chan->load_state) {
+ case S3C2410_DMALOAD_1LOADED:
+ chan->load_state = S3C2410_DMALOAD_1RUNNING;
+ break;
+
+ default:
+ printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
+ }
+
+ return 1;
+ }
+ }
+
+ if (chan->stats != NULL) {
+ chan->stats->timeout_failed++;
+ }
+
+ return 0;
+}
+
+
+
+/* s3c2410_dma_loadbuffer
+ *
+ * load a buffer, and update the channel state
+*/
+
+static inline int
+s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
+ struct s3c2410_dma_buf *buf)
+{
+ unsigned long reload;
+
+ pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
+ buf, (unsigned long)buf->data, buf->size);
+
+ if (buf == NULL) {
+ dmawarn("buffer is NULL\n");
+ return -EINVAL;
+ }
+
+ /* check the state of the channel before we do anything */
+
+ if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+ dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
+ }
+
+ if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
+ dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
+ }
+
+ /* it would seem sensible if we are the last buffer to not bother
+ * with the auto-reload bit, so that the DMA engine will not try
+ * and load another transfer after this one has finished...
+ */
+ if (chan->load_state == S3C2410_DMALOAD_NONE) {
+ pr_debug("load_state is none, checking for noreload (next=%p)\n",
+ buf->next);
+ reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
+ } else {
+ //pr_debug("load_state is %d => autoreload\n", chan->load_state);
+ reload = S3C2410_DCON_AUTORELOAD;
+ }
+
+ if ((buf->data & 0xf0000000) != 0x30000000) {
+ dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
+ }
+
+ writel(buf->data, chan->addr_reg);
+
+ dma_wrreg(chan, S3C2410_DMA_DCON,
+ chan->dcon | reload | (buf->size/chan->xfer_unit));
+
+ chan->next = buf->next;
+
+ /* update the state of the channel */
+
+ switch (chan->load_state) {
+ case S3C2410_DMALOAD_NONE:
+ chan->load_state = S3C2410_DMALOAD_1LOADED;
+ break;
+
+ case S3C2410_DMALOAD_1RUNNING:
+ chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
+ break;
+
+ default:
+ dmawarn("dmaload: unknown state %d in loadbuffer\n",
+ chan->load_state);
+ break;
+ }
+
+ return 0;
+}
+
+/* s3c2410_dma_call_op
+ *
+ * small routine to call the op routine with the given op if it has been
+ * registered
+*/
+
+static void
+s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
+{
+ if (chan->op_fn != NULL) {
+ (chan->op_fn)(chan, op);
+ }
+}
+
+/* s3c2410_dma_buffdone
+ *
+ * small wrapper to check if callback routine needs to be called, and
+ * if so, call it
+*/
+
+static inline void
+s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
+ enum s3c2410_dma_buffresult result)
+{
+#if 0
+ pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
+ chan->callback_fn, buf, buf->id, buf->size, result);
+#endif
+
+ if (chan->callback_fn != NULL) {
+ (chan->callback_fn)(chan, buf->id, buf->size, result);
+ }
+}
+
+/* s3c2410_dma_start
+ *
+ * start a dma channel going
+*/
+
+static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
+{
+ unsigned long tmp;
+ unsigned long flags;
+
+ pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
+
+ local_irq_save(flags);
+
+ if (chan->state == S3C2410_DMA_RUNNING) {
+ pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
+ local_irq_restore(flags);
+ return 0;
+ }
+
+ chan->state = S3C2410_DMA_RUNNING;
+
+ /* check wether there is anything to load, and if not, see
+ * if we can find anything to load
+ */
+
+ if (chan->load_state == S3C2410_DMALOAD_NONE) {
+ if (chan->next == NULL) {
+ printk(KERN_ERR "dma%d: channel has nothing loaded\n",
+ chan->number);
+ chan->state = S3C2410_DMA_IDLE;
+ local_irq_restore(flags);
+ return -EINVAL;
+ }
+
+ s3c2410_dma_loadbuffer(chan, chan->next);
+ }
+
+ dbg_showchan(chan);
+
+ /* enable the channel */
+
+ if (!chan->irq_enabled) {
+ enable_irq(chan->irq);
+ chan->irq_enabled = 1;
+ }
+
+ /* start the channel going */
+
+ tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+ tmp &= ~S3C2410_DMASKTRIG_STOP;
+ tmp |= S3C2410_DMASKTRIG_ON;
+ dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+ pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
+
+#if 0
+ /* the dma buffer loads should take care of clearing the AUTO
+ * reloading feature */
+ tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+ tmp &= ~S3C2410_DCON_NORELOAD;
+ dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+ s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
+
+ dbg_showchan(chan);
+
+ /* if we've only loaded one buffer onto the channel, then chec
+ * to see if we have another, and if so, try and load it so when
+ * the first buffer is finished, the new one will be loaded onto
+ * the channel */
+
+ if (chan->next != NULL) {
+ if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+ if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+ pr_debug("%s: buff not yet loaded, no more todo\n",
+ __FUNCTION__);
+ } else {
+ chan->load_state = S3C2410_DMALOAD_1RUNNING;
+ s3c2410_dma_loadbuffer(chan, chan->next);
+ }
+
+ } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+ s3c2410_dma_loadbuffer(chan, chan->next);
+ }
+ }
+
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+/* s3c2410_dma_canload
+ *
+ * work out if we can queue another buffer into the DMA engine
+*/
+
+static int
+s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
+{
+ if (chan->load_state == S3C2410_DMALOAD_NONE ||
+ chan->load_state == S3C2410_DMALOAD_1RUNNING)
+ return 1;
+
+ return 0;
+}
+
+/* s3c2410_dma_enqueue
+ *
+ * queue an given buffer for dma transfer.
+ *
+ * id the device driver's id information for this buffer
+ * data the physical address of the buffer data
+ * size the size of the buffer in bytes
+ *
+ * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
+ * is checked, and if set, the channel is started. If this flag isn't set,
+ * then an error will be returned.
+ *
+ * It is possible to queue more than one DMA buffer onto a channel at
+ * once, and the code will deal with the re-loading of the next buffer
+ * when necessary.
+*/
+
+int s3c2410_dma_enqueue(unsigned int channel, void *id,
+ dma_addr_t data, int size)
+{
+ struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+ struct s3c2410_dma_buf *buf;
+ unsigned long flags;
+
+ if (chan == NULL)
+ return -EINVAL;
+
+ pr_debug("%s: id=%p, data=%08x, size=%d\n",
+ __FUNCTION__, id, (unsigned int)data, size);
+
+ buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
+ if (buf == NULL) {
+ pr_debug("%s: out of memory (%ld alloc)\n",
+ __FUNCTION__, (long)sizeof(*buf));
+ return -ENOMEM;
+ }
+
+ //pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
+ //dbg_showchan(chan);
+
+ buf->next = NULL;
+ buf->data = buf->ptr = data;
+ buf->size = size;
+ buf->id = id;
+ buf->magic = BUF_MAGIC;
+
+ local_irq_save(flags);
+
+ if (chan->curr == NULL) {
+ /* we've got nothing loaded... */
+ pr_debug("%s: buffer %p queued onto empty channel\n",
+ __FUNCTION__, buf);
+
+ chan->curr = buf;
+ chan->end = buf;
+ chan->next = NULL;
+ } else {
+ pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
+ chan->number, __FUNCTION__, buf);
+
+ if (chan->end == NULL)
+ pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
+ chan->number, __FUNCTION__, chan);
+
+ chan->end->next = buf;
+ chan->end = buf;
+ }
+
+ /* if necessary, update the next buffer field */
+ if (chan->next == NULL)
+ chan->next = buf;
+
+ /* check to see if we can load a buffer */
+ if (chan->state == S3C2410_DMA_RUNNING) {
+ if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
+ if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+ printk(KERN_ERR "dma%d: loadbuffer:"
+ "timeout loading buffer\n",
+ chan->number);
+ dbg_showchan(chan);
+ local_irq_restore(flags);
+ return -EINVAL;
+ }
+ }
+
+ while (s3c2410_dma_canload(chan) && chan->next != NULL) {
+ s3c2410_dma_loadbuffer(chan, chan->next);
+ }
+ } else if (chan->state == S3C2410_DMA_IDLE) {
+ if (chan->flags & S3C2410_DMAF_AUTOSTART) {
+ s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
+ }
+ }
+
+ local_irq_restore(flags);
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_enqueue);
+
+static inline void
+s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
+{
+ int magicok = (buf->magic == BUF_MAGIC);
+
+ buf->magic = -1;
+
+ if (magicok) {
+ kmem_cache_free(dma_kmem, buf);
+ } else {
+ printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
+ }
+}
+
+/* s3c2410_dma_lastxfer
+ *
+ * called when the system is out of buffers, to ensure that the channel
+ * is prepared for shutdown.
+*/
+
+static inline void
+s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
+{
+#if 0
+ pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
+ chan->number, chan->load_state);
+#endif
+
+ switch (chan->load_state) {
+ case S3C2410_DMALOAD_NONE:
+ break;
+
+ case S3C2410_DMALOAD_1LOADED:
+ if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+ /* flag error? */
+ printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+ chan->number, __FUNCTION__);
+ return;
+ }
+ break;
+
+ case S3C2410_DMALOAD_1LOADED_1RUNNING:
+ /* I belive in this case we do not have anything to do
+ * until the next buffer comes along, and we turn off the
+ * reload */
+ return;
+
+ default:
+ pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
+ chan->number, chan->load_state);
+ return;
+
+ }
+
+ /* hopefully this'll shut the damned thing up after the transfer... */
+ dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
+}
+
+
+#define dmadbg2(x...)
+
+static irqreturn_t
+s3c2410_dma_irq(int irq, void *devpw)
+{
+ struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
+ struct s3c2410_dma_buf *buf;
+
+ buf = chan->curr;
+
+ dbg_showchan(chan);
+
+ /* modify the channel state */
+
+ switch (chan->load_state) {
+ case S3C2410_DMALOAD_1RUNNING:
+ /* TODO - if we are running only one buffer, we probably
+ * want to reload here, and then worry about the buffer
+ * callback */
+
+ chan->load_state = S3C2410_DMALOAD_NONE;
+ break;
+
+ case S3C2410_DMALOAD_1LOADED:
+ /* iirc, we should go back to NONE loaded here, we
+ * had a buffer, and it was never verified as being
+ * loaded.
+ */
+
+ chan->load_state = S3C2410_DMALOAD_NONE;
+ break;
+
+ case S3C2410_DMALOAD_1LOADED_1RUNNING:
+ /* we'll worry about checking to see if another buffer is
+ * ready after we've called back the owner. This should
+ * ensure we do not wait around too long for the DMA
+ * engine to start the next transfer
+ */
+
+ chan->load_state = S3C2410_DMALOAD_1LOADED;
+ break;
+
+ case S3C2410_DMALOAD_NONE:
+ printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
+ chan->number);
+ break;
+
+ default:
+ printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
+ chan->number, chan->load_state);
+ break;
+ }
+
+ if (buf != NULL) {
+ /* update the chain to make sure that if we load any more
+ * buffers when we call the callback function, things should
+ * work properly */
+
+ chan->curr = buf->next;
+ buf->next = NULL;
+
+ if (buf->magic != BUF_MAGIC) {
+ printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
+ chan->number, __FUNCTION__, buf);
+ return IRQ_HANDLED;
+ }
+
+ s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
+
+ /* free resouces */
+ s3c2410_dma_freebuf(buf);
+ } else {
+ }
+
+ /* only reload if the channel is still running... our buffer done
+ * routine may have altered the state by requesting the dma channel
+ * to stop or shutdown... */
+
+ /* todo: check that when the channel is shut-down from inside this
+ * function, we cope with unsetting reload, etc */
+
+ if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
+ unsigned long flags;
+
+ switch (chan->load_state) {
+ case S3C2410_DMALOAD_1RUNNING:
+ /* don't need to do anything for this state */
+ break;
+
+ case S3C2410_DMALOAD_NONE:
+ /* can load buffer immediately */
+ break;
+
+ case S3C2410_DMALOAD_1LOADED:
+ if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+ /* flag error? */
+ printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+ chan->number, __FUNCTION__);
+ return IRQ_HANDLED;
+ }
+
+ break;
+
+ case S3C2410_DMALOAD_1LOADED_1RUNNING:
+ goto no_load;
+
+ default:
+ printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
+ chan->number, chan->load_state);
+ return IRQ_HANDLED;
+ }
+
+ local_irq_save(flags);
+ s3c2410_dma_loadbuffer(chan, chan->next);
+ local_irq_restore(flags);
+ } else {
+ s3c2410_dma_lastxfer(chan);
+
+ /* see if we can stop this channel.. */
+ if (chan->load_state == S3C2410_DMALOAD_NONE) {
+ pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
+ chan->number, jiffies);
+ s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
+ S3C2410_DMAOP_STOP);
+ }
+ }
+
+ no_load:
+ return IRQ_HANDLED;
+}
+
+static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
+
+/* s3c2410_request_dma
+ *
+ * get control of an dma channel
+*/
+
+int s3c2410_dma_request(unsigned int channel,
+ struct s3c2410_dma_client *client,
+ void *dev)
+{
+ struct s3c2410_dma_chan *chan;
+ unsigned long flags;
+ int err;
+
+ pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
+ channel, client->name, dev);
+
+ local_irq_save(flags);
+
+ chan = s3c2410_dma_map_channel(channel);
+ if (chan == NULL) {
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+
+ dbg_showchan(chan);
+
+ chan->client = client;
+ chan->in_use = 1;
+
+ if (!chan->irq_claimed) {
+ pr_debug("dma%d: %s : requesting irq %d\n",
+ channel, __FUNCTION__, chan->irq);
+
+ chan->irq_claimed = 1;
+ local_irq_restore(flags);
+
+ err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
+ client->name, (void *)chan);
+
+ local_irq_save(flags);
+
+ if (err) {
+ chan->in_use = 0;
+ chan->irq_claimed = 0;
+ local_irq_restore(flags);
+
+ printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
+ client->name, chan->irq, chan->number);
+ return err;
+ }
+
+ chan->irq_enabled = 1;
+ }
+
+ local_irq_restore(flags);
+
+ /* need to setup */
+
+ pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_request);
+
+/* s3c2410_dma_free
+ *
+ * release the given channel back to the system, will stop and flush
+ * any outstanding transfers, and ensure the channel is ready for the
+ * next claimant.
+ *
+ * Note, although a warning is currently printed if the freeing client
+ * info is not the same as the registrant's client info, the free is still
+ * allowed to go through.
+*/
+
+int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
+{
+ struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+ unsigned long flags;
+
+ if (chan == NULL)
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ if (chan->client != client) {
+ printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
+ channel, chan->client, client);
+ }
+
+ /* sort out stopping and freeing the channel */
+
+ if (chan->state != S3C2410_DMA_IDLE) {
+ pr_debug("%s: need to stop dma channel %p\n",
+ __FUNCTION__, chan);
+
+ /* possibly flush the channel */
+ s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
+ }
+
+ chan->client = NULL;
+ chan->in_use = 0;
+
+ if (chan->irq_claimed)
+ free_irq(chan->irq, (void *)chan);
+
+ chan->irq_claimed = 0;
+
+ if (!(channel & DMACH_LOW_LEVEL))
+ dma_chan_map[channel] = NULL;
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_free);
+
+static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
+{
+ unsigned long flags;
+ unsigned long tmp;
+
+ pr_debug("%s:\n", __FUNCTION__);
+
+ dbg_showchan(chan);
+
+ local_irq_save(flags);
+
+ s3c2410_dma_call_op(chan, S3C2410_DMAOP_STOP);
+
+ tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+ tmp |= S3C2410_DMASKTRIG_STOP;
+ //tmp &= ~S3C2410_DMASKTRIG_ON;
+ dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+#if 0
+ /* should also clear interrupts, according to WinCE BSP */
+ tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+ tmp |= S3C2410_DCON_NORELOAD;
+ dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+ /* should stop do this, or should we wait for flush? */
+ chan->state = S3C2410_DMA_IDLE;
+ chan->load_state = S3C2410_DMALOAD_NONE;
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
+{
+ unsigned long tmp;
+ unsigned int timeout = 0x10000;
+
+ while (timeout-- > 0) {
+ tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+
+ if (!(tmp & S3C2410_DMASKTRIG_ON))
+ return;
+ }
+
+ pr_debug("dma%d: failed to stop?\n", chan->number);
+}
+
+
+/* s3c2410_dma_flush
+ *
+ * stop the channel, and remove all current and pending transfers
+*/
+
+static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
+{
+ struct s3c2410_dma_buf *buf, *next;
+ unsigned long flags;
+
+ pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
+
+ dbg_showchan(chan);
+
+ local_irq_save(flags);
+
+ if (chan->state != S3C2410_DMA_IDLE) {
+ pr_debug("%s: stopping channel...\n", __FUNCTION__ );
+ s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
+ }
+
+ buf = chan->curr;
+ if (buf == NULL)
+ buf = chan->next;
+
+ chan->curr = chan->next = chan->end = NULL;
+
+ if (buf != NULL) {
+ for ( ; buf != NULL; buf = next) {
+ next = buf->next;
+
+ pr_debug("%s: free buffer %p, next %p\n",
+ __FUNCTION__, buf, buf->next);
+
+ s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
+ s3c2410_dma_freebuf(buf);
+ }
+ }
+
+ dbg_showregs(chan);
+
+ s3c2410_dma_waitforstop(chan);
+
+#if 0
+ /* should also clear interrupts, according to WinCE BSP */
+ {
+ unsigned long tmp;
+
+ tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+ tmp |= S3C2410_DCON_NORELOAD;
+ dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+ }
+#endif
+
+ dbg_showregs(chan);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+int
+s3c2410_dma_started(struct s3c2410_dma_chan *chan)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ dbg_showchan(chan);
+
+ /* if we've only loaded one buffer onto the channel, then chec
+ * to see if we have another, and if so, try and load it so when
+ * the first buffer is finished, the new one will be loaded onto
+ * the channel */
+
+ if (chan->next != NULL) {
+ if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+ if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+ pr_debug("%s: buff not yet loaded, no more todo\n",
+ __FUNCTION__);
+ } else {
+ chan->load_state = S3C2410_DMALOAD_1RUNNING;
+ s3c2410_dma_loadbuffer(chan, chan->next);
+ }
+
+ } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+ s3c2410_dma_loadbuffer(chan, chan->next);
+ }
+ }
+
+
+ local_irq_restore(flags);
+
+ return 0;
+
+}
+
+int
+s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
+{
+ struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+ if (chan == NULL)
+ return -EINVAL;
+
+ switch (op) {
+ case S3C2410_DMAOP_START:
+ return s3c2410_dma_start(chan);
+
+ case S3C2410_DMAOP_STOP:
+ return s3c2410_dma_dostop(chan);
+
+ case S3C2410_DMAOP_PAUSE:
+ case S3C2410_DMAOP_RESUME:
+ return -ENOENT;
+
+ case S3C2410_DMAOP_FLUSH:
+ return s3c2410_dma_flush(chan);
+
+ case S3C2410_DMAOP_STARTED:
+ return s3c2410_dma_started(chan);
+
+ case S3C2410_DMAOP_TIMEOUT:
+ return 0;
+
+ }
+
+ return -ENOENT; /* unknown, don't bother */
+}
+
+EXPORT_SYMBOL(s3c2410_dma_ctrl);
+
+/* DMA configuration for each channel
+ *
+ * DISRCC -> source of the DMA (AHB,APB)
+ * DISRC -> source address of the DMA
+ * DIDSTC -> destination of the DMA (AHB,APD)
+ * DIDST -> destination address of the DMA
+*/
+
+/* s3c2410_dma_config
+ *
+ * xfersize: size of unit in bytes (1,2,4)
+ * dcon: base value of the DCONx register
+*/
+
+int s3c2410_dma_config(dmach_t channel,
+ int xferunit,
+ int dcon)
+{
+ struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+ pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
+ __FUNCTION__, channel, xferunit, dcon);
+
+ if (chan == NULL)
+ return -EINVAL;
+
+ pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
+
+ dcon |= chan->dcon & dma_sel.dcon_mask;
+
+ pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
+
+ switch (xferunit) {
+ case 1:
+ dcon |= S3C2410_DCON_BYTE;
+ break;
+
+ case 2:
+ dcon |= S3C2410_DCON_HALFWORD;
+ break;
+
+ case 4:
+ dcon |= S3C2410_DCON_WORD;
+ break;
+
+ default:
+ pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
+ return -EINVAL;
+ }
+
+ dcon |= S3C2410_DCON_HWTRIG;
+ dcon |= S3C2410_DCON_INTREQ;
+
+ pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
+
+ chan->dcon = dcon;
+ chan->xfer_unit = xferunit;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_config);
+
+int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
+{
+ struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+ if (chan == NULL)
+ return -EINVAL;
+
+ pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
+
+ chan->flags = flags;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_setflags);
+
+
+/* do we need to protect the settings of the fields from
+ * irq?
+*/
+
+int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
+{
+ struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+ if (chan == NULL)
+ return -EINVAL;
+
+ pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
+
+ chan->op_fn = rtn;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_set_opfn);
+
+int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
+{
+ struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+ if (chan == NULL)
+ return -EINVAL;
+
+ pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
+
+ chan->callback_fn = rtn;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
+
+/* s3c2410_dma_devconfig
+ *
+ * configure the dma source/destination hardware type and address
+ *
+ * source: S3C2410_DMASRC_HW: source is hardware
+ * S3C2410_DMASRC_MEM: source is memory
+ *
+ * hwcfg: the value for xxxSTCn register,
+ * bit 0: 0=increment pointer, 1=leave pointer
+ * bit 1: 0=soucre is AHB, 1=soucre is APB
+ *
+ * devaddr: physical address of the source
+*/
+
+int s3c2410_dma_devconfig(int channel,
+ enum s3c2410_dmasrc source,
+ int hwcfg,
+ unsigned long devaddr)
+{
+ struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+ if (chan == NULL)
+ return -EINVAL;
+
+ pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
+ __FUNCTION__, (int)source, hwcfg, devaddr);
+
+ chan->source = source;
+ chan->dev_addr = devaddr;
+
+ switch (source) {
+ case S3C2410_DMASRC_HW:
+ /* source is hardware */
+ pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
+ __FUNCTION__, devaddr, hwcfg);
+ dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
+ dma_wrreg(chan, S3C2410_DMA_DISRC, devaddr);
+ dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
+
+ chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
+ return 0;
+
+ case S3C2410_DMASRC_MEM:
+ /* source is memory */
+ pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
+ __FUNCTION__, devaddr, hwcfg);
+ dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
+ dma_wrreg(chan, S3C2410_DMA_DIDST, devaddr);
+ dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
+
+ chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
+ return 0;
+ }
+
+ printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
+ return -EINVAL;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_devconfig);
+
+/* s3c2410_dma_getposition
+ *
+ * returns the current transfer points for the dma source and destination
+*/
+
+int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
+{
+ struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+ if (chan == NULL)
+ return -EINVAL;
+
+ if (src != NULL)
+ *src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
+
+ if (dst != NULL)
+ *dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_getposition);
+
+
+/* system device class */
+
+#ifdef CONFIG_PM
+
+static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
+{
+ struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
+
+ printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
+
+ if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
+ /* the dma channel is still working, which is probably
+ * a bad thing to do over suspend/resume. We stop the
+ * channel and assume that the client is either going to
+ * retry after resume, or that it is broken.
+ */
+
+ printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
+ cp->number);
+
+ s3c2410_dma_dostop(cp);
+ }
+
+ return 0;
+}
+
+static int s3c2410_dma_resume(struct sys_device *dev)
+{
+ return 0;
+}
+
+#else
+#define s3c2410_dma_suspend NULL
+#define s3c2410_dma_resume NULL
+#endif /* CONFIG_PM */
+
+struct sysdev_class dma_sysclass = {
+ set_kset_name("s3c24xx-dma"),
+ .suspend = s3c2410_dma_suspend,
+ .resume = s3c2410_dma_resume,
+};
+
+/* kmem cache implementation */
+
+static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
+{
+ memset(p, 0, sizeof(struct s3c2410_dma_buf));
+}
+
+/* initialisation code */
+
+int __init s3c24xx_dma_sysclass_init(void)
+{
+ int ret = sysdev_class_register(&dma_sysclass);
+
+ if (ret != 0)
+ printk(KERN_ERR "dma sysclass registration failed\n");
+
+ return ret;
+}
+
+core_initcall(s3c24xx_dma_sysclass_init);
+
+int __init s3c24xx_dma_sysdev_register(void)
+{
+ struct s3c2410_dma_chan *cp = s3c2410_chans;
+ int channel, ret;
+
+ for (channel = 0; channel < dma_channels; cp++, channel++) {
+ cp->dev.cls = &dma_sysclass;
+ cp->dev.id = channel;
+ ret = sysdev_register(&cp->dev);
+
+ if (ret) {
+ printk(KERN_ERR "error registering dev for dma %d\n",
+ channel);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+late_initcall(s3c24xx_dma_sysdev_register);
+
+int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq,
+ unsigned int stride)
+{
+ struct s3c2410_dma_chan *cp;
+ int channel;
+ int ret;
+
+ printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
+
+ dma_channels = channels;
+
+ dma_base = ioremap(S3C24XX_PA_DMA, stride * channels);
+ if (dma_base == NULL) {
+ printk(KERN_ERR "dma failed to remap register block\n");
+ return -ENOMEM;
+ }
+
+ dma_kmem = kmem_cache_create("dma_desc",
+ sizeof(struct s3c2410_dma_buf), 0,
+ SLAB_HWCACHE_ALIGN,
+ s3c2410_dma_cache_ctor, NULL);
+
+ if (dma_kmem == NULL) {
+ printk(KERN_ERR "dma failed to make kmem cache\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (channel = 0; channel < channels; channel++) {
+ cp = &s3c2410_chans[channel];
+
+ memset(cp, 0, sizeof(struct s3c2410_dma_chan));
+
+ /* dma channel irqs are in order.. */
+ cp->number = channel;
+ cp->irq = channel + irq;
+ cp->regs = dma_base + (channel * stride);
+
+ /* point current stats somewhere */
+ cp->stats = &cp->stats_store;
+ cp->stats_store.timeout_shortest = LONG_MAX;
+
+ /* basic channel configuration */
+
+ cp->load_timeout = 1<<18;
+
+ printk("DMA channel %d at %p, irq %d\n",
+ cp->number, cp->regs, cp->irq);
+ }
+
+ return 0;
+
+ err:
+ kmem_cache_destroy(dma_kmem);
+ iounmap(dma_base);
+ dma_base = NULL;
+ return ret;
+}
+
+int s3c2410_dma_init(void)
+{
+ return s3c24xx_dma_init(4, IRQ_DMA0, 0x40);
+}
+
+static inline int is_channel_valid(unsigned int channel)
+{
+ return (channel & DMA_CH_VALID);
+}
+
+static struct s3c24xx_dma_order *dma_order;
+
+
+/* s3c2410_dma_map_channel()
+ *
+ * turn the virtual channel number into a real, and un-used hardware
+ * channel.
+ *
+ * first, try the dma ordering given to us by either the relevant
+ * dma code, or the board. Then just find the first usable free
+ * channel
+*/
+
+struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
+{
+ struct s3c24xx_dma_order_ch *ord = NULL;
+ struct s3c24xx_dma_map *ch_map;
+ struct s3c2410_dma_chan *dmach;
+ int ch;
+
+ if (dma_sel.map == NULL || channel > dma_sel.map_size)
+ return NULL;
+
+ ch_map = dma_sel.map + channel;
+
+ /* first, try the board mapping */
+
+ if (dma_order) {
+ ord = &dma_order->channels[channel];
+
+ for (ch = 0; ch < dma_channels; ch++) {
+ if (!is_channel_valid(ord->list[ch]))
+ continue;
+
+ if (s3c2410_chans[ord->list[ch]].in_use == 0) {
+ ch = ord->list[ch] & ~DMA_CH_VALID;
+ goto found;
+ }
+ }
+
+ if (ord->flags & DMA_CH_NEVER)
+ return NULL;
+ }
+
+ /* second, search the channel map for first free */
+
+ for (ch = 0; ch < dma_channels; ch++) {
+ if (!is_channel_valid(ch_map->channels[ch]))
+ continue;
+
+ if (s3c2410_chans[ch].in_use == 0) {
+ printk("mapped channel %d to %d\n", channel, ch);
+ break;
+ }
+ }
+
+ if (ch >= dma_channels)
+ return NULL;
+
+ /* update our channel mapping */
+
+ found:
+ dmach = &s3c2410_chans[ch];
+ dma_chan_map[channel] = dmach;
+
+ /* select the channel */
+
+ (dma_sel.select)(dmach, ch_map);
+
+ return dmach;
+}
+
+static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
+{
+ return 0;
+}
+
+int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
+{
+ struct s3c24xx_dma_map *nmap;
+ size_t map_sz = sizeof(*nmap) * sel->map_size;
+ int ptr;
+
+ nmap = kmalloc(map_sz, GFP_KERNEL);
+ if (nmap == NULL)
+ return -ENOMEM;
+
+ memcpy(nmap, sel->map, map_sz);
+ memcpy(&dma_sel, sel, sizeof(*sel));
+
+ dma_sel.map = nmap;
+
+ for (ptr = 0; ptr < sel->map_size; ptr++)
+ s3c24xx_dma_check_entry(nmap+ptr, ptr);
+
+ return 0;
+}
+
+int __init s3c24xx_dma_order_set(struct s3c24xx_dma_order *ord)
+{
+ struct s3c24xx_dma_order *nord = dma_order;
+
+ if (nord == NULL)
+ nord = kmalloc(sizeof(struct s3c24xx_dma_order), GFP_KERNEL);
+
+ if (nord == NULL) {
+ printk(KERN_ERR "no memory to store dma channel order\n");
+ return -ENOMEM;
+ }
+
+ dma_order = nord;
+ memcpy(nord, ord, sizeof(struct s3c24xx_dma_order));
+ return 0;
+}
diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c
new file mode 100644
index 00000000000..ec3a09c4d18
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/gpio.c
@@ -0,0 +1,188 @@
+/* linux/arch/arm/plat-s3c24xx/gpio.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX GPIO support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-gpio.h>
+
+void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
+{
+ void __iomem *base = S3C24XX_GPIO_BASE(pin);
+ unsigned long mask;
+ unsigned long con;
+ unsigned long flags;
+
+ if (pin < S3C2410_GPIO_BANKB) {
+ mask = 1 << S3C2410_GPIO_OFFSET(pin);
+ } else {
+ mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
+ }
+
+ switch (function) {
+ case S3C2410_GPIO_LEAVE:
+ mask = 0;
+ function = 0;
+ break;
+
+ case S3C2410_GPIO_INPUT:
+ case S3C2410_GPIO_OUTPUT:
+ case S3C2410_GPIO_SFN2:
+ case S3C2410_GPIO_SFN3:
+ if (pin < S3C2410_GPIO_BANKB) {
+ function -= 1;
+ function &= 1;
+ function <<= S3C2410_GPIO_OFFSET(pin);
+ } else {
+ function &= 3;
+ function <<= S3C2410_GPIO_OFFSET(pin)*2;
+ }
+ }
+
+ /* modify the specified register wwith IRQs off */
+
+ local_irq_save(flags);
+
+ con = __raw_readl(base + 0x00);
+ con &= ~mask;
+ con |= function;
+
+ __raw_writel(con, base + 0x00);
+
+ local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
+
+unsigned int s3c2410_gpio_getcfg(unsigned int pin)
+{
+ void __iomem *base = S3C24XX_GPIO_BASE(pin);
+ unsigned long val = __raw_readl(base);
+
+ if (pin < S3C2410_GPIO_BANKB) {
+ val >>= S3C2410_GPIO_OFFSET(pin);
+ val &= 1;
+ val += 1;
+ } else {
+ val >>= S3C2410_GPIO_OFFSET(pin)*2;
+ val &= 3;
+ }
+
+ return val | S3C2410_GPIO_INPUT;
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getcfg);
+
+void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
+{
+ void __iomem *base = S3C24XX_GPIO_BASE(pin);
+ unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+ unsigned long flags;
+ unsigned long up;
+
+ if (pin < S3C2410_GPIO_BANKB)
+ return;
+
+ local_irq_save(flags);
+
+ up = __raw_readl(base + 0x08);
+ up &= ~(1L << offs);
+ up |= to << offs;
+ __raw_writel(up, base + 0x08);
+
+ local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_pullup);
+
+void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
+{
+ void __iomem *base = S3C24XX_GPIO_BASE(pin);
+ unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+ unsigned long flags;
+ unsigned long dat;
+
+ local_irq_save(flags);
+
+ dat = __raw_readl(base + 0x04);
+ dat &= ~(1 << offs);
+ dat |= to << offs;
+ __raw_writel(dat, base + 0x04);
+
+ local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_setpin);
+
+unsigned int s3c2410_gpio_getpin(unsigned int pin)
+{
+ void __iomem *base = S3C24XX_GPIO_BASE(pin);
+ unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+
+ return __raw_readl(base + 0x04) & (1<< offs);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getpin);
+
+unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
+{
+ unsigned long flags;
+ unsigned long misccr;
+
+ local_irq_save(flags);
+ misccr = __raw_readl(S3C24XX_MISCCR);
+ misccr &= ~clear;
+ misccr ^= change;
+ __raw_writel(misccr, S3C24XX_MISCCR);
+ local_irq_restore(flags);
+
+ return misccr;
+}
+
+EXPORT_SYMBOL(s3c2410_modify_misccr);
+
+int s3c2410_gpio_getirq(unsigned int pin)
+{
+ if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
+ return -1; /* not valid interrupts */
+
+ if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
+ return -1; /* not valid pin */
+
+ if (pin < S3C2410_GPF4)
+ return (pin - S3C2410_GPF0) + IRQ_EINT0;
+
+ if (pin < S3C2410_GPG0)
+ return (pin - S3C2410_GPF4) + IRQ_EINT4;
+
+ return (pin - S3C2410_GPG0) + IRQ_EINT8;
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getirq);
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
new file mode 100644
index 00000000000..ce186398e3f
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -0,0 +1,801 @@
+/* linux/arch/arm/plat-s3c24xx/irq.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Changelog:
+ *
+ * 22-Jul-2004 Ben Dooks <ben@simtec.co.uk>
+ * Fixed compile warnings
+ *
+ * 22-Jul-2004 Roc Wu <cooloney@yahoo.com.cn>
+ * Fixed s3c_extirq_type
+ *
+ * 21-Jul-2004 Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
+ * Addition of ADC/TC demux
+ *
+ * 04-Oct-2004 Klaus Fetscher <k.fetscher@fetron.de>
+ * Fix for set_irq_type() on low EINT numbers
+ *
+ * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
+ * Tidy up KF's patch and sort out new release
+ *
+ * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
+ * Add support for power management controls
+ *
+ * 04-Nov-2004 Ben Dooks
+ * Fix standard IRQ wake for EINT0..4 and RTC
+ *
+ * 22-Feb-2005 Ben Dooks
+ * Fixed edge-triggering on ADC IRQ
+ *
+ * 28-Jun-2005 Ben Dooks
+ * Mark IRQ_LCD valid
+ *
+ * 25-Jul-2005 Ben Dooks
+ * Split the S3C2440 IRQ code to seperate file
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
+
+/* wakeup irq control */
+
+#ifdef CONFIG_PM
+
+/* state for IRQs over sleep */
+
+/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
+ *
+ * set bit to 1 in allow bitfield to enable the wakeup settings on it
+*/
+
+unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
+unsigned long s3c_irqwake_intmask = 0xffffffffL;
+unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
+unsigned long s3c_irqwake_eintmask = 0xffffffffL;
+
+int
+s3c_irq_wake(unsigned int irqno, unsigned int state)
+{
+ unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
+
+ if (!(s3c_irqwake_intallow & irqbit))
+ return -ENOENT;
+
+ printk(KERN_INFO "wake %s for irq %d\n",
+ state ? "enabled" : "disabled", irqno);
+
+ if (!state)
+ s3c_irqwake_intmask |= irqbit;
+ else
+ s3c_irqwake_intmask &= ~irqbit;
+
+ return 0;
+}
+
+static int
+s3c_irqext_wake(unsigned int irqno, unsigned int state)
+{
+ unsigned long bit = 1L << (irqno - EXTINT_OFF);
+
+ if (!(s3c_irqwake_eintallow & bit))
+ return -ENOENT;
+
+ printk(KERN_INFO "wake %s for irq %d\n",
+ state ? "enabled" : "disabled", irqno);
+
+ if (!state)
+ s3c_irqwake_eintmask |= bit;
+ else
+ s3c_irqwake_eintmask &= ~bit;
+
+ return 0;
+}
+
+#else
+#define s3c_irqext_wake NULL
+#define s3c_irq_wake NULL
+#endif
+
+
+static void
+s3c_irq_mask(unsigned int irqno)
+{
+ unsigned long mask;
+
+ irqno -= IRQ_EINT0;
+
+ mask = __raw_readl(S3C2410_INTMSK);
+ mask |= 1UL << irqno;
+ __raw_writel(mask, S3C2410_INTMSK);
+}
+
+static inline void
+s3c_irq_ack(unsigned int irqno)
+{
+ unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+
+ __raw_writel(bitval, S3C2410_SRCPND);
+ __raw_writel(bitval, S3C2410_INTPND);
+}
+
+static inline void
+s3c_irq_maskack(unsigned int irqno)
+{
+ unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+ unsigned long mask;
+
+ mask = __raw_readl(S3C2410_INTMSK);
+ __raw_writel(mask|bitval, S3C2410_INTMSK);
+
+ __raw_writel(bitval, S3C2410_SRCPND);
+ __raw_writel(bitval, S3C2410_INTPND);
+}
+
+
+static void
+s3c_irq_unmask(unsigned int irqno)
+{
+ unsigned long mask;
+
+ if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
+ irqdbf2("s3c_irq_unmask %d\n", irqno);
+
+ irqno -= IRQ_EINT0;
+
+ mask = __raw_readl(S3C2410_INTMSK);
+ mask &= ~(1UL << irqno);
+ __raw_writel(mask, S3C2410_INTMSK);
+}
+
+struct irq_chip s3c_irq_level_chip = {
+ .name = "s3c-level",
+ .ack = s3c_irq_maskack,
+ .mask = s3c_irq_mask,
+ .unmask = s3c_irq_unmask,
+ .set_wake = s3c_irq_wake
+};
+
+static struct irq_chip s3c_irq_chip = {
+ .name = "s3c",
+ .ack = s3c_irq_ack,
+ .mask = s3c_irq_mask,
+ .unmask = s3c_irq_unmask,
+ .set_wake = s3c_irq_wake
+};
+
+static void
+s3c_irqext_mask(unsigned int irqno)
+{
+ unsigned long mask;
+
+ irqno -= EXTINT_OFF;
+
+ mask = __raw_readl(S3C24XX_EINTMASK);
+ mask |= ( 1UL << irqno);
+ __raw_writel(mask, S3C24XX_EINTMASK);
+}
+
+static void
+s3c_irqext_ack(unsigned int irqno)
+{
+ unsigned long req;
+ unsigned long bit;
+ unsigned long mask;
+
+ bit = 1UL << (irqno - EXTINT_OFF);
+
+ mask = __raw_readl(S3C24XX_EINTMASK);
+
+ __raw_writel(bit, S3C24XX_EINTPEND);
+
+ req = __raw_readl(S3C24XX_EINTPEND);
+ req &= ~mask;
+
+ /* not sure if we should be acking the parent irq... */
+
+ if (irqno <= IRQ_EINT7 ) {
+ if ((req & 0xf0) == 0)
+ s3c_irq_ack(IRQ_EINT4t7);
+ } else {
+ if ((req >> 8) == 0)
+ s3c_irq_ack(IRQ_EINT8t23);
+ }
+}
+
+static void
+s3c_irqext_unmask(unsigned int irqno)
+{
+ unsigned long mask;
+
+ irqno -= EXTINT_OFF;
+
+ mask = __raw_readl(S3C24XX_EINTMASK);
+ mask &= ~( 1UL << irqno);
+ __raw_writel(mask, S3C24XX_EINTMASK);
+}
+
+int
+s3c_irqext_type(unsigned int irq, unsigned int type)
+{
+ void __iomem *extint_reg;
+ void __iomem *gpcon_reg;
+ unsigned long gpcon_offset, extint_offset;
+ unsigned long newvalue = 0, value;
+
+ if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
+ {
+ gpcon_reg = S3C2410_GPFCON;
+ extint_reg = S3C24XX_EXTINT0;
+ gpcon_offset = (irq - IRQ_EINT0) * 2;
+ extint_offset = (irq - IRQ_EINT0) * 4;
+ }
+ else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
+ {
+ gpcon_reg = S3C2410_GPFCON;
+ extint_reg = S3C24XX_EXTINT0;
+ gpcon_offset = (irq - (EXTINT_OFF)) * 2;
+ extint_offset = (irq - (EXTINT_OFF)) * 4;
+ }
+ else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
+ {
+ gpcon_reg = S3C2410_GPGCON;
+ extint_reg = S3C24XX_EXTINT1;
+ gpcon_offset = (irq - IRQ_EINT8) * 2;
+ extint_offset = (irq - IRQ_EINT8) * 4;
+ }
+ else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
+ {
+ gpcon_reg = S3C2410_GPGCON;
+ extint_reg = S3C24XX_EXTINT2;
+ gpcon_offset = (irq - IRQ_EINT8) * 2;
+ extint_offset = (irq - IRQ_EINT16) * 4;
+ } else
+ return -1;
+
+ /* Set the GPIO to external interrupt mode */
+ value = __raw_readl(gpcon_reg);
+ value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
+ __raw_writel(value, gpcon_reg);
+
+ /* Set the external interrupt to pointed trigger type */
+ switch (type)
+ {
+ case IRQT_NOEDGE:
+ printk(KERN_WARNING "No edge setting!\n");
+ break;
+
+ case IRQT_RISING:
+ newvalue = S3C2410_EXTINT_RISEEDGE;
+ break;
+
+ case IRQT_FALLING:
+ newvalue = S3C2410_EXTINT_FALLEDGE;
+ break;
+
+ case IRQT_BOTHEDGE:
+ newvalue = S3C2410_EXTINT_BOTHEDGE;
+ break;
+
+ case IRQT_LOW:
+ newvalue = S3C2410_EXTINT_LOWLEV;
+ break;
+
+ case IRQT_HIGH:
+ newvalue = S3C2410_EXTINT_HILEV;
+ break;
+
+ default:
+ printk(KERN_ERR "No such irq type %d", type);
+ return -1;
+ }
+
+ value = __raw_readl(extint_reg);
+ value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
+ __raw_writel(value, extint_reg);
+
+ return 0;
+}
+
+static struct irq_chip s3c_irqext_chip = {
+ .name = "s3c-ext",
+ .mask = s3c_irqext_mask,
+ .unmask = s3c_irqext_unmask,
+ .ack = s3c_irqext_ack,
+ .set_type = s3c_irqext_type,
+ .set_wake = s3c_irqext_wake
+};
+
+static struct irq_chip s3c_irq_eint0t4 = {
+ .name = "s3c-ext0",
+ .ack = s3c_irq_ack,
+ .mask = s3c_irq_mask,
+ .unmask = s3c_irq_unmask,
+ .set_wake = s3c_irq_wake,
+ .set_type = s3c_irqext_type,
+};
+
+/* mask values for the parent registers for each of the interrupt types */
+
+#define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0))
+#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0))
+#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0))
+#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
+
+
+/* UART0 */
+
+static void
+s3c_irq_uart0_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
+}
+
+static void
+s3c_irq_uart0_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_UART0);
+}
+
+static void
+s3c_irq_uart0_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
+}
+
+static struct irq_chip s3c_irq_uart0 = {
+ .name = "s3c-uart0",
+ .mask = s3c_irq_uart0_mask,
+ .unmask = s3c_irq_uart0_unmask,
+ .ack = s3c_irq_uart0_ack,
+};
+
+/* UART1 */
+
+static void
+s3c_irq_uart1_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
+}
+
+static void
+s3c_irq_uart1_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_UART1);
+}
+
+static void
+s3c_irq_uart1_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
+}
+
+static struct irq_chip s3c_irq_uart1 = {
+ .name = "s3c-uart1",
+ .mask = s3c_irq_uart1_mask,
+ .unmask = s3c_irq_uart1_unmask,
+ .ack = s3c_irq_uart1_ack,
+};
+
+/* UART2 */
+
+static void
+s3c_irq_uart2_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
+}
+
+static void
+s3c_irq_uart2_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_UART2);
+}
+
+static void
+s3c_irq_uart2_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
+}
+
+static struct irq_chip s3c_irq_uart2 = {
+ .name = "s3c-uart2",
+ .mask = s3c_irq_uart2_mask,
+ .unmask = s3c_irq_uart2_unmask,
+ .ack = s3c_irq_uart2_ack,
+};
+
+/* ADC and Touchscreen */
+
+static void
+s3c_irq_adc_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
+}
+
+static void
+s3c_irq_adc_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
+}
+
+static void
+s3c_irq_adc_ack(unsigned int irqno)
+{
+ s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
+}
+
+static struct irq_chip s3c_irq_adc = {
+ .name = "s3c-adc",
+ .mask = s3c_irq_adc_mask,
+ .unmask = s3c_irq_adc_unmask,
+ .ack = s3c_irq_adc_ack,
+};
+
+/* irq demux for adc */
+static void s3c_irq_demux_adc(unsigned int irq,
+ struct irq_desc *desc)
+{
+ unsigned int subsrc, submsk;
+ unsigned int offset = 9;
+ struct irq_desc *mydesc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+ subsrc = __raw_readl(S3C2410_SUBSRCPND);
+ submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+ subsrc &= ~submsk;
+ subsrc >>= offset;
+ subsrc &= 3;
+
+ if (subsrc != 0) {
+ if (subsrc & 1) {
+ mydesc = irq_desc + IRQ_TC;
+ desc_handle_irq(IRQ_TC, mydesc);
+ }
+ if (subsrc & 2) {
+ mydesc = irq_desc + IRQ_ADC;
+ desc_handle_irq(IRQ_ADC, mydesc);
+ }
+ }
+}
+
+static void s3c_irq_demux_uart(unsigned int start)
+{
+ unsigned int subsrc, submsk;
+ unsigned int offset = start - IRQ_S3CUART_RX0;
+ struct irq_desc *desc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+ subsrc = __raw_readl(S3C2410_SUBSRCPND);
+ submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+ irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
+ start, offset, subsrc, submsk);
+
+ subsrc &= ~submsk;
+ subsrc >>= offset;
+ subsrc &= 7;
+
+ if (subsrc != 0) {
+ desc = irq_desc + start;
+
+ if (subsrc & 1)
+ desc_handle_irq(start, desc);
+
+ desc++;
+
+ if (subsrc & 2)
+ desc_handle_irq(start+1, desc);
+
+ desc++;
+
+ if (subsrc & 4)
+ desc_handle_irq(start+2, desc);
+ }
+}
+
+/* uart demux entry points */
+
+static void
+s3c_irq_demux_uart0(unsigned int irq,
+ struct irq_desc *desc)
+{
+ irq = irq;
+ s3c_irq_demux_uart(IRQ_S3CUART_RX0);
+}
+
+static void
+s3c_irq_demux_uart1(unsigned int irq,
+ struct irq_desc *desc)
+{
+ irq = irq;
+ s3c_irq_demux_uart(IRQ_S3CUART_RX1);
+}
+
+static void
+s3c_irq_demux_uart2(unsigned int irq,
+ struct irq_desc *desc)
+{
+ irq = irq;
+ s3c_irq_demux_uart(IRQ_S3CUART_RX2);
+}
+
+static void
+s3c_irq_demux_extint8(unsigned int irq,
+ struct irq_desc *desc)
+{
+ unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+ unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+ eintpnd &= ~eintmsk;
+ eintpnd &= ~0xff; /* ignore lower irqs */
+
+ /* we may as well handle all the pending IRQs here */
+
+ while (eintpnd) {
+ irq = __ffs(eintpnd);
+ eintpnd &= ~(1<<irq);
+
+ irq += (IRQ_EINT4 - 4);
+ desc_handle_irq(irq, irq_desc + irq);
+ }
+
+}
+
+static void
+s3c_irq_demux_extint4t7(unsigned int irq,
+ struct irq_desc *desc)
+{
+ unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+ unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+ eintpnd &= ~eintmsk;
+ eintpnd &= 0xff; /* only lower irqs */
+
+ /* we may as well handle all the pending IRQs here */
+
+ while (eintpnd) {
+ irq = __ffs(eintpnd);
+ eintpnd &= ~(1<<irq);
+
+ irq += (IRQ_EINT4 - 4);
+
+ desc_handle_irq(irq, irq_desc + irq);
+ }
+}
+
+#ifdef CONFIG_PM
+
+static struct sleep_save irq_save[] = {
+ SAVE_ITEM(S3C2410_INTMSK),
+ SAVE_ITEM(S3C2410_INTSUBMSK),
+};
+
+/* the extint values move between the s3c2410/s3c2440 and the s3c2412
+ * so we use an array to hold them, and to calculate the address of
+ * the register at run-time
+*/
+
+static unsigned long save_extint[3];
+static unsigned long save_eintflt[4];
+static unsigned long save_eintmask;
+
+int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+ save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
+
+ for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+ save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
+
+ s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+ save_eintmask = __raw_readl(S3C24XX_EINTMASK);
+
+ return 0;
+}
+
+int s3c24xx_irq_resume(struct sys_device *dev)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+ __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
+
+ for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+ __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
+
+ s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+ __raw_writel(save_eintmask, S3C24XX_EINTMASK);
+
+ return 0;
+}
+
+#else
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume NULL
+#endif
+
+/* s3c24xx_init_irq
+ *
+ * Initialise S3C2410 IRQ system
+*/
+
+void __init s3c24xx_init_irq(void)
+{
+ unsigned long pend;
+ unsigned long last;
+ int irqno;
+ int i;
+
+ irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
+
+ /* first, clear all interrupts pending... */
+
+ last = 0;
+ for (i = 0; i < 4; i++) {
+ pend = __raw_readl(S3C24XX_EINTPEND);
+
+ if (pend == 0 || pend == last)
+ break;
+
+ __raw_writel(pend, S3C24XX_EINTPEND);
+ printk("irq: clearing pending ext status %08x\n", (int)pend);
+ last = pend;
+ }
+
+ last = 0;
+ for (i = 0; i < 4; i++) {
+ pend = __raw_readl(S3C2410_INTPND);
+
+ if (pend == 0 || pend == last)
+ break;
+
+ __raw_writel(pend, S3C2410_SRCPND);
+ __raw_writel(pend, S3C2410_INTPND);
+ printk("irq: clearing pending status %08x\n", (int)pend);
+ last = pend;
+ }
+
+ last = 0;
+ for (i = 0; i < 4; i++) {
+ pend = __raw_readl(S3C2410_SUBSRCPND);
+
+ if (pend == 0 || pend == last)
+ break;
+
+ printk("irq: clearing subpending status %08x\n", (int)pend);
+ __raw_writel(pend, S3C2410_SUBSRCPND);
+ last = pend;
+ }
+
+ /* register the main interrupts */
+
+ irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
+
+ for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
+ /* set all the s3c2410 internal irqs */
+
+ switch (irqno) {
+ /* deal with the special IRQs (cascaded) */
+
+ case IRQ_EINT4t7:
+ case IRQ_EINT8t23:
+ case IRQ_UART0:
+ case IRQ_UART1:
+ case IRQ_UART2:
+ case IRQ_ADCPARENT:
+ set_irq_chip(irqno, &s3c_irq_level_chip);
+ set_irq_handler(irqno, handle_level_irq);
+ break;
+
+ case IRQ_RESERVED6:
+ case IRQ_RESERVED24:
+ /* no IRQ here */
+ break;
+
+ default:
+ //irqdbf("registering irq %d (s3c irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_chip);
+ set_irq_handler(irqno, handle_edge_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+ }
+
+ /* setup the cascade irq handlers */
+
+ set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
+ set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
+
+ set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
+ set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
+ set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
+ set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
+
+ /* external interrupts */
+
+ for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
+ irqdbf("registering irq %d (ext int)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_eint0t4);
+ set_irq_handler(irqno, handle_edge_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
+ irqdbf("registering irq %d (extended s3c irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irqext_chip);
+ set_irq_handler(irqno, handle_edge_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ /* register the uart interrupts */
+
+ irqdbf("s3c2410: registering external interrupts\n");
+
+ for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
+ irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_uart0);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
+ irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_uart1);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
+ irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_uart2);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
+ irqdbf("registering irq %d (s3c adc irq)\n", irqno);
+ set_irq_chip(irqno, &s3c_irq_adc);
+ set_irq_handler(irqno, handle_edge_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ irqdbf("s3c2410: registered interrupt handlers\n");
+}
diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/plat-s3c24xx/pm-simtec.c
index 619133eb716..bd965f2feec 100644
--- a/arch/arm/mach-s3c2410/pm-simtec.c
+++ b/arch/arm/plat-s3c24xx/pm-simtec.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/pm-simtec.c
+/* linux/arch/arm/plat-s3c24xx/pm-simtec.c
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -32,7 +32,7 @@
#include <asm/mach-types.h>
-#include "pm.h"
+#include <asm/plat-s3c24xx/pm.h>
#define COPYRIGHT ", (c) 2005 Simtec Electronics"
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c
new file mode 100644
index 00000000000..ecf68d61190
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/pm.c
@@ -0,0 +1,659 @@
+/* linux/arch/arm/plat-s3c24xx/pm.c
+ *
+ * Copyright (c) 2004,2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX Power Manager (Suspend-To-RAM) support
+ *
+ * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Parts based on arch/arm/mach-pxa/pm.c
+ *
+ * Thanks to Dimitry Andric for debugging
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/crc32.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-irq.h>
+
+#include <asm/mach/time.h>
+
+#include <asm/plat-s3c24xx/pm.h>
+
+/* for external use */
+
+unsigned long s3c_pm_flags;
+
+#define PFX "s3c24xx-pm: "
+
+static struct sleep_save core_save[] = {
+ SAVE_ITEM(S3C2410_LOCKTIME),
+ SAVE_ITEM(S3C2410_CLKCON),
+
+ /* we restore the timings here, with the proviso that the board
+ * brings the system up in an slower, or equal frequency setting
+ * to the original system.
+ *
+ * if we cannot guarantee this, then things are going to go very
+ * wrong here, as we modify the refresh and both pll settings.
+ */
+
+ SAVE_ITEM(S3C2410_BWSCON),
+ SAVE_ITEM(S3C2410_BANKCON0),
+ SAVE_ITEM(S3C2410_BANKCON1),
+ SAVE_ITEM(S3C2410_BANKCON2),
+ SAVE_ITEM(S3C2410_BANKCON3),
+ SAVE_ITEM(S3C2410_BANKCON4),
+ SAVE_ITEM(S3C2410_BANKCON5),
+
+ SAVE_ITEM(S3C2410_CLKDIVN),
+ SAVE_ITEM(S3C2410_MPLLCON),
+ SAVE_ITEM(S3C2410_UPLLCON),
+ SAVE_ITEM(S3C2410_CLKSLOW),
+ SAVE_ITEM(S3C2410_REFRESH),
+};
+
+static struct sleep_save gpio_save[] = {
+ SAVE_ITEM(S3C2410_GPACON),
+ SAVE_ITEM(S3C2410_GPADAT),
+
+ SAVE_ITEM(S3C2410_GPBCON),
+ SAVE_ITEM(S3C2410_GPBDAT),
+ SAVE_ITEM(S3C2410_GPBUP),
+
+ SAVE_ITEM(S3C2410_GPCCON),
+ SAVE_ITEM(S3C2410_GPCDAT),
+ SAVE_ITEM(S3C2410_GPCUP),
+
+ SAVE_ITEM(S3C2410_GPDCON),
+ SAVE_ITEM(S3C2410_GPDDAT),
+ SAVE_ITEM(S3C2410_GPDUP),
+
+ SAVE_ITEM(S3C2410_GPECON),
+ SAVE_ITEM(S3C2410_GPEDAT),
+ SAVE_ITEM(S3C2410_GPEUP),
+
+ SAVE_ITEM(S3C2410_GPFCON),
+ SAVE_ITEM(S3C2410_GPFDAT),
+ SAVE_ITEM(S3C2410_GPFUP),
+
+ SAVE_ITEM(S3C2410_GPGCON),
+ SAVE_ITEM(S3C2410_GPGDAT),
+ SAVE_ITEM(S3C2410_GPGUP),
+
+ SAVE_ITEM(S3C2410_GPHCON),
+ SAVE_ITEM(S3C2410_GPHDAT),
+ SAVE_ITEM(S3C2410_GPHUP),
+
+ SAVE_ITEM(S3C2410_DCLKCON),
+};
+
+#ifdef CONFIG_S3C2410_PM_DEBUG
+
+#define SAVE_UART(va) \
+ SAVE_ITEM((va) + S3C2410_ULCON), \
+ SAVE_ITEM((va) + S3C2410_UCON), \
+ SAVE_ITEM((va) + S3C2410_UFCON), \
+ SAVE_ITEM((va) + S3C2410_UMCON), \
+ SAVE_ITEM((va) + S3C2410_UBRDIV)
+
+static struct sleep_save uart_save[] = {
+ SAVE_UART(S3C24XX_VA_UART0),
+ SAVE_UART(S3C24XX_VA_UART1),
+#ifndef CONFIG_CPU_S3C2400
+ SAVE_UART(S3C24XX_VA_UART2),
+#endif
+};
+
+/* debug
+ *
+ * we send the debug to printascii() to allow it to be seen if the
+ * system never wakes up from the sleep
+*/
+
+extern void printascii(const char *);
+
+void pm_dbg(const char *fmt, ...)
+{
+ va_list va;
+ char buff[256];
+
+ va_start(va, fmt);
+ vsprintf(buff, fmt, va);
+ va_end(va);
+
+ printascii(buff);
+}
+
+static void s3c2410_pm_debug_init(void)
+{
+ unsigned long tmp = __raw_readl(S3C2410_CLKCON);
+
+ /* re-start uart clocks */
+ tmp |= S3C2410_CLKCON_UART0;
+ tmp |= S3C2410_CLKCON_UART1;
+ tmp |= S3C2410_CLKCON_UART2;
+
+ __raw_writel(tmp, S3C2410_CLKCON);
+ udelay(10);
+}
+
+#define DBG(fmt...) pm_dbg(fmt)
+#else
+#define DBG(fmt...) printk(KERN_DEBUG fmt)
+
+#define s3c2410_pm_debug_init() do { } while(0)
+
+static struct sleep_save uart_save[] = {};
+#endif
+
+#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
+
+/* suspend checking code...
+ *
+ * this next area does a set of crc checks over all the installed
+ * memory, so the system can verify if the resume was ok.
+ *
+ * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
+ * increasing it will mean that the area corrupted will be less easy to spot,
+ * and reducing the size will cause the CRC save area to grow
+*/
+
+#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
+
+static u32 crc_size; /* size needed for the crc block */
+static u32 *crcs; /* allocated over suspend/resume */
+
+typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
+
+/* s3c2410_pm_run_res
+ *
+ * go thorugh the given resource list, and look for system ram
+*/
+
+static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
+{
+ while (ptr != NULL) {
+ if (ptr->child != NULL)
+ s3c2410_pm_run_res(ptr->child, fn, arg);
+
+ if ((ptr->flags & IORESOURCE_MEM) &&
+ strcmp(ptr->name, "System RAM") == 0) {
+ DBG("Found system RAM at %08lx..%08lx\n",
+ ptr->start, ptr->end);
+ arg = (fn)(ptr, arg);
+ }
+
+ ptr = ptr->sibling;
+ }
+}
+
+static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
+{
+ s3c2410_pm_run_res(&iomem_resource, fn, arg);
+}
+
+static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
+{
+ u32 size = (u32)(res->end - res->start)+1;
+
+ size += CHECK_CHUNKSIZE-1;
+ size /= CHECK_CHUNKSIZE;
+
+ DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
+
+ *val += size * sizeof(u32);
+ return val;
+}
+
+/* s3c2410_pm_prepare_check
+ *
+ * prepare the necessary information for creating the CRCs. This
+ * must be done before the final save, as it will require memory
+ * allocating, and thus touching bits of the kernel we do not
+ * know about.
+*/
+
+static void s3c2410_pm_check_prepare(void)
+{
+ crc_size = 0;
+
+ s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
+
+ DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
+
+ crcs = kmalloc(crc_size+4, GFP_KERNEL);
+ if (crcs == NULL)
+ printk(KERN_ERR "Cannot allocated CRC save area\n");
+}
+
+static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
+{
+ unsigned long addr, left;
+
+ for (addr = res->start; addr < res->end;
+ addr += CHECK_CHUNKSIZE) {
+ left = res->end - addr;
+
+ if (left > CHECK_CHUNKSIZE)
+ left = CHECK_CHUNKSIZE;
+
+ *val = crc32_le(~0, phys_to_virt(addr), left);
+ val++;
+ }
+
+ return val;
+}
+
+/* s3c2410_pm_check_store
+ *
+ * compute the CRC values for the memory blocks before the final
+ * sleep.
+*/
+
+static void s3c2410_pm_check_store(void)
+{
+ if (crcs != NULL)
+ s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
+}
+
+/* in_region
+ *
+ * return TRUE if the area defined by ptr..ptr+size contatins the
+ * what..what+whatsz
+*/
+
+static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
+{
+ if ((what+whatsz) < ptr)
+ return 0;
+
+ if (what > (ptr+size))
+ return 0;
+
+ return 1;
+}
+
+static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
+{
+ void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
+ unsigned long addr;
+ unsigned long left;
+ void *ptr;
+ u32 calc;
+
+ for (addr = res->start; addr < res->end;
+ addr += CHECK_CHUNKSIZE) {
+ left = res->end - addr;
+
+ if (left > CHECK_CHUNKSIZE)
+ left = CHECK_CHUNKSIZE;
+
+ ptr = phys_to_virt(addr);
+
+ if (in_region(ptr, left, crcs, crc_size)) {
+ DBG("skipping %08lx, has crc block in\n", addr);
+ goto skip_check;
+ }
+
+ if (in_region(ptr, left, save_at, 32*4 )) {
+ DBG("skipping %08lx, has save block in\n", addr);
+ goto skip_check;
+ }
+
+ /* calculate and check the checksum */
+
+ calc = crc32_le(~0, ptr, left);
+ if (calc != *val) {
+ printk(KERN_ERR PFX "Restore CRC error at "
+ "%08lx (%08x vs %08x)\n", addr, calc, *val);
+
+ DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
+ addr, calc, *val);
+ }
+
+ skip_check:
+ val++;
+ }
+
+ return val;
+}
+
+/* s3c2410_pm_check_restore
+ *
+ * check the CRCs after the restore event and free the memory used
+ * to hold them
+*/
+
+static void s3c2410_pm_check_restore(void)
+{
+ if (crcs != NULL) {
+ s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
+ kfree(crcs);
+ crcs = NULL;
+ }
+}
+
+#else
+
+#define s3c2410_pm_check_prepare() do { } while(0)
+#define s3c2410_pm_check_restore() do { } while(0)
+#define s3c2410_pm_check_store() do { } while(0)
+#endif
+
+/* helper functions to save and restore register state */
+
+void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
+{
+ for (; count > 0; count--, ptr++) {
+ ptr->val = __raw_readl(ptr->reg);
+ DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
+ }
+}
+
+/* s3c2410_pm_do_restore
+ *
+ * restore the system from the given list of saved registers
+ *
+ * Note, we do not use DBG() in here, as the system may not have
+ * restore the UARTs state yet
+*/
+
+void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
+{
+ for (; count > 0; count--, ptr++) {
+ printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
+ ptr->reg, ptr->val, __raw_readl(ptr->reg));
+
+ __raw_writel(ptr->val, ptr->reg);
+ }
+}
+
+/* s3c2410_pm_do_restore_core
+ *
+ * similar to s3c2410_pm_do_restore_core
+ *
+ * WARNING: Do not put any debug in here that may effect memory or use
+ * peripherals, as things may be changing!
+*/
+
+static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
+{
+ for (; count > 0; count--, ptr++) {
+ __raw_writel(ptr->val, ptr->reg);
+ }
+}
+
+/* s3c2410_pm_show_resume_irqs
+ *
+ * print any IRQs asserted at resume time (ie, we woke from)
+*/
+
+static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
+ unsigned long mask)
+{
+ int i;
+
+ which &= ~mask;
+
+ for (i = 0; i <= 31; i++) {
+ if ((which) & (1L<<i)) {
+ DBG("IRQ %d asserted at resume\n", start+i);
+ }
+ }
+}
+
+/* s3c2410_pm_check_resume_pin
+ *
+ * check to see if the pin is configured correctly for sleep mode, and
+ * make any necessary adjustments if it is not
+*/
+
+static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
+{
+ unsigned long irqstate;
+ unsigned long pinstate;
+ int irq = s3c2410_gpio_getirq(pin);
+
+ if (irqoffs < 4)
+ irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
+ else
+ irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
+
+ pinstate = s3c2410_gpio_getcfg(pin);
+
+ if (!irqstate) {
+ if (pinstate == S3C2410_GPIO_IRQ)
+ DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
+ } else {
+ if (pinstate == S3C2410_GPIO_IRQ) {
+ DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
+ s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
+ }
+ }
+}
+
+/* s3c2410_pm_configure_extint
+ *
+ * configure all external interrupt pins
+*/
+
+static void s3c2410_pm_configure_extint(void)
+{
+ int pin;
+
+ /* for each of the external interrupts (EINT0..EINT15) we
+ * need to check wether it is an external interrupt source,
+ * and then configure it as an input if it is not
+ */
+
+ for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
+ s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
+ }
+
+ for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
+ s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
+ }
+}
+
+void (*pm_cpu_prep)(void);
+void (*pm_cpu_sleep)(void);
+
+#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
+
+/* s3c2410_pm_enter
+ *
+ * central control for sleep/resume process
+*/
+
+static int s3c2410_pm_enter(suspend_state_t state)
+{
+ unsigned long regs_save[16];
+
+ /* ensure the debug is initialised (if enabled) */
+
+ s3c2410_pm_debug_init();
+
+ DBG("s3c2410_pm_enter(%d)\n", state);
+
+ if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
+ printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
+ return -EINVAL;
+ }
+
+ if (state != PM_SUSPEND_MEM) {
+ printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
+ return -EINVAL;
+ }
+
+ /* check if we have anything to wake-up with... bad things seem
+ * to happen if you suspend with no wakeup (system will often
+ * require a full power-cycle)
+ */
+
+ if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
+ !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
+ printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
+ printk(KERN_ERR PFX "Aborting sleep\n");
+ return -EINVAL;
+ }
+
+ /* prepare check area if configured */
+
+ s3c2410_pm_check_prepare();
+
+ /* store the physical address of the register recovery block */
+
+ s3c2410_sleep_save_phys = virt_to_phys(regs_save);
+
+ DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
+
+ /* save all necessary core registers not covered by the drivers */
+
+ s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
+ s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
+ s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
+
+ /* set the irq configuration for wake */
+
+ s3c2410_pm_configure_extint();
+
+ DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
+ s3c_irqwake_intmask, s3c_irqwake_eintmask);
+
+ __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
+ __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
+
+ /* ack any outstanding external interrupts before we go to sleep */
+
+ __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
+ __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
+ __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
+
+ /* call cpu specific preperation */
+
+ pm_cpu_prep();
+
+ /* flush cache back to ram */
+
+ flush_cache_all();
+
+ s3c2410_pm_check_store();
+
+ /* send the cpu to sleep... */
+
+ __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
+
+ /* s3c2410_cpu_save will also act as our return point from when
+ * we resume as it saves its own register state, so use the return
+ * code to differentiate return from save and return from sleep */
+
+ if (s3c2410_cpu_save(regs_save) == 0) {
+ flush_cache_all();
+ pm_cpu_sleep();
+ }
+
+ /* restore the cpu state */
+
+ cpu_init();
+
+ /* restore the system state */
+
+ s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+ s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
+ s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
+
+ s3c2410_pm_debug_init();
+
+ /* check what irq (if any) restored the system */
+
+ DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
+ __raw_readl(S3C2410_SRCPND),
+ __raw_readl(S3C2410_EINTPEND));
+
+ s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
+ s3c_irqwake_intmask);
+
+ s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
+ s3c_irqwake_eintmask);
+
+ DBG("post sleep, preparing to return\n");
+
+ s3c2410_pm_check_restore();
+
+ /* ok, let's return from sleep */
+
+ DBG("S3C2410 PM Resume (post-restore)\n");
+ return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int s3c2410_pm_prepare(suspend_state_t state)
+{
+ return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static int s3c2410_pm_finish(suspend_state_t state)
+{
+ return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops s3c2410_pm_ops = {
+ .pm_disk_mode = PM_DISK_FIRMWARE,
+ .prepare = s3c2410_pm_prepare,
+ .enter = s3c2410_pm_enter,
+ .finish = s3c2410_pm_finish,
+};
+
+/* s3c2410_pm_init
+ *
+ * Attach the power management functions. This should be called
+ * from the board specific initialisation if the board supports
+ * it.
+*/
+
+int __init s3c2410_pm_init(void)
+{
+ printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
+
+ pm_set_ops(&s3c2410_pm_ops);
+ return 0;
+}
diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/plat-s3c24xx/s3c244x-irq.c
index ede94636a72..a0e39d89401 100644
--- a/arch/arm/mach-s3c2410/s3c244x-irq.c
+++ b/arch/arm/plat-s3c24xx/s3c244x-irq.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c244x-irq.c
+/* linux/arch/arm/plat-s3c24xx/s3c244x-irq.c
*
* Copyright (c) 2003,2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
#include <asm/arch/regs-irq.h>
#include <asm/arch/regs-gpio.h>
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
/* camera irq */
diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c
index 23c7494ad10..767f2e9a3a5 100644
--- a/arch/arm/mach-s3c2410/s3c244x.c
+++ b/arch/arm/plat-s3c24xx/s3c244x.c
@@ -1,9 +1,9 @@
-/* linux/arch/arm/mach-s3c2410/s3c244x.c
+/* linux/arch/arm/plat-s3c24xx/s3c244x.c
*
* Copyright (c) 2004-2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
- * Samsung S3C2440 and S3C2442 Mobile CPU support
+ * Samsung S3C2440 and S3C2442 Mobile CPU support (not S3C2443)
*
* 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
@@ -35,13 +35,13 @@
#include <asm/arch/regs-gpioj.h>
#include <asm/arch/regs-dsc.h>
-#include "s3c2410.h"
-#include "s3c2440.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
#include "s3c244x.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
static struct map_desc s3c244x_iodesc[] __initdata = {
IODESC_ENT(CLKPWR),
diff --git a/arch/arm/mach-s3c2410/s3c244x.h b/arch/arm/plat-s3c24xx/s3c244x.h
index 1488c1eb37e..f8ed17676a3 100644
--- a/arch/arm/mach-s3c2410/s3c244x.h
+++ b/arch/arm/plat-s3c24xx/s3c244x.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c244x.h
+/* linux/arch/arm/plat-s3c24xx/s3c244x.h
*
* Copyright (c) 2004-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
new file mode 100644
index 00000000000..435349dc324
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/sleep.S
@@ -0,0 +1,157 @@
+/* linux/arch/arm/mach-s3c2410/sleep.S
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 Power Manager (Suspend-To-RAM) support
+ *
+ * Based on PXA/SA1100 sleep code by:
+ * Nicolas Pitre, (c) 2002 Monta Vista Software Inc
+ * Cliff Brake, (c) 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+#include <asm/arch/map.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-serial.h>
+
+/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
+ * reset the UART configuration, only enable if you really need this!
+*/
+//#define CONFIG_DEBUG_RESUME
+
+ .text
+
+ /* s3c2410_cpu_save
+ *
+ * save enough of the CPU state to allow us to re-start
+ * pm.c code. as we store items like the sp/lr, we will
+ * end up returning from this function when the cpu resumes
+ * so the return value is set to mark this.
+ *
+ * This arangement means we avoid having to flush the cache
+ * from this code.
+ *
+ * entry:
+ * r0 = pointer to save block
+ *
+ * exit:
+ * r0 = 0 => we stored everything
+ * 1 => resumed from sleep
+ */
+
+ENTRY(s3c2410_cpu_save)
+ stmfd sp!, { r4 - r12, lr }
+
+ @@ store co-processor registers
+
+ mrc p15, 0, r4, c13, c0, 0 @ PID
+ mrc p15, 0, r5, c3, c0, 0 @ Domain ID
+ mrc p15, 0, r6, c2, c0, 0 @ translation table base address
+ mrc p15, 0, r7, c1, c0, 0 @ control register
+
+ stmia r0, { r4 - r13 }
+
+ mov r0, #0
+ ldmfd sp, { r4 - r12, pc }
+
+ @@ return to the caller, after having the MMU
+ @@ turned on, this restores the last bits from the
+ @@ stack
+resume_with_mmu:
+ mov r0, #1
+ ldmfd sp!, { r4 - r12, pc }
+
+ .ltorg
+
+ @@ the next bits sit in the .data segment, even though they
+ @@ happen to be code... the s3c2410_sleep_save_phys needs to be
+ @@ accessed by the resume code before it can restore the MMU.
+ @@ This means that the variable has to be close enough for the
+ @@ code to read it... since the .text segment needs to be RO,
+ @@ the data segment can be the only place to put this code.
+
+ .data
+
+ .global s3c2410_sleep_save_phys
+s3c2410_sleep_save_phys:
+ .word 0
+
+ /* s3c2410_cpu_resume
+ *
+ * resume code entry for bootloader to call
+ *
+ * we must put this code here in the data segment as we have no
+ * other way of restoring the stack pointer after sleep, and we
+ * must not write to the code segment (code is read-only)
+ */
+
+ENTRY(s3c2410_cpu_resume)
+ mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+ msr cpsr_c, r0
+
+ @@ load UART to allow us to print the two characters for
+ @@ resume debug
+
+ mov r2, #S3C24XX_PA_UART & 0xff000000
+ orr r2, r2, #S3C24XX_PA_UART & 0xff000
+
+#if 0
+ /* SMDK2440 LED set */
+ mov r14, #S3C24XX_PA_GPIO
+ ldr r12, [ r14, #0x54 ]
+ bic r12, r12, #3<<4
+ orr r12, r12, #1<<7
+ str r12, [ r14, #0x54 ]
+#endif
+
+#ifdef CONFIG_DEBUG_RESUME
+ mov r3, #'L'
+ strb r3, [ r2, #S3C2410_UTXH ]
+1001:
+ ldrb r14, [ r3, #S3C2410_UTRSTAT ]
+ tst r14, #S3C2410_UTRSTAT_TXE
+ beq 1001b
+#endif /* CONFIG_DEBUG_RESUME */
+
+ mov r1, #0
+ mcr p15, 0, r1, c8, c7, 0 @@ invalidate I & D TLBs
+ mcr p15, 0, r1, c7, c7, 0 @@ invalidate I & D caches
+
+ ldr r0, s3c2410_sleep_save_phys @ address of restore block
+ ldmia r0, { r4 - r13 }
+
+ mcr p15, 0, r4, c13, c0, 0 @ PID
+ mcr p15, 0, r5, c3, c0, 0 @ Domain ID
+ mcr p15, 0, r6, c2, c0, 0 @ translation table base
+
+#ifdef CONFIG_DEBUG_RESUME
+ mov r3, #'R'
+ strb r3, [ r2, #S3C2410_UTXH ]
+#endif
+
+ ldr r2, =resume_with_mmu
+ mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, etc
+ nop @ second-to-last before mmu
+ mov pc, r2 @ go back to virtual address
+
+ .ltorg
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/plat-s3c24xx/time.c
index 9910bf0f2ce..c523d1c9cce 100644
--- a/arch/arm/mach-s3c2410/time.c
+++ b/arch/arm/plat-s3c24xx/time.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/time.c
+/* linux/arch/arm/plat-s3c24xx/time.c
*
* Copyright (C) 2003-2005 Simtec Electronics
* Ben Dooks, <ben@simtec.co.uk>
@@ -37,8 +37,8 @@
#include <asm/arch/regs-irq.h>
#include <asm/mach/time.h>
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
static unsigned long timer_startval;
static unsigned long timer_usec_ticks;
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
index 49e7b12fe71..00c435452d7 100644
--- a/arch/avr32/mach-at32ap/clock.c
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2006 Atmel Corporation
*
- * Based on arch/arm/mach-at91rm9200/clock.c
+ * Based on arch/arm/mach-at91/clock.c
* Copyright (C) 2005 David Brownell
* Copyright (C) 2005 Ivan Kokshaysky
*
diff --git a/arch/avr32/mach-at32ap/clock.h b/arch/avr32/mach-at32ap/clock.h
index f953f044ba4..bb8e1f29583 100644
--- a/arch/avr32/mach-at32ap/clock.h
+++ b/arch/avr32/mach-at32ap/clock.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2006 Atmel Corporation
*
- * Based on arch/arm/mach-at91rm9200/clock.c
+ * Based on arch/arm/mach-at91/clock.c
* Copyright (C) 2005 David Brownell
* Copyright (C) 2005 Ivan Kokshaysky
*
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index fb3e72328a5..e5eb97a910e 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -850,10 +850,9 @@ static inline int acpi_parse_madt_ioapic_entries(void)
static void __init acpi_process_madt(void)
{
#ifdef CONFIG_X86_LOCAL_APIC
- int count, error;
+ int error;
- count = acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt);
- if (count >= 1) {
+ if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
/*
* Parse MADT LAPIC entries
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 53ca6e89798..1bb06937214 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -191,6 +191,94 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"),
},
},
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant BL20p G3",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"),
+ },
+ },
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant BL20p G4",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"),
+ },
+ },
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant BL30p G1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"),
+ },
+ },
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant BL25p G1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"),
+ },
+ },
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant BL35p G1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"),
+ },
+ },
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant BL45p G1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"),
+ },
+ },
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant BL45p G2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"),
+ },
+ },
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant BL460c G1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"),
+ },
+ },
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant BL465c G1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"),
+ },
+ },
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant BL480c G1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"),
+ },
+ },
+ {
+ .callback = set_bf_sort,
+ .ident = "HP ProLiant BL685c G1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
+ },
+ },
{}
};
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 9197d7b361b..3549c94467b 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -651,7 +651,7 @@ int __init acpi_boot_init(void)
* information -- the successor to MPS tables.
*/
- if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt) < 1) {
+ if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
printk(KERN_ERR PREFIX "Can't find MADT\n");
goto skip_madt;
}
@@ -702,7 +702,7 @@ int __init acpi_boot_init(void)
* gets interrupts such as power and sleep buttons. If it's not
* on a Legacy interrupt, it needs to be setup.
*/
- if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt) < 1)
+ if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt))
printk(KERN_ERR PREFIX "Can't find FADT\n");
#ifdef CONFIG_SMP
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 340d9beab6d..6dfbd52694a 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -620,6 +620,15 @@ config RTAS_FLASH
tristate "Firmware flash interface"
depends on PPC64 && RTAS_PROC
+config PPC_PMI
+ tristate "Support for PMI"
+ depends PPC_IBM_CELL_BLADE
+ help
+ PMI (Platform Management Interrupt) is a way to
+ communicate with the BMC (Baseboard Mangement Controller).
+ It is used in some IBM Cell blades.
+ default m
+
config MMIO_NVRAM
bool
default n
diff --git a/arch/powerpc/boot/dts/kuroboxHD.dts b/arch/powerpc/boot/dts/kuroboxHD.dts
index 096e94ac415..b89791802e8 100644
--- a/arch/powerpc/boot/dts/kuroboxHD.dts
+++ b/arch/powerpc/boot/dts/kuroboxHD.dts
@@ -35,7 +35,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHD.dtb -V 16 kuroboxHD.dts"
PowerPC,603e { /* Really 8241 */
linux,phandle = <2100>;
- linux,boot-cpu;
device_type = "cpu";
reg = <0>;
clock-frequency = <bebc200>; /* Fixed by bootwrapper */
diff --git a/arch/powerpc/boot/dts/kuroboxHG.dts b/arch/powerpc/boot/dts/kuroboxHG.dts
index d06b0b01889..753102752d8 100644
--- a/arch/powerpc/boot/dts/kuroboxHG.dts
+++ b/arch/powerpc/boot/dts/kuroboxHG.dts
@@ -35,7 +35,6 @@ build with: "dtc -f -I dts -O dtb -o kuroboxHG.dtb -V 16 kuroboxHG.dts"
PowerPC,603e { /* Really 8241 */
linux,phandle = <2100>;
- linux,boot-cpu;
device_type = "cpu";
reg = <0>;
clock-frequency = <fdad680>; /* Fixed by bootwrapper */
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
index c4d9562cbaa..41d0720c590 100644
--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -36,7 +36,6 @@
bus-frequency = <0>; // From U-Boot
32-bit;
linux,phandle = <201>;
- linux,boot-cpu;
};
};
diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts
index 26b44f7513d..260b2e44777 100644
--- a/arch/powerpc/boot/dts/mpc8272ads.dts
+++ b/arch/powerpc/boot/dts/mpc8272ads.dts
@@ -34,7 +34,6 @@
clock-frequency = <0>;
32-bit;
linux,phandle = <201>;
- linux,boot-cpu;
};
};
diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts
index 3d2f5a06df3..6d721900d00 100644
--- a/arch/powerpc/boot/dts/mpc8313erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8313erdb.dts
@@ -11,7 +11,7 @@
/ {
model = "MPC8313ERDB";
- compatible = "MPC83xx";
+ compatible = "MPC8313ERDB", "MPC831xRDB", "MPC83xxRDB";
#address-cells = <1>;
#size-cells = <1>;
@@ -59,7 +59,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <e 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
dfsrr;
};
@@ -68,7 +68,7 @@
compatible = "fsl-i2c";
reg = <3100 100>;
interrupts = <f 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
dfsrr;
};
@@ -77,7 +77,7 @@
compatible = "mpc83xx_spi";
reg = <7000 1000>;
interrupts = <10 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
mode = <0>;
};
@@ -88,8 +88,8 @@
reg = <23000 1000>;
#address-cells = <1>;
#size-cells = <0>;
- interrupt-parent = <700>;
- interrupts = <26 2>;
+ interrupt-parent = < &ipic >;
+ interrupts = <26 8>;
phy_type = "utmi_wide";
};
@@ -99,18 +99,15 @@
reg = <24520 20>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <24520>;
- ethernet-phy@1 {
- linux,phandle = <2452001>;
- interrupt-parent = <700>;
- interrupts = <13 2>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = < &ipic >;
+ interrupts = <13 8>;
reg = <1>;
device_type = "ethernet-phy";
};
- ethernet-phy@4 {
- linux,phandle = <2452004>;
- interrupt-parent = <700>;
- interrupts = <14 2>;
+ phy4: ethernet-phy@4 {
+ interrupt-parent = < &ipic >;
+ interrupts = <14 8>;
reg = <4>;
device_type = "ethernet-phy";
};
@@ -123,8 +120,8 @@
reg = <24000 1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <25 8 24 8 23 8>;
- interrupt-parent = <700>;
- phy-handle = <2452001>;
+ interrupt-parent = < &ipic >;
+ phy-handle = < &phy1 >;
};
ethernet@25000 {
@@ -134,8 +131,8 @@
reg = <25000 1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <22 8 21 8 20 8>;
- interrupt-parent = <700>;
- phy-handle = <2452004>;
+ interrupt-parent = < &ipic >;
+ phy-handle = < &phy4 >;
};
serial@4500 {
@@ -144,7 +141,7 @@
reg = <4500 100>;
clock-frequency = <0>;
interrupts = <9 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
serial@4600 {
@@ -153,7 +150,7 @@
reg = <4600 100>;
clock-frequency = <0>;
interrupts = <a 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
pci@8500 {
@@ -161,17 +158,17 @@
interrupt-map = <
/* IDSEL 0x0E -mini PCI */
- 7000 0 0 1 700 12 8
- 7000 0 0 2 700 12 8
- 7000 0 0 3 700 12 8
- 7000 0 0 4 700 12 8
+ 7000 0 0 1 &ipic 12 8
+ 7000 0 0 2 &ipic 12 8
+ 7000 0 0 3 &ipic 12 8
+ 7000 0 0 4 &ipic 12 8
/* IDSEL 0x0F - PCI slot */
- 7800 0 0 1 700 11 8
- 7800 0 0 2 700 12 8
- 7800 0 0 3 700 11 8
- 7800 0 0 4 700 12 8>;
- interrupt-parent = <700>;
+ 7800 0 0 1 &ipic 11 8
+ 7800 0 0 2 &ipic 12 8
+ 7800 0 0 3 &ipic 11 8
+ 7800 0 0 4 &ipic 12 8>;
+ interrupt-parent = < &ipic >;
interrupts = <42 8>;
bus-range = <0 0>;
ranges = <02000000 0 90000000 90000000 0 10000000
@@ -192,7 +189,7 @@
compatible = "talitos";
reg = <30000 7000>;
interrupts = <b 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
/* Rev. 2.2 */
num-channels = <1>;
channel-fifo-len = <18>;
@@ -206,8 +203,7 @@
* sense == 8: Level, low assertion
* sense == 2: Edge, high-to-low change
*/
- pic@700 {
- linux,phandle = <700>;
+ ipic: pic@700 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
diff --git a/arch/powerpc/boot/dts/mpc8323emds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index fa7ef24d205..06b310698a0 100644
--- a/arch/powerpc/boot/dts/mpc8323emds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -11,16 +11,14 @@
/ {
model = "MPC8323EMDS";
- compatible = "MPC83xx";
+ compatible = "MPC8323EMDS", "MPC832xMDS", "MPC83xxMDS";
#address-cells = <1>;
#size-cells = <1>;
- linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <200>;
PowerPC,8323@0 {
device_type = "cpu";
@@ -33,14 +31,11 @@
bus-frequency = <0>;
clock-frequency = <0>;
32-bit;
- linux,phandle = <201>;
- linux,boot-cpu;
};
};
memory {
device_type = "memory";
- linux,phandle = <300>;
reg = <00000000 08000000>;
};
@@ -69,7 +64,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <e 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
dfsrr;
};
@@ -79,7 +74,7 @@
reg = <4500 100>;
clock-frequency = <0>;
interrupts = <9 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
serial@4600 {
@@ -88,7 +83,7 @@
reg = <4600 100>;
clock-frequency = <0>;
interrupts = <a 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
crypto@30000 {
@@ -97,7 +92,7 @@
compatible = "talitos";
reg = <30000 7000>;
interrupts = <b 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
/* Rev. 2.2 */
num-channels = <1>;
channel-fifo-len = <18>;
@@ -106,51 +101,50 @@
};
pci@8500 {
- linux,phandle = <8500>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x11 AD17 */
- 8800 0 0 1 700 14 8
- 8800 0 0 2 700 15 8
- 8800 0 0 3 700 16 8
- 8800 0 0 4 700 17 8
+ 8800 0 0 1 &ipic 14 8
+ 8800 0 0 2 &ipic 15 8
+ 8800 0 0 3 &ipic 16 8
+ 8800 0 0 4 &ipic 17 8
/* IDSEL 0x12 AD18 */
- 9000 0 0 1 700 16 8
- 9000 0 0 2 700 17 8
- 9000 0 0 3 700 14 8
- 9000 0 0 4 700 15 8
+ 9000 0 0 1 &ipic 16 8
+ 9000 0 0 2 &ipic 17 8
+ 9000 0 0 3 &ipic 14 8
+ 9000 0 0 4 &ipic 15 8
/* IDSEL 0x13 AD19 */
- 9800 0 0 1 700 17 8
- 9800 0 0 2 700 14 8
- 9800 0 0 3 700 15 8
- 9800 0 0 4 700 16 8
+ 9800 0 0 1 &ipic 17 8
+ 9800 0 0 2 &ipic 14 8
+ 9800 0 0 3 &ipic 15 8
+ 9800 0 0 4 &ipic 16 8
/* IDSEL 0x15 AD21*/
- a800 0 0 1 700 14 8
- a800 0 0 2 700 15 8
- a800 0 0 3 700 16 8
- a800 0 0 4 700 17 8
+ a800 0 0 1 &ipic 14 8
+ a800 0 0 2 &ipic 15 8
+ a800 0 0 3 &ipic 16 8
+ a800 0 0 4 &ipic 17 8
/* IDSEL 0x16 AD22*/
- b000 0 0 1 700 17 8
- b000 0 0 2 700 14 8
- b000 0 0 3 700 15 8
- b000 0 0 4 700 16 8
+ b000 0 0 1 &ipic 17 8
+ b000 0 0 2 &ipic 14 8
+ b000 0 0 3 &ipic 15 8
+ b000 0 0 4 &ipic 16 8
/* IDSEL 0x17 AD23*/
- b800 0 0 1 700 16 8
- b800 0 0 2 700 17 8
- b800 0 0 3 700 14 8
- b800 0 0 4 700 15 8
+ b800 0 0 1 &ipic 16 8
+ b800 0 0 2 &ipic 17 8
+ b800 0 0 3 &ipic 14 8
+ b800 0 0 4 &ipic 15 8
/* IDSEL 0x18 AD24*/
- c000 0 0 1 700 15 8
- c000 0 0 2 700 16 8
- c000 0 0 3 700 17 8
- c000 0 0 4 700 14 8>;
- interrupt-parent = <700>;
+ c000 0 0 1 &ipic 15 8
+ c000 0 0 2 &ipic 16 8
+ c000 0 0 3 &ipic 17 8
+ c000 0 0 4 &ipic 14 8>;
+ interrupt-parent = < &ipic >;
interrupts = <42 8>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 90000000 0 10000000
@@ -165,8 +159,7 @@
device_type = "pci";
};
- pic@700 {
- linux,phandle = <700>;
+ ipic: pic@700 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
@@ -180,8 +173,7 @@
device_type = "par_io";
num-ports = <7>;
- ucc_pin@03 {
- linux,phandle = <140003>;
+ pio3: ucc_pin@03 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
3 4 3 0 2 0 /* MDIO */
@@ -204,8 +196,7 @@
1 c 1 0 1 0 /* TX_EN */
1 d 2 0 1 0>;/* CRS */
};
- ucc_pin@04 {
- linux,phandle = <140004>;
+ pio4: ucc_pin@04 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
3 1f 2 0 1 0 /* RX_CLK (CLK7) */
@@ -252,7 +243,7 @@
compatible = "fsl_spi";
reg = <4c0 40>;
interrupts = <2>;
- interrupt-parent = <80>;
+ interrupt-parent = < &qeic >;
mode = "cpu";
};
@@ -261,7 +252,7 @@
compatible = "fsl_spi";
reg = <500 40>;
interrupts = <1>;
- interrupt-parent = <80>;
+ interrupt-parent = < &qeic >;
mode = "cpu";
};
@@ -270,7 +261,7 @@
compatible = "qe_udc";
reg = <6c0 40 8B00 100>;
interrupts = <b>;
- interrupt-parent = <80>;
+ interrupt-parent = < &qeic >;
mode = "slave";
};
@@ -281,12 +272,12 @@
device-id = <3>;
reg = <2200 200>;
interrupts = <22>;
- interrupt-parent = <80>;
+ interrupt-parent = < &qeic >;
mac-address = [ 00 04 9f 00 23 23 ];
rx-clock = <19>;
tx-clock = <1a>;
- phy-handle = <212003>;
- pio-handle = <140003>;
+ phy-handle = < &phy3 >;
+ pio-handle = < &pio3 >;
};
ucc@3200 {
@@ -296,12 +287,12 @@
device-id = <4>;
reg = <3000 200>;
interrupts = <23>;
- interrupt-parent = <80>;
+ interrupt-parent = < &qeic >;
mac-address = [ 00 11 22 33 44 55 ];
rx-clock = <17>;
tx-clock = <18>;
- phy-handle = <212004>;
- pio-handle = <140004>;
+ phy-handle = < &phy4 >;
+ pio-handle = < &pio4 >;
};
mdio@2320 {
@@ -311,26 +302,23 @@
device_type = "mdio";
compatible = "ucc_geth_phy";
- ethernet-phy@03 {
- linux,phandle = <212003>;
- interrupt-parent = <700>;
- interrupts = <11 2>;
+ phy3: ethernet-phy@03 {
+ interrupt-parent = < &ipic >;
+ interrupts = <11 8>;
reg = <3>;
device_type = "ethernet-phy";
interface = <3>; //ENET_100_MII
};
- ethernet-phy@04 {
- linux,phandle = <212004>;
- interrupt-parent = <700>;
- interrupts = <12 2>;
+ phy4: ethernet-phy@04 {
+ interrupt-parent = < &ipic >;
+ interrupts = <12 8>;
reg = <4>;
device_type = "ethernet-phy";
interface = <3>;
};
};
- qeic@80 {
- linux,phandle = <80>;
+ qeic: qeic@80 {
interrupt-controller;
device_type = "qeic";
#address-cells = <0>;
@@ -339,7 +327,7 @@
built-in;
big-endian;
interrupts = <20 8 21 8>; //high:32 low:33
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
};
};
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 27807fc4588..61b550bf164 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -10,7 +10,7 @@
*/
/ {
model = "MPC8349EMITX";
- compatible = "MPC834xMITX";
+ compatible = "MPC8349EMITX", "MPC834xMITX", "MPC83xxMITX";
#address-cells = <1>;
#size-cells = <1>;
@@ -58,7 +58,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <e 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
dfsrr;
};
@@ -67,7 +67,7 @@
compatible = "fsl-i2c";
reg = <3100 100>;
interrupts = <f 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
dfsrr;
};
@@ -76,7 +76,7 @@
compatible = "mpc83xx_spi";
reg = <7000 1000>;
interrupts = <10 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
mode = <0>;
};
@@ -86,8 +86,8 @@
reg = <22000 1000>;
#address-cells = <1>;
#size-cells = <0>;
- interrupt-parent = <700>;
- interrupts = <27 2>;
+ interrupt-parent = < &ipic >;
+ interrupts = <27 8>;
phy_type = "ulpi";
port1;
};
@@ -98,8 +98,8 @@
reg = <23000 1000>;
#address-cells = <1>;
#size-cells = <0>;
- interrupt-parent = <700>;
- interrupts = <26 2>;
+ interrupt-parent = < &ipic >;
+ interrupts = <26 8>;
phy_type = "ulpi";
};
@@ -109,22 +109,19 @@
reg = <24520 20>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <24520>;
/* Vitesse 8201 */
- ethernet-phy@1c {
- linux,phandle = <245201c>;
- interrupt-parent = <700>;
- interrupts = <12 2>;
+ phy1c: ethernet-phy@1c {
+ interrupt-parent = < &ipic >;
+ interrupts = <12 8>;
reg = <1c>;
device_type = "ethernet-phy";
};
/* Vitesse 7385 */
- ethernet-phy@1f {
- linux,phandle = <245201f>;
- interrupt-parent = <700>;
- interrupts = <12 2>;
+ phy1f: ethernet-phy@1f {
+ interrupt-parent = < &ipic >;
+ interrupts = <12 8>;
reg = <1f>;
device_type = "ethernet-phy";
};
@@ -138,8 +135,8 @@
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <20 8 21 8 22 8>;
- interrupt-parent = <700>;
- phy-handle = <245201c>;
+ interrupt-parent = < &ipic >;
+ phy-handle = < &phy1c >;
};
ethernet@25000 {
@@ -152,8 +149,8 @@
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 8 24 8 25 8>;
- interrupt-parent = <700>;
- phy-handle = <245201f>;
+ interrupt-parent = < &ipic >;
+ phy-handle = < &phy1f >;
};
serial@4500 {
@@ -162,7 +159,7 @@
reg = <4500 100>;
clock-frequency = <0>; // from bootloader
interrupts = <9 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
serial@4600 {
@@ -171,16 +168,16 @@
reg = <4600 100>;
clock-frequency = <0>; // from bootloader
interrupts = <a 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
pci@8500 {
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x10 - SATA */
- 8000 0 0 1 700 16 8 /* SATA_INTA */
+ 8000 0 0 1 &ipic 16 8 /* SATA_INTA */
>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
interrupts = <42 8>;
bus-range = <0 0>;
ranges = <42000000 0 80000000 80000000 0 10000000
@@ -199,13 +196,13 @@
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x0E - MiniPCI Slot */
- 7000 0 0 1 700 15 8 /* PCI_INTA */
+ 7000 0 0 1 &ipic 15 8 /* PCI_INTA */
/* IDSEL 0x0F - PCI Slot */
- 7800 0 0 1 700 14 8 /* PCI_INTA */
- 7800 0 0 2 700 15 8 /* PCI_INTB */
+ 7800 0 0 1 &ipic 14 8 /* PCI_INTA */
+ 7800 0 0 2 &ipic 15 8 /* PCI_INTB */
>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
interrupts = <43 8>;
bus-range = <1 1>;
ranges = <42000000 0 a0000000 a0000000 0 10000000
@@ -226,15 +223,14 @@
compatible = "talitos";
reg = <30000 10000>;
interrupts = <b 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
num-channels = <4>;
channel-fifo-len = <18>;
exec-units-mask = <0000007e>;
descriptor-types-mask = <01010ebf>;
};
- pic@700 {
- linux,phandle = <700>;
+ ipic: pic@700 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
diff --git a/arch/powerpc/boot/dts/mpc8349emitxgp.dts b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
index 3190774de1d..b2e1a5ec377 100644
--- a/arch/powerpc/boot/dts/mpc8349emitxgp.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
@@ -10,7 +10,7 @@
*/
/ {
model = "MPC8349EMITXGP";
- compatible = "MPC834xMITXGP";
+ compatible = "MPC8349EMITXGP", "MPC834xMITX", "MPC83xxMITX";
#address-cells = <1>;
#size-cells = <1>;
@@ -58,7 +58,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <e 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
dfsrr;
};
@@ -67,7 +67,7 @@
compatible = "fsl-i2c";
reg = <3100 100>;
interrupts = <f 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
dfsrr;
};
@@ -76,7 +76,7 @@
compatible = "mpc83xx_spi";
reg = <7000 1000>;
interrupts = <10 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
mode = <0>;
};
@@ -86,8 +86,8 @@
reg = <23000 1000>;
#address-cells = <1>;
#size-cells = <0>;
- interrupt-parent = <700>;
- interrupts = <26 2>;
+ interrupt-parent = < &ipic >;
+ interrupts = <26 8>;
dr_mode = "otg";
phy_type = "ulpi";
};
@@ -98,13 +98,11 @@
reg = <24520 20>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <24520>;
/* Vitesse 8201 */
- ethernet-phy@1c {
- linux,phandle = <245201c>;
- interrupt-parent = <700>;
- interrupts = <12 2>;
+ phy1c: ethernet-phy@1c {
+ interrupt-parent = < &ipic >;
+ interrupts = <12 8>;
reg = <1c>;
device_type = "ethernet-phy";
};
@@ -117,8 +115,8 @@
reg = <24000 1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <20 8 21 8 22 8>;
- interrupt-parent = <700>;
- phy-handle = <245201c>;
+ interrupt-parent = < &ipic >;
+ phy-handle = < &phy1c >;
};
serial@4500 {
@@ -127,7 +125,7 @@
reg = <4500 100>;
clock-frequency = <0>; // from bootloader
interrupts = <9 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
serial@4600 {
@@ -136,17 +134,17 @@
reg = <4600 100>;
clock-frequency = <0>; // from bootloader
interrupts = <a 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
pci@8600 {
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x0F - PCI Slot */
- 7800 0 0 1 700 14 8 /* PCI_INTA */
- 7800 0 0 2 700 15 8 /* PCI_INTB */
+ 7800 0 0 1 &ipic 14 8 /* PCI_INTA */
+ 7800 0 0 2 &ipic 15 8 /* PCI_INTB */
>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
interrupts = <43 8>;
bus-range = <1 1>;
ranges = <42000000 0 a0000000 a0000000 0 10000000
@@ -167,15 +165,14 @@
compatible = "talitos";
reg = <30000 10000>;
interrupts = <b 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
num-channels = <4>;
channel-fifo-len = <18>;
exec-units-mask = <0000007e>;
descriptor-types-mask = <01010ebf>;
};
- pic@700 {
- linux,phandle = <700>;
+ ipic: pic@700 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts
index dc121b3cb4a..e4b43c24bc0 100644
--- a/arch/powerpc/boot/dts/mpc834x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
@@ -11,7 +11,7 @@
/ {
model = "MPC8349EMDS";
- compatible = "MPC834xMDS";
+ compatible = "MPC8349EMDS", "MPC834xMDS", "MPC83xxMDS";
#address-cells = <1>;
#size-cells = <1>;
@@ -64,7 +64,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <e 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
dfsrr;
};
@@ -73,7 +73,7 @@
compatible = "fsl-i2c";
reg = <3100 100>;
interrupts = <f 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
dfsrr;
};
@@ -82,7 +82,7 @@
compatible = "mpc83xx_spi";
reg = <7000 1000>;
interrupts = <10 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
mode = <0>;
};
@@ -94,8 +94,8 @@
reg = <22000 1000>;
#address-cells = <1>;
#size-cells = <0>;
- interrupt-parent = <700>;
- interrupts = <27 2>;
+ interrupt-parent = < &ipic >;
+ interrupts = <27 8>;
phy_type = "ulpi";
port1;
};
@@ -106,8 +106,8 @@
reg = <23000 1000>;
#address-cells = <1>;
#size-cells = <0>;
- interrupt-parent = <700>;
- interrupts = <26 2>;
+ interrupt-parent = < &ipic >;
+ interrupts = <26 8>;
dr_mode = "otg";
phy_type = "ulpi";
};
@@ -118,18 +118,15 @@
reg = <24520 20>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <24520>;
- ethernet-phy@0 {
- linux,phandle = <2452000>;
- interrupt-parent = <700>;
- interrupts = <11 2>;
+ phy0: ethernet-phy@0 {
+ interrupt-parent = < &ipic >;
+ interrupts = <11 8>;
reg = <0>;
device_type = "ethernet-phy";
};
- ethernet-phy@1 {
- linux,phandle = <2452001>;
- interrupt-parent = <700>;
- interrupts = <12 2>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = < &ipic >;
+ interrupts = <12 8>;
reg = <1>;
device_type = "ethernet-phy";
};
@@ -143,8 +140,8 @@
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <20 8 21 8 22 8>;
- interrupt-parent = <700>;
- phy-handle = <2452000>;
+ interrupt-parent = < &ipic >;
+ phy-handle = < &phy0 >;
};
ethernet@25000 {
@@ -157,8 +154,8 @@
address = [ 00 00 00 00 00 00 ];
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <23 8 24 8 25 8>;
- interrupt-parent = <700>;
- phy-handle = <2452001>;
+ interrupt-parent = < &ipic >;
+ phy-handle = < &phy1 >;
};
serial@4500 {
@@ -167,7 +164,7 @@
reg = <4500 100>;
clock-frequency = <0>;
interrupts = <9 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
serial@4600 {
@@ -176,7 +173,7 @@
reg = <4600 100>;
clock-frequency = <0>;
interrupts = <a 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
pci@8500 {
@@ -184,47 +181,47 @@
interrupt-map = <
/* IDSEL 0x11 */
- 8800 0 0 1 700 14 8
- 8800 0 0 2 700 15 8
- 8800 0 0 3 700 16 8
- 8800 0 0 4 700 17 8
+ 8800 0 0 1 &ipic 14 8
+ 8800 0 0 2 &ipic 15 8
+ 8800 0 0 3 &ipic 16 8
+ 8800 0 0 4 &ipic 17 8
/* IDSEL 0x12 */
- 9000 0 0 1 700 16 8
- 9000 0 0 2 700 17 8
- 9000 0 0 3 700 14 8
- 9000 0 0 4 700 15 8
+ 9000 0 0 1 &ipic 16 8
+ 9000 0 0 2 &ipic 17 8
+ 9000 0 0 3 &ipic 14 8
+ 9000 0 0 4 &ipic 15 8
/* IDSEL 0x13 */
- 9800 0 0 1 700 17 8
- 9800 0 0 2 700 14 8
- 9800 0 0 3 700 15 8
- 9800 0 0 4 700 16 8
+ 9800 0 0 1 &ipic 17 8
+ 9800 0 0 2 &ipic 14 8
+ 9800 0 0 3 &ipic 15 8
+ 9800 0 0 4 &ipic 16 8
/* IDSEL 0x15 */
- a800 0 0 1 700 14 8
- a800 0 0 2 700 15 8
- a800 0 0 3 700 16 8
- a800 0 0 4 700 17 8
+ a800 0 0 1 &ipic 14 8
+ a800 0 0 2 &ipic 15 8
+ a800 0 0 3 &ipic 16 8
+ a800 0 0 4 &ipic 17 8
/* IDSEL 0x16 */
- b000 0 0 1 700 17 8
- b000 0 0 2 700 14 8
- b000 0 0 3 700 15 8
- b000 0 0 4 700 16 8
+ b000 0 0 1 &ipic 17 8
+ b000 0 0 2 &ipic 14 8
+ b000 0 0 3 &ipic 15 8
+ b000 0 0 4 &ipic 16 8
/* IDSEL 0x17 */
- b800 0 0 1 700 16 8
- b800 0 0 2 700 17 8
- b800 0 0 3 700 14 8
- b800 0 0 4 700 15 8
+ b800 0 0 1 &ipic 16 8
+ b800 0 0 2 &ipic 17 8
+ b800 0 0 3 &ipic 14 8
+ b800 0 0 4 &ipic 15 8
/* IDSEL 0x18 */
- c000 0 0 1 700 15 8
- c000 0 0 2 700 16 8
- c000 0 0 3 700 17 8
- c000 0 0 4 700 14 8>;
- interrupt-parent = <700>;
+ c000 0 0 1 &ipic 15 8
+ c000 0 0 2 &ipic 16 8
+ c000 0 0 3 &ipic 17 8
+ c000 0 0 4 &ipic 14 8>;
+ interrupt-parent = < &ipic >;
interrupts = <42 8>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 a0000000 0 10000000
@@ -244,47 +241,47 @@
interrupt-map = <
/* IDSEL 0x11 */
- 8800 0 0 1 700 14 8
- 8800 0 0 2 700 15 8
- 8800 0 0 3 700 16 8
- 8800 0 0 4 700 17 8
+ 8800 0 0 1 &ipic 14 8
+ 8800 0 0 2 &ipic 15 8
+ 8800 0 0 3 &ipic 16 8
+ 8800 0 0 4 &ipic 17 8
/* IDSEL 0x12 */
- 9000 0 0 1 700 16 8
- 9000 0 0 2 700 17 8
- 9000 0 0 3 700 14 8
- 9000 0 0 4 700 15 8
+ 9000 0 0 1 &ipic 16 8
+ 9000 0 0 2 &ipic 17 8
+ 9000 0 0 3 &ipic 14 8
+ 9000 0 0 4 &ipic 15 8
/* IDSEL 0x13 */
- 9800 0 0 1 700 17 8
- 9800 0 0 2 700 14 8
- 9800 0 0 3 700 15 8
- 9800 0 0 4 700 16 8
+ 9800 0 0 1 &ipic 17 8
+ 9800 0 0 2 &ipic 14 8
+ 9800 0 0 3 &ipic 15 8
+ 9800 0 0 4 &ipic 16 8
/* IDSEL 0x15 */
- a800 0 0 1 700 14 8
- a800 0 0 2 700 15 8
- a800 0 0 3 700 16 8
- a800 0 0 4 700 17 8
+ a800 0 0 1 &ipic 14 8
+ a800 0 0 2 &ipic 15 8
+ a800 0 0 3 &ipic 16 8
+ a800 0 0 4 &ipic 17 8
/* IDSEL 0x16 */
- b000 0 0 1 700 17 8
- b000 0 0 2 700 14 8
- b000 0 0 3 700 15 8
- b000 0 0 4 700 16 8
+ b000 0 0 1 &ipic 17 8
+ b000 0 0 2 &ipic 14 8
+ b000 0 0 3 &ipic 15 8
+ b000 0 0 4 &ipic 16 8
/* IDSEL 0x17 */
- b800 0 0 1 700 16 8
- b800 0 0 2 700 17 8
- b800 0 0 3 700 14 8
- b800 0 0 4 700 15 8
+ b800 0 0 1 &ipic 16 8
+ b800 0 0 2 &ipic 17 8
+ b800 0 0 3 &ipic 14 8
+ b800 0 0 4 &ipic 15 8
/* IDSEL 0x18 */
- c000 0 0 1 700 15 8
- c000 0 0 2 700 16 8
- c000 0 0 3 700 17 8
- c000 0 0 4 700 14 8>;
- interrupt-parent = <700>;
+ c000 0 0 1 &ipic 15 8
+ c000 0 0 2 &ipic 16 8
+ c000 0 0 3 &ipic 17 8
+ c000 0 0 4 &ipic 14 8>;
+ interrupt-parent = < &ipic >;
interrupts = <42 8>;
bus-range = <0 0>;
ranges = <02000000 0 b0000000 b0000000 0 10000000
@@ -306,7 +303,7 @@
compatible = "talitos";
reg = <30000 10000>;
interrupts = <b 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
num-channels = <4>;
channel-fifo-len = <18>;
exec-units-mask = <0000007e>;
@@ -321,8 +318,7 @@
* sense == 8: Level, low assertion
* sense == 2: Edge, high-to-low change
*/
- pic@700 {
- linux,phandle = <700>;
+ ipic: pic@700 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
diff --git a/arch/powerpc/boot/dts/mpc8360emds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index 9022192155b..4fe45c02184 100644
--- a/arch/powerpc/boot/dts/mpc8360emds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -15,17 +15,15 @@
*/
/ {
- model = "MPC8360EPB";
- compatible = "MPC83xx";
+ model = "MPC8360MDS";
+ compatible = "MPC8360EMDS", "MPC836xMDS", "MPC83xxMDS";
#address-cells = <1>;
#size-cells = <1>;
- linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <200>;
PowerPC,8360@0 {
device_type = "cpu";
@@ -38,14 +36,11 @@
bus-frequency = <FBC5200>;
clock-frequency = <1F78A400>;
32-bit;
- linux,phandle = <201>;
- linux,boot-cpu;
};
};
memory {
device_type = "memory";
- linux,phandle = <300>;
reg = <00000000 10000000>;
};
@@ -74,7 +69,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <e 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
dfsrr;
};
@@ -83,7 +78,7 @@
compatible = "fsl-i2c";
reg = <3100 100>;
interrupts = <f 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
dfsrr;
};
@@ -93,7 +88,7 @@
reg = <4500 100>;
clock-frequency = <FBC5200>;
interrupts = <9 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
serial@4600 {
@@ -102,7 +97,7 @@
reg = <4600 100>;
clock-frequency = <FBC5200>;
interrupts = <a 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
crypto@30000 {
@@ -111,7 +106,7 @@
compatible = "talitos";
reg = <30000 10000>;
interrupts = <b 8>;
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
num-channels = <4>;
channel-fifo-len = <18>;
exec-units-mask = <0000007e>;
@@ -120,52 +115,51 @@
};
pci@8500 {
- linux,phandle = <8500>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x11 AD17 */
- 8800 0 0 1 700 14 8
- 8800 0 0 2 700 15 8
- 8800 0 0 3 700 16 8
- 8800 0 0 4 700 17 8
+ 8800 0 0 1 &ipic 14 8
+ 8800 0 0 2 &ipic 15 8
+ 8800 0 0 3 &ipic 16 8
+ 8800 0 0 4 &ipic 17 8
/* IDSEL 0x12 AD18 */
- 9000 0 0 1 700 16 8
- 9000 0 0 2 700 17 8
- 9000 0 0 3 700 14 8
- 9000 0 0 4 700 15 8
+ 9000 0 0 1 &ipic 16 8
+ 9000 0 0 2 &ipic 17 8
+ 9000 0 0 3 &ipic 14 8
+ 9000 0 0 4 &ipic 15 8
/* IDSEL 0x13 AD19 */
- 9800 0 0 1 700 17 8
- 9800 0 0 2 700 14 8
- 9800 0 0 3 700 15 8
- 9800 0 0 4 700 16 8
+ 9800 0 0 1 &ipic 17 8
+ 9800 0 0 2 &ipic 14 8
+ 9800 0 0 3 &ipic 15 8
+ 9800 0 0 4 &ipic 16 8
/* IDSEL 0x15 AD21*/
- a800 0 0 1 700 14 8
- a800 0 0 2 700 15 8
- a800 0 0 3 700 16 8
- a800 0 0 4 700 17 8
+ a800 0 0 1 &ipic 14 8
+ a800 0 0 2 &ipic 15 8
+ a800 0 0 3 &ipic 16 8
+ a800 0 0 4 &ipic 17 8
/* IDSEL 0x16 AD22*/
- b000 0 0 1 700 17 8
- b000 0 0 2 700 14 8
- b000 0 0 3 700 15 8
- b000 0 0 4 700 16 8
+ b000 0 0 1 &ipic 17 8
+ b000 0 0 2 &ipic 14 8
+ b000 0 0 3 &ipic 15 8
+ b000 0 0 4 &ipic 16 8
/* IDSEL 0x17 AD23*/
- b800 0 0 1 700 16 8
- b800 0 0 2 700 17 8
- b800 0 0 3 700 14 8
- b800 0 0 4 700 15 8
+ b800 0 0 1 &ipic 16 8
+ b800 0 0 2 &ipic 17 8
+ b800 0 0 3 &ipic 14 8
+ b800 0 0 4 &ipic 15 8
/* IDSEL 0x18 AD24*/
- c000 0 0 1 700 15 8
- c000 0 0 2 700 16 8
- c000 0 0 3 700 17 8
- c000 0 0 4 700 14 8>;
- interrupt-parent = <700>;
+ c000 0 0 1 &ipic 15 8
+ c000 0 0 2 &ipic 16 8
+ c000 0 0 3 &ipic 17 8
+ c000 0 0 4 &ipic 14 8>;
+ interrupt-parent = < &ipic >;
interrupts = <42 8>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 a0000000 0 10000000
@@ -180,8 +174,7 @@
device_type = "pci";
};
- pic@700 {
- linux,phandle = <700>;
+ ipic: pic@700 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
@@ -195,8 +188,7 @@
device_type = "par_io";
num-ports = <7>;
- ucc_pin@01 {
- linux,phandle = <140001>;
+ pio1: ucc_pin@01 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
0 3 1 0 1 0 /* TxD0 */
@@ -223,8 +215,7 @@
2 9 1 0 3 0 /* GTX_CLK - CLK10 */
2 8 2 0 1 0>; /* GTX125 - CLK9 */
};
- ucc_pin@02 {
- linux,phandle = <140002>;
+ pio2: ucc_pin@02 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
0 11 1 0 1 0 /* TxD0 */
@@ -281,7 +272,7 @@
compatible = "fsl_spi";
reg = <4c0 40>;
interrupts = <2>;
- interrupt-parent = <80>;
+ interrupt-parent = < &qeic >;
mode = "cpu";
};
@@ -290,7 +281,7 @@
compatible = "fsl_spi";
reg = <500 40>;
interrupts = <1>;
- interrupt-parent = <80>;
+ interrupt-parent = < &qeic >;
mode = "cpu";
};
@@ -299,7 +290,7 @@
compatible = "qe_udc";
reg = <6c0 40 8B00 100>;
interrupts = <b>;
- interrupt-parent = <80>;
+ interrupt-parent = < &qeic >;
mode = "slave";
};
@@ -310,12 +301,12 @@
device-id = <1>;
reg = <2000 200>;
interrupts = <20>;
- interrupt-parent = <80>;
+ interrupt-parent = < &qeic >;
mac-address = [ 00 04 9f 00 23 23 ];
rx-clock = <0>;
tx-clock = <19>;
- phy-handle = <212000>;
- pio-handle = <140001>;
+ phy-handle = < &phy0 >;
+ pio-handle = < &pio1 >;
};
ucc@3000 {
@@ -325,12 +316,12 @@
device-id = <2>;
reg = <3000 200>;
interrupts = <21>;
- interrupt-parent = <80>;
+ interrupt-parent = < &qeic >;
mac-address = [ 00 11 22 33 44 55 ];
rx-clock = <0>;
tx-clock = <14>;
- phy-handle = <212001>;
- pio-handle = <140002>;
+ phy-handle = < &phy1 >;
+ pio-handle = < &pio2 >;
};
mdio@2120 {
@@ -340,26 +331,23 @@
device_type = "mdio";
compatible = "ucc_geth_phy";
- ethernet-phy@00 {
- linux,phandle = <212000>;
- interrupt-parent = <700>;
- interrupts = <11 2>;
+ phy0: ethernet-phy@00 {
+ interrupt-parent = < &ipic >;
+ interrupts = <11 8>;
reg = <0>;
device_type = "ethernet-phy";
interface = <6>; //ENET_1000_GMII
};
- ethernet-phy@01 {
- linux,phandle = <212001>;
- interrupt-parent = <700>;
- interrupts = <12 2>;
+ phy1: ethernet-phy@01 {
+ interrupt-parent = < &ipic >;
+ interrupts = <12 8>;
reg = <1>;
device_type = "ethernet-phy";
interface = <6>;
};
};
- qeic@80 {
- linux,phandle = <80>;
+ qeic: qeic@80 {
interrupt-controller;
device_type = "qeic";
#address-cells = <0>;
@@ -368,7 +356,7 @@
built-in;
big-endian;
interrupts = <20 8 21 8>; //high:32 low:33
- interrupt-parent = <700>;
+ interrupt-parent = < &ipic >;
};
};
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
index 5f41c1f7a5f..3c0917fa791 100644
--- a/arch/powerpc/boot/dts/mpc8540ads.dts
+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
@@ -12,16 +12,14 @@
/ {
model = "MPC8540ADS";
- compatible = "MPC85xxADS";
+ compatible = "MPC8540ADS", "MPC85xxADS";
#address-cells = <1>;
#size-cells = <1>;
- linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <200>;
PowerPC,8540@0 {
device_type = "cpu";
@@ -34,13 +32,11 @@
bus-frequency = <0>; // 166 MHz
clock-frequency = <0>; // 825 MHz, from uboot
32-bit;
- linux,phandle = <201>;
};
};
memory {
device_type = "memory";
- linux,phandle = <300>;
reg = <00000000 08000000>; // 128M at 0x0
};
@@ -58,7 +54,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
dfsrr;
};
@@ -68,24 +64,20 @@
device_type = "mdio";
compatible = "gianfar";
reg = <24520 20>;
- linux,phandle = <24520>;
- ethernet-phy@0 {
- linux,phandle = <2452000>;
- interrupt-parent = <40000>;
+ phy0: ethernet-phy@0 {
+ interrupt-parent = <&mpic>;
interrupts = <35 1>;
reg = <0>;
device_type = "ethernet-phy";
};
- ethernet-phy@1 {
- linux,phandle = <2452001>;
- interrupt-parent = <40000>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&mpic>;
interrupts = <35 1>;
reg = <1>;
device_type = "ethernet-phy";
};
- ethernet-phy@3 {
- linux,phandle = <2452003>;
- interrupt-parent = <40000>;
+ phy3: ethernet-phy@3 {
+ interrupt-parent = <&mpic>;
interrupts = <37 1>;
reg = <3>;
device_type = "ethernet-phy";
@@ -102,8 +94,8 @@
address = [ 00 E0 0C 00 73 00 ];
local-mac-address = [ 00 E0 0C 00 73 00 ];
interrupts = <d 2 e 2 12 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452000>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
};
ethernet@25000 {
@@ -116,8 +108,8 @@
address = [ 00 E0 0C 00 73 01 ];
local-mac-address = [ 00 E0 0C 00 73 01 ];
interrupts = <13 2 14 2 18 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452001>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
};
ethernet@26000 {
@@ -130,8 +122,8 @@
address = [ 00 E0 0C 00 73 02 ];
local-mac-address = [ 00 E0 0C 00 73 02 ];
interrupts = <19 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452003>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy3>;
};
serial@4500 {
@@ -140,7 +132,7 @@
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
serial@4600 {
@@ -149,85 +141,84 @@
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
pci@8000 {
- linux,phandle = <8000>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x02 */
- 1000 0 0 1 40000 31 1
- 1000 0 0 2 40000 32 1
- 1000 0 0 3 40000 33 1
- 1000 0 0 4 40000 34 1
+ 1000 0 0 1 &mpic 31 1
+ 1000 0 0 2 &mpic 32 1
+ 1000 0 0 3 &mpic 33 1
+ 1000 0 0 4 &mpic 34 1
/* IDSEL 0x03 */
- 1800 0 0 1 40000 34 1
- 1800 0 0 2 40000 31 1
- 1800 0 0 3 40000 32 1
- 1800 0 0 4 40000 33 1
+ 1800 0 0 1 &mpic 34 1
+ 1800 0 0 2 &mpic 31 1
+ 1800 0 0 3 &mpic 32 1
+ 1800 0 0 4 &mpic 33 1
/* IDSEL 0x04 */
- 2000 0 0 1 40000 33 1
- 2000 0 0 2 40000 34 1
- 2000 0 0 3 40000 31 1
- 2000 0 0 4 40000 32 1
+ 2000 0 0 1 &mpic 33 1
+ 2000 0 0 2 &mpic 34 1
+ 2000 0 0 3 &mpic 31 1
+ 2000 0 0 4 &mpic 32 1
/* IDSEL 0x05 */
- 2800 0 0 1 40000 32 1
- 2800 0 0 2 40000 33 1
- 2800 0 0 3 40000 34 1
- 2800 0 0 4 40000 31 1
+ 2800 0 0 1 &mpic 32 1
+ 2800 0 0 2 &mpic 33 1
+ 2800 0 0 3 &mpic 34 1
+ 2800 0 0 4 &mpic 31 1
/* IDSEL 0x0c */
- 6000 0 0 1 40000 31 1
- 6000 0 0 2 40000 32 1
- 6000 0 0 3 40000 33 1
- 6000 0 0 4 40000 34 1
+ 6000 0 0 1 &mpic 31 1
+ 6000 0 0 2 &mpic 32 1
+ 6000 0 0 3 &mpic 33 1
+ 6000 0 0 4 &mpic 34 1
/* IDSEL 0x0d */
- 6800 0 0 1 40000 34 1
- 6800 0 0 2 40000 31 1
- 6800 0 0 3 40000 32 1
- 6800 0 0 4 40000 33 1
+ 6800 0 0 1 &mpic 34 1
+ 6800 0 0 2 &mpic 31 1
+ 6800 0 0 3 &mpic 32 1
+ 6800 0 0 4 &mpic 33 1
/* IDSEL 0x0e */
- 7000 0 0 1 40000 33 1
- 7000 0 0 2 40000 34 1
- 7000 0 0 3 40000 31 1
- 7000 0 0 4 40000 32 1
+ 7000 0 0 1 &mpic 33 1
+ 7000 0 0 2 &mpic 34 1
+ 7000 0 0 3 &mpic 31 1
+ 7000 0 0 4 &mpic 32 1
/* IDSEL 0x0f */
- 7800 0 0 1 40000 32 1
- 7800 0 0 2 40000 33 1
- 7800 0 0 3 40000 34 1
- 7800 0 0 4 40000 31 1
+ 7800 0 0 1 &mpic 32 1
+ 7800 0 0 2 &mpic 33 1
+ 7800 0 0 3 &mpic 34 1
+ 7800 0 0 4 &mpic 31 1
/* IDSEL 0x12 */
- 9000 0 0 1 40000 31 1
- 9000 0 0 2 40000 32 1
- 9000 0 0 3 40000 33 1
- 9000 0 0 4 40000 34 1
+ 9000 0 0 1 &mpic 31 1
+ 9000 0 0 2 &mpic 32 1
+ 9000 0 0 3 &mpic 33 1
+ 9000 0 0 4 &mpic 34 1
/* IDSEL 0x13 */
- 9800 0 0 1 40000 34 1
- 9800 0 0 2 40000 31 1
- 9800 0 0 3 40000 32 1
- 9800 0 0 4 40000 33 1
+ 9800 0 0 1 &mpic 34 1
+ 9800 0 0 2 &mpic 31 1
+ 9800 0 0 3 &mpic 32 1
+ 9800 0 0 4 &mpic 33 1
/* IDSEL 0x14 */
- a000 0 0 1 40000 33 1
- a000 0 0 2 40000 34 1
- a000 0 0 3 40000 31 1
- a000 0 0 4 40000 32 1
+ a000 0 0 1 &mpic 33 1
+ a000 0 0 2 &mpic 34 1
+ a000 0 0 3 &mpic 31 1
+ a000 0 0 4 &mpic 32 1
/* IDSEL 0x15 */
- a800 0 0 1 40000 32 1
- a800 0 0 2 40000 33 1
- a800 0 0 3 40000 34 1
- a800 0 0 4 40000 31 1>;
- interrupt-parent = <40000>;
+ a800 0 0 1 &mpic 32 1
+ a800 0 0 2 &mpic 33 1
+ a800 0 0 3 &mpic 34 1
+ a800 0 0 4 &mpic 31 1>;
+ interrupt-parent = <&mpic>;
interrupts = <08 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
@@ -241,8 +232,7 @@
device_type = "pci";
};
- pic@40000 {
- linux,phandle = <40000>;
+ mpic: pic@40000 {
clock-frequency = <0>;
interrupt-controller;
#address-cells = <0>;
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
index 7be0bc659e1..2a1ae760ab3 100644
--- a/arch/powerpc/boot/dts/mpc8541cds.dts
+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
@@ -12,16 +12,14 @@
/ {
model = "MPC8541CDS";
- compatible = "MPC85xxCDS";
+ compatible = "MPC8541CDS", "MPC85xxCDS";
#address-cells = <1>;
#size-cells = <1>;
- linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <200>;
PowerPC,8541@0 {
device_type = "cpu";
@@ -34,13 +32,11 @@
bus-frequency = <0>; // 166 MHz
clock-frequency = <0>; // 825 MHz, from uboot
32-bit;
- linux,phandle = <201>;
};
};
memory {
device_type = "memory";
- linux,phandle = <300>;
reg = <00000000 08000000>; // 128M at 0x0
};
@@ -58,7 +54,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
dfsrr;
};
@@ -68,17 +64,14 @@
device_type = "mdio";
compatible = "gianfar";
reg = <24520 20>;
- linux,phandle = <24520>;
- ethernet-phy@0 {
- linux,phandle = <2452000>;
- interrupt-parent = <40000>;
+ phy0: ethernet-phy@0 {
+ interrupt-parent = <&mpic>;
interrupts = <35 0>;
reg = <0>;
device_type = "ethernet-phy";
};
- ethernet-phy@1 {
- linux,phandle = <2452001>;
- interrupt-parent = <40000>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&mpic>;
interrupts = <35 0>;
reg = <1>;
device_type = "ethernet-phy";
@@ -94,8 +87,8 @@
reg = <24000 1000>;
local-mac-address = [ 00 E0 0C 00 73 00 ];
interrupts = <d 2 e 2 12 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452000>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
};
ethernet@25000 {
@@ -107,8 +100,8 @@
reg = <25000 1000>;
local-mac-address = [ 00 E0 0C 00 73 01 ];
interrupts = <13 2 14 2 18 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452001>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
};
serial@4500 {
@@ -117,7 +110,7 @@
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
serial@4600 {
@@ -126,57 +119,56 @@
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
- pci@8000 {
- linux,phandle = <8000>;
+ pci1: pci@8000 {
interrupt-map-mask = <1f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x10 */
- 08000 0 0 1 40000 30 1
- 08000 0 0 2 40000 31 1
- 08000 0 0 3 40000 32 1
- 08000 0 0 4 40000 33 1
+ 08000 0 0 1 &mpic 30 1
+ 08000 0 0 2 &mpic 31 1
+ 08000 0 0 3 &mpic 32 1
+ 08000 0 0 4 &mpic 33 1
/* IDSEL 0x11 */
- 08800 0 0 1 40000 30 1
- 08800 0 0 2 40000 31 1
- 08800 0 0 3 40000 32 1
- 08800 0 0 4 40000 33 1
+ 08800 0 0 1 &mpic 30 1
+ 08800 0 0 2 &mpic 31 1
+ 08800 0 0 3 &mpic 32 1
+ 08800 0 0 4 &mpic 33 1
/* IDSEL 0x12 (Slot 1) */
- 09000 0 0 1 40000 30 1
- 09000 0 0 2 40000 31 1
- 09000 0 0 3 40000 32 1
- 09000 0 0 4 40000 33 1
+ 09000 0 0 1 &mpic 30 1
+ 09000 0 0 2 &mpic 31 1
+ 09000 0 0 3 &mpic 32 1
+ 09000 0 0 4 &mpic 33 1
/* IDSEL 0x13 (Slot 2) */
- 09800 0 0 1 40000 31 1
- 09800 0 0 2 40000 32 1
- 09800 0 0 3 40000 33 1
- 09800 0 0 4 40000 30 1
+ 09800 0 0 1 &mpic 31 1
+ 09800 0 0 2 &mpic 32 1
+ 09800 0 0 3 &mpic 33 1
+ 09800 0 0 4 &mpic 30 1
/* IDSEL 0x14 (Slot 3) */
- 0a000 0 0 1 40000 32 1
- 0a000 0 0 2 40000 33 1
- 0a000 0 0 3 40000 30 1
- 0a000 0 0 4 40000 31 1
+ 0a000 0 0 1 &mpic 32 1
+ 0a000 0 0 2 &mpic 33 1
+ 0a000 0 0 3 &mpic 30 1
+ 0a000 0 0 4 &mpic 31 1
/* IDSEL 0x15 (Slot 4) */
- 0a800 0 0 1 40000 33 1
- 0a800 0 0 2 40000 30 1
- 0a800 0 0 3 40000 31 1
- 0a800 0 0 4 40000 32 1
+ 0a800 0 0 1 &mpic 33 1
+ 0a800 0 0 2 &mpic 30 1
+ 0a800 0 0 3 &mpic 31 1
+ 0a800 0 0 4 &mpic 32 1
/* Bus 1 (Tundra Bridge) */
/* IDSEL 0x12 (ISA bridge) */
- 19000 0 0 1 40000 30 1
- 19000 0 0 2 40000 31 1
- 19000 0 0 3 40000 32 1
- 19000 0 0 4 40000 33 1>;
- interrupt-parent = <40000>;
+ 19000 0 0 1 &mpic 30 1
+ 19000 0 0 2 &mpic 31 1
+ 19000 0 0 3 &mpic 32 1
+ 19000 0 0 4 &mpic 33 1>;
+ interrupt-parent = <&mpic>;
interrupts = <08 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
@@ -200,21 +192,20 @@
compatible = "chrp,iic";
big-endian;
interrupts = <1>;
- interrupt-parent = <8000>;
+ interrupt-parent = <&pci1>;
};
};
pci@9000 {
- linux,phandle = <9000>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x15 */
- a800 0 0 1 40000 3b 1
- a800 0 0 2 40000 3b 1
- a800 0 0 3 40000 3b 1
- a800 0 0 4 40000 3b 1>;
- interrupt-parent = <40000>;
+ a800 0 0 1 &mpic 3b 1
+ a800 0 0 2 &mpic 3b 1
+ a800 0 0 3 &mpic 3b 1
+ a800 0 0 4 &mpic 3b 1>;
+ interrupt-parent = <&mpic>;
interrupts = <09 2>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 a0000000 0 20000000
@@ -228,8 +219,7 @@
device_type = "pci";
};
- pic@40000 {
- linux,phandle = <40000>;
+ mpic: pic@40000 {
clock-frequency = <0>;
interrupt-controller;
#address-cells = <0>;
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
index 893d7957c17..7eb5d81d5ee 100644
--- a/arch/powerpc/boot/dts/mpc8548cds.dts
+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
@@ -12,16 +12,14 @@
/ {
model = "MPC8548CDS";
- compatible = "MPC85xxCDS";
+ compatible = "MPC8548CDS", "MPC85xxCDS";
#address-cells = <1>;
#size-cells = <1>;
- linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <200>;
PowerPC,8548@0 {
device_type = "cpu";
@@ -34,13 +32,11 @@
bus-frequency = <0>; // 166 MHz
clock-frequency = <0>; // 825 MHz, from uboot
32-bit;
- linux,phandle = <201>;
};
};
memory {
device_type = "memory";
- linux,phandle = <300>;
reg = <00000000 08000000>; // 128M at 0x0
};
@@ -58,7 +54,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
dfsrr;
};
@@ -68,32 +64,26 @@
device_type = "mdio";
compatible = "gianfar";
reg = <24520 20>;
- linux,phandle = <24520>;
- ethernet-phy@0 {
- linux,phandle = <2452000>;
- interrupt-parent = <40000>;
+ phy0: ethernet-phy@0 {
+ interrupt-parent = <&mpic>;
interrupts = <35 0>;
reg = <0>;
device_type = "ethernet-phy";
};
- ethernet-phy@1 {
- linux,phandle = <2452001>;
- interrupt-parent = <40000>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&mpic>;
interrupts = <35 0>;
reg = <1>;
device_type = "ethernet-phy";
};
-
- ethernet-phy@2 {
- linux,phandle = <2452002>;
- interrupt-parent = <40000>;
+ phy2: ethernet-phy@2 {
+ interrupt-parent = <&mpic>;
interrupts = <35 0>;
reg = <2>;
device_type = "ethernet-phy";
};
- ethernet-phy@3 {
- linux,phandle = <2452003>;
- interrupt-parent = <40000>;
+ phy3: ethernet-phy@3 {
+ interrupt-parent = <&mpic>;
interrupts = <35 0>;
reg = <3>;
device_type = "ethernet-phy";
@@ -109,8 +99,8 @@
reg = <24000 1000>;
local-mac-address = [ 00 E0 0C 00 73 00 ];
interrupts = <d 2 e 2 12 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452000>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
};
ethernet@25000 {
@@ -122,10 +112,11 @@
reg = <25000 1000>;
local-mac-address = [ 00 E0 0C 00 73 01 ];
interrupts = <13 2 14 2 18 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452001>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
};
+/* eTSEC 3/4 are currently broken
ethernet@26000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -135,11 +126,10 @@
reg = <26000 1000>;
local-mac-address = [ 00 E0 0C 00 73 02 ];
interrupts = <f 2 10 2 11 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452001>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy2>;
};
-/* eTSEC 4 is currently broken
ethernet@27000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -149,8 +139,8 @@
reg = <27000 1000>;
local-mac-address = [ 00 E0 0C 00 73 03 ];
interrupts = <15 2 16 2 17 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452001>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy3>;
};
*/
@@ -160,7 +150,7 @@
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
serial@4600 {
@@ -169,57 +159,56 @@
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
- pci@8000 {
- linux,phandle = <8000>;
+ pci1: pci@8000 {
interrupt-map-mask = <1f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x10 */
- 08000 0 0 1 40000 30 1
- 08000 0 0 2 40000 31 1
- 08000 0 0 3 40000 32 1
- 08000 0 0 4 40000 33 1
+ 08000 0 0 1 &mpic 30 1
+ 08000 0 0 2 &mpic 31 1
+ 08000 0 0 3 &mpic 32 1
+ 08000 0 0 4 &mpic 33 1
/* IDSEL 0x11 */
- 08800 0 0 1 40000 30 1
- 08800 0 0 2 40000 31 1
- 08800 0 0 3 40000 32 1
- 08800 0 0 4 40000 33 1
+ 08800 0 0 1 &mpic 30 1
+ 08800 0 0 2 &mpic 31 1
+ 08800 0 0 3 &mpic 32 1
+ 08800 0 0 4 &mpic 33 1
/* IDSEL 0x12 (Slot 1) */
- 09000 0 0 1 40000 30 1
- 09000 0 0 2 40000 31 1
- 09000 0 0 3 40000 32 1
- 09000 0 0 4 40000 33 1
+ 09000 0 0 1 &mpic 30 1
+ 09000 0 0 2 &mpic 31 1
+ 09000 0 0 3 &mpic 32 1
+ 09000 0 0 4 &mpic 33 1
/* IDSEL 0x13 (Slot 2) */
- 09800 0 0 1 40000 31 1
- 09800 0 0 2 40000 32 1
- 09800 0 0 3 40000 33 1
- 09800 0 0 4 40000 30 1
+ 09800 0 0 1 &mpic 31 1
+ 09800 0 0 2 &mpic 32 1
+ 09800 0 0 3 &mpic 33 1
+ 09800 0 0 4 &mpic 30 1
/* IDSEL 0x14 (Slot 3) */
- 0a000 0 0 1 40000 32 1
- 0a000 0 0 2 40000 33 1
- 0a000 0 0 3 40000 30 1
- 0a000 0 0 4 40000 31 1
+ 0a000 0 0 1 &mpic 32 1
+ 0a000 0 0 2 &mpic 33 1
+ 0a000 0 0 3 &mpic 30 1
+ 0a000 0 0 4 &mpic 31 1
/* IDSEL 0x15 (Slot 4) */
- 0a800 0 0 1 40000 33 1
- 0a800 0 0 2 40000 30 1
- 0a800 0 0 3 40000 31 1
- 0a800 0 0 4 40000 32 1
+ 0a800 0 0 1 &mpic 33 1
+ 0a800 0 0 2 &mpic 30 1
+ 0a800 0 0 3 &mpic 31 1
+ 0a800 0 0 4 &mpic 32 1
/* Bus 1 (Tundra Bridge) */
/* IDSEL 0x12 (ISA bridge) */
- 19000 0 0 1 40000 30 1
- 19000 0 0 2 40000 31 1
- 19000 0 0 3 40000 32 1
- 19000 0 0 4 40000 33 1>;
- interrupt-parent = <40000>;
+ 19000 0 0 1 &mpic 30 1
+ 19000 0 0 2 &mpic 31 1
+ 19000 0 0 3 &mpic 32 1
+ 19000 0 0 4 &mpic 33 1>;
+ interrupt-parent = <&mpic>;
interrupts = <08 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
@@ -243,21 +232,20 @@
compatible = "chrp,iic";
big-endian;
interrupts = <1>;
- interrupt-parent = <8000>;
+ interrupt-parent = <&pci1>;
};
};
pci@9000 {
- linux,phandle = <9000>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x15 */
- a800 0 0 1 40000 3b 1
- a800 0 0 2 40000 3b 1
- a800 0 0 3 40000 3b 1
- a800 0 0 4 40000 3b 1>;
- interrupt-parent = <40000>;
+ a800 0 0 1 &mpic 3b 1
+ a800 0 0 2 &mpic 3b 1
+ a800 0 0 3 &mpic 3b 1
+ a800 0 0 4 &mpic 3b 1>;
+ interrupt-parent = <&mpic>;
interrupts = <09 2>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 a0000000 0 20000000
@@ -271,8 +259,7 @@
device_type = "pci";
};
- pic@40000 {
- linux,phandle = <40000>;
+ mpic: pic@40000 {
clock-frequency = <0>;
interrupt-controller;
#address-cells = <0>;
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
index 118f5a88765..5f9c102a0ab 100644
--- a/arch/powerpc/boot/dts/mpc8555cds.dts
+++ b/arch/powerpc/boot/dts/mpc8555cds.dts
@@ -12,16 +12,14 @@
/ {
model = "MPC8555CDS";
- compatible = "MPC85xxCDS";
+ compatible = "MPC8555CDS", "MPC85xxCDS";
#address-cells = <1>;
#size-cells = <1>;
- linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <200>;
PowerPC,8555@0 {
device_type = "cpu";
@@ -34,13 +32,11 @@
bus-frequency = <0>; // 166 MHz
clock-frequency = <0>; // 825 MHz, from uboot
32-bit;
- linux,phandle = <201>;
};
};
memory {
device_type = "memory";
- linux,phandle = <300>;
reg = <00000000 08000000>; // 128M at 0x0
};
@@ -58,7 +54,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
dfsrr;
};
@@ -68,17 +64,14 @@
device_type = "mdio";
compatible = "gianfar";
reg = <24520 20>;
- linux,phandle = <24520>;
- ethernet-phy@0 {
- linux,phandle = <2452000>;
- interrupt-parent = <40000>;
+ phy0: ethernet-phy@0 {
+ interrupt-parent = <&mpic>;
interrupts = <35 0>;
reg = <0>;
device_type = "ethernet-phy";
};
- ethernet-phy@1 {
- linux,phandle = <2452001>;
- interrupt-parent = <40000>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&mpic>;
interrupts = <35 0>;
reg = <1>;
device_type = "ethernet-phy";
@@ -94,8 +87,8 @@
reg = <24000 1000>;
local-mac-address = [ 00 E0 0C 00 73 00 ];
interrupts = <0d 2 0e 2 12 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452000>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
};
ethernet@25000 {
@@ -107,8 +100,8 @@
reg = <25000 1000>;
local-mac-address = [ 00 E0 0C 00 73 01 ];
interrupts = <13 2 14 2 18 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452001>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
};
serial@4500 {
@@ -117,7 +110,7 @@
reg = <4500 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
serial@4600 {
@@ -126,57 +119,56 @@
reg = <4600 100>; // reg base, size
clock-frequency = <0>; // should we fill in in uboot?
interrupts = <1a 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
- pci@8000 {
- linux,phandle = <8000>;
+ pci1: pci@8000 {
interrupt-map-mask = <1f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x10 */
- 08000 0 0 1 40000 30 1
- 08000 0 0 2 40000 31 1
- 08000 0 0 3 40000 32 1
- 08000 0 0 4 40000 33 1
+ 08000 0 0 1 &mpic 30 1
+ 08000 0 0 2 &mpic 31 1
+ 08000 0 0 3 &mpic 32 1
+ 08000 0 0 4 &mpic 33 1
/* IDSEL 0x11 */
- 08800 0 0 1 40000 30 1
- 08800 0 0 2 40000 31 1
- 08800 0 0 3 40000 32 1
- 08800 0 0 4 40000 33 1
+ 08800 0 0 1 &mpic 30 1
+ 08800 0 0 2 &mpic 31 1
+ 08800 0 0 3 &mpic 32 1
+ 08800 0 0 4 &mpic 33 1
/* IDSEL 0x12 (Slot 1) */
- 09000 0 0 1 40000 30 1
- 09000 0 0 2 40000 31 1
- 09000 0 0 3 40000 32 1
- 09000 0 0 4 40000 33 1
+ 09000 0 0 1 &mpic 30 1
+ 09000 0 0 2 &mpic 31 1
+ 09000 0 0 3 &mpic 32 1
+ 09000 0 0 4 &mpic 33 1
/* IDSEL 0x13 (Slot 2) */
- 09800 0 0 1 40000 31 1
- 09800 0 0 2 40000 32 1
- 09800 0 0 3 40000 33 1
- 09800 0 0 4 40000 30 1
+ 09800 0 0 1 &mpic 31 1
+ 09800 0 0 2 &mpic 32 1
+ 09800 0 0 3 &mpic 33 1
+ 09800 0 0 4 &mpic 30 1
/* IDSEL 0x14 (Slot 3) */
- 0a000 0 0 1 40000 32 1
- 0a000 0 0 2 40000 33 1
- 0a000 0 0 3 40000 30 1
- 0a000 0 0 4 40000 31 1
+ 0a000 0 0 1 &mpic 32 1
+ 0a000 0 0 2 &mpic 33 1
+ 0a000 0 0 3 &mpic 30 1
+ 0a000 0 0 4 &mpic 31 1
/* IDSEL 0x15 (Slot 4) */
- 0a800 0 0 1 40000 33 1
- 0a800 0 0 2 40000 30 1
- 0a800 0 0 3 40000 31 1
- 0a800 0 0 4 40000 32 1
+ 0a800 0 0 1 &mpic 33 1
+ 0a800 0 0 2 &mpic 30 1
+ 0a800 0 0 3 &mpic 31 1
+ 0a800 0 0 4 &mpic 32 1
/* Bus 1 (Tundra Bridge) */
/* IDSEL 0x12 (ISA bridge) */
- 19000 0 0 1 40000 30 1
- 19000 0 0 2 40000 31 1
- 19000 0 0 3 40000 32 1
- 19000 0 0 4 40000 33 1>;
- interrupt-parent = <40000>;
+ 19000 0 0 1 &mpic 30 1
+ 19000 0 0 2 &mpic 31 1
+ 19000 0 0 3 &mpic 32 1
+ 19000 0 0 4 &mpic 33 1>;
+ interrupt-parent = <&mpic>;
interrupts = <08 2>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
@@ -200,21 +192,20 @@
compatible = "chrp,iic";
big-endian;
interrupts = <1>;
- interrupt-parent = <8000>;
+ interrupt-parent = <&pci1>;
};
};
pci@9000 {
- linux,phandle = <9000>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x15 */
- a800 0 0 1 40000 3b 1
- a800 0 0 2 40000 3b 1
- a800 0 0 3 40000 3b 1
- a800 0 0 4 40000 3b 1>;
- interrupt-parent = <40000>;
+ a800 0 0 1 &mpic 3b 1
+ a800 0 0 2 &mpic 3b 1
+ a800 0 0 3 &mpic 3b 1
+ a800 0 0 4 &mpic 3b 1>;
+ interrupt-parent = <&mpic>;
interrupts = <09 2>;
bus-range = <0 0>;
ranges = <02000000 0 a0000000 a0000000 0 20000000
@@ -228,8 +219,7 @@
device_type = "pci";
};
- pic@40000 {
- linux,phandle = <40000>;
+ mpic: pic@40000 {
clock-frequency = <0>;
interrupt-controller;
#address-cells = <0>;
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
index 119bd5d3a83..10502638b0e 100644
--- a/arch/powerpc/boot/dts/mpc8560ads.dts
+++ b/arch/powerpc/boot/dts/mpc8560ads.dts
@@ -12,16 +12,14 @@
/ {
model = "MPC8560ADS";
- compatible = "MPC85xxADS";
+ compatible = "MPC8560ADS", "MPC85xxADS";
#address-cells = <1>;
#size-cells = <1>;
- linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <200>;
PowerPC,8560@0 {
device_type = "cpu";
@@ -34,14 +32,11 @@
bus-frequency = <13ab6680>;
clock-frequency = <312c8040>;
32-bit;
- linux,phandle = <201>;
- linux,boot-cpu;
};
};
memory {
device_type = "memory";
- linux,phandle = <300>;
reg = <00000000 10000000>;
};
@@ -58,33 +53,28 @@
device_type = "mdio";
compatible = "gianfar";
reg = <24520 20>;
- linux,phandle = <24520>;
#address-cells = <1>;
#size-cells = <0>;
- ethernet-phy@0 {
- linux,phandle = <2452000>;
- interrupt-parent = <40000>;
+ phy0: ethernet-phy@0 {
+ interrupt-parent = <&mpic>;
interrupts = <35 1>;
reg = <0>;
device_type = "ethernet-phy";
};
- ethernet-phy@1 {
- linux,phandle = <2452001>;
- interrupt-parent = <40000>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&mpic>;
interrupts = <35 1>;
reg = <1>;
device_type = "ethernet-phy";
};
- ethernet-phy@2 {
- linux,phandle = <2452002>;
- interrupt-parent = <40000>;
+ phy2: ethernet-phy@2 {
+ interrupt-parent = <&mpic>;
interrupts = <37 1>;
reg = <2>;
device_type = "ethernet-phy";
};
- ethernet-phy@3 {
- linux,phandle = <2452003>;
- interrupt-parent = <40000>;
+ phy3: ethernet-phy@3 {
+ interrupt-parent = <&mpic>;
interrupts = <37 1>;
reg = <3>;
device_type = "ethernet-phy";
@@ -98,8 +88,8 @@
reg = <24000 1000>;
address = [ 00 00 0C 00 00 FD ];
interrupts = <d 2 e 2 12 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452000>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
};
ethernet@25000 {
@@ -111,12 +101,11 @@
reg = <25000 1000>;
address = [ 00 00 0C 00 01 FD ];
interrupts = <13 2 14 2 18 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452001>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
};
pci@8000 {
- linux,phandle = <8000>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
@@ -128,96 +117,94 @@
interrupt-map = <
/* IDSEL 0x2 */
- 1000 0 0 1 40000 31 1
- 1000 0 0 2 40000 32 1
- 1000 0 0 3 40000 33 1
- 1000 0 0 4 40000 34 1
+ 1000 0 0 1 &mpic 31 1
+ 1000 0 0 2 &mpic 32 1
+ 1000 0 0 3 &mpic 33 1
+ 1000 0 0 4 &mpic 34 1
/* IDSEL 0x3 */
- 1800 0 0 1 40000 34 1
- 1800 0 0 2 40000 31 1
- 1800 0 0 3 40000 32 1
- 1800 0 0 4 40000 33 1
+ 1800 0 0 1 &mpic 34 1
+ 1800 0 0 2 &mpic 31 1
+ 1800 0 0 3 &mpic 32 1
+ 1800 0 0 4 &mpic 33 1
/* IDSEL 0x4 */
- 2000 0 0 1 40000 33 1
- 2000 0 0 2 40000 34 1
- 2000 0 0 3 40000 31 1
- 2000 0 0 4 40000 32 1
+ 2000 0 0 1 &mpic 33 1
+ 2000 0 0 2 &mpic 34 1
+ 2000 0 0 3 &mpic 31 1
+ 2000 0 0 4 &mpic 32 1
/* IDSEL 0x5 */
- 2800 0 0 1 40000 32 1
- 2800 0 0 2 40000 33 1
- 2800 0 0 3 40000 34 1
- 2800 0 0 4 40000 31 1
+ 2800 0 0 1 &mpic 32 1
+ 2800 0 0 2 &mpic 33 1
+ 2800 0 0 3 &mpic 34 1
+ 2800 0 0 4 &mpic 31 1
/* IDSEL 12 */
- 6000 0 0 1 40000 31 1
- 6000 0 0 2 40000 32 1
- 6000 0 0 3 40000 33 1
- 6000 0 0 4 40000 34 1
+ 6000 0 0 1 &mpic 31 1
+ 6000 0 0 2 &mpic 32 1
+ 6000 0 0 3 &mpic 33 1
+ 6000 0 0 4 &mpic 34 1
/* IDSEL 13 */
- 6800 0 0 1 40000 34 1
- 6800 0 0 2 40000 31 1
- 6800 0 0 3 40000 32 1
- 6800 0 0 4 40000 33 1
+ 6800 0 0 1 &mpic 34 1
+ 6800 0 0 2 &mpic 31 1
+ 6800 0 0 3 &mpic 32 1
+ 6800 0 0 4 &mpic 33 1
/* IDSEL 14*/
- 7000 0 0 1 40000 33 1
- 7000 0 0 2 40000 34 1
- 7000 0 0 3 40000 31 1
- 7000 0 0 4 40000 32 1
+ 7000 0 0 1 &mpic 33 1
+ 7000 0 0 2 &mpic 34 1
+ 7000 0 0 3 &mpic 31 1
+ 7000 0 0 4 &mpic 32 1
/* IDSEL 15 */
- 7800 0 0 1 40000 32 1
- 7800 0 0 2 40000 33 1
- 7800 0 0 3 40000 34 1
- 7800 0 0 4 40000 31 1
+ 7800 0 0 1 &mpic 32 1
+ 7800 0 0 2 &mpic 33 1
+ 7800 0 0 3 &mpic 34 1
+ 7800 0 0 4 &mpic 31 1
/* IDSEL 18 */
- 9000 0 0 1 40000 31 1
- 9000 0 0 2 40000 32 1
- 9000 0 0 3 40000 33 1
- 9000 0 0 4 40000 34 1
+ 9000 0 0 1 &mpic 31 1
+ 9000 0 0 2 &mpic 32 1
+ 9000 0 0 3 &mpic 33 1
+ 9000 0 0 4 &mpic 34 1
/* IDSEL 19 */
- 9800 0 0 1 40000 34 1
- 9800 0 0 2 40000 31 1
- 9800 0 0 3 40000 32 1
- 9800 0 0 4 40000 33 1
+ 9800 0 0 1 &mpic 34 1
+ 9800 0 0 2 &mpic 31 1
+ 9800 0 0 3 &mpic 32 1
+ 9800 0 0 4 &mpic 33 1
/* IDSEL 20 */
- a000 0 0 1 40000 33 1
- a000 0 0 2 40000 34 1
- a000 0 0 3 40000 31 1
- a000 0 0 4 40000 32 1
+ a000 0 0 1 &mpic 33 1
+ a000 0 0 2 &mpic 34 1
+ a000 0 0 3 &mpic 31 1
+ a000 0 0 4 &mpic 32 1
/* IDSEL 21 */
- a800 0 0 1 40000 32 1
- a800 0 0 2 40000 33 1
- a800 0 0 3 40000 34 1
- a800 0 0 4 40000 31 1>;
+ a800 0 0 1 &mpic 32 1
+ a800 0 0 2 &mpic 33 1
+ a800 0 0 3 &mpic 34 1
+ a800 0 0 4 &mpic 31 1>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
interrupts = <8 0>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 01000000>;
};
- pic@40000 {
- linux,phandle = <40000>;
+ mpic: pic@40000 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
- reg = <40000 20100>;
+ reg = <40000 40000>;
built-in;
device_type = "open-pic";
};
cpm@e0000000 {
- linux,phandle = <e0000000>;
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
@@ -228,13 +215,12 @@
command-proc = <919c0>;
brg-frequency = <9d5b340>;
- pic@90c00 {
- linux,phandle = <90c00>;
+ cpmpic: pic@90c00 {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
interrupts = <1e 0>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
reg = <90c00 80>;
built-in;
device_type = "cpm-pic";
@@ -251,7 +237,7 @@
tx-clock = <1>;
current-speed = <1c200>;
interrupts = <28 8>;
- interrupt-parent = <90c00>;
+ interrupt-parent = <&cpmpic>;
};
scc@91a20 {
@@ -265,7 +251,7 @@
tx-clock = <2>;
current-speed = <1c200>;
interrupts = <29 8>;
- interrupt-parent = <90c00>;
+ interrupt-parent = <&cpmpic>;
};
fcc@91320 {
@@ -279,8 +265,8 @@
rx-clock = <15>;
tx-clock = <16>;
interrupts = <21 8>;
- interrupt-parent = <90c00>;
- phy-handle = <2452002>;
+ interrupt-parent = <&cpmpic>;
+ phy-handle = <&phy2>;
};
fcc@91340 {
@@ -294,8 +280,8 @@
rx-clock = <17>;
tx-clock = <18>;
interrupts = <22 8>;
- interrupt-parent = <90c00>;
- phy-handle = <2452003>;
+ interrupt-parent = <&cpmpic>;
+ phy-handle = <&phy3>;
};
};
};
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 06d24653e42..bf49d8c997b 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -16,16 +16,14 @@
/ {
model = "MPC8568EMDS";
- compatible = "MPC85xxMDS";
+ compatible = "MPC8568EMDS", "MPC85xxMDS";
#address-cells = <1>;
#size-cells = <1>;
- linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
- linux,phandle = <200>;
PowerPC,8568@0 {
device_type = "cpu";
@@ -38,13 +36,11 @@
bus-frequency = <0>;
clock-frequency = <0>;
32-bit;
- linux,phandle = <201>;
};
};
memory {
device_type = "memory";
- linux,phandle = <300>;
reg = <00000000 10000000>;
};
@@ -67,7 +63,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <1b 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
dfsrr;
};
@@ -76,7 +72,7 @@
compatible = "fsl-i2c";
reg = <3100 100>;
interrupts = <1b 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
dfsrr;
};
@@ -86,32 +82,26 @@
device_type = "mdio";
compatible = "gianfar";
reg = <24520 20>;
- linux,phandle = <24520>;
- ethernet-phy@0 {
- linux,phandle = <2452000>;
- interrupt-parent = <40000>;
+ phy0: ethernet-phy@0 {
+ interrupt-parent = <&mpic>;
interrupts = <31 1>;
reg = <0>;
device_type = "ethernet-phy";
};
- ethernet-phy@1 {
- linux,phandle = <2452001>;
- interrupt-parent = <40000>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&mpic>;
interrupts = <32 1>;
reg = <1>;
device_type = "ethernet-phy";
};
-
- ethernet-phy@2 {
- linux,phandle = <2452002>;
- interrupt-parent = <40000>;
+ phy2: ethernet-phy@2 {
+ interrupt-parent = <&mpic>;
interrupts = <31 1>;
reg = <2>;
device_type = "ethernet-phy";
};
- ethernet-phy@3 {
- linux,phandle = <2452003>;
- interrupt-parent = <40000>;
+ phy3: ethernet-phy@3 {
+ interrupt-parent = <&mpic>;
interrupts = <32 1>;
reg = <3>;
device_type = "ethernet-phy";
@@ -127,8 +117,8 @@
reg = <24000 1000>;
mac-address = [ 00 00 00 00 00 00 ];
interrupts = <d 2 e 2 12 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452002>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy2>;
};
ethernet@25000 {
@@ -140,8 +130,8 @@
reg = <25000 1000>;
mac-address = [ 00 00 00 00 00 00];
interrupts = <13 2 14 2 18 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452003>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy3>;
};
serial@4500 {
@@ -150,7 +140,7 @@
reg = <4500 100>;
clock-frequency = <0>;
interrupts = <1a 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
serial@4600 {
@@ -159,7 +149,7 @@
reg = <4600 100>;
clock-frequency = <0>;
interrupts = <1a 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
crypto@30000 {
@@ -168,15 +158,14 @@
compatible = "talitos";
reg = <30000 f000>;
interrupts = <1d 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
num-channels = <4>;
channel-fifo-len = <18>;
exec-units-mask = <000000fe>;
descriptor-types-mask = <012b0ebf>;
};
- pic@40000 {
- linux,phandle = <40000>;
+ mpic: pic@40000 {
clock-frequency = <0>;
interrupt-controller;
#address-cells = <0>;
@@ -192,8 +181,7 @@
device_type = "par_io";
num-ports = <7>;
- ucc_pin@01 {
- linux,phandle = <e010001>;
+ pio1: ucc_pin@01 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
4 0a 1 0 2 0 /* TxD0 */
@@ -220,8 +208,7 @@
4 13 1 0 2 0 /* GTX_CLK */
1 1f 2 0 3 0>; /* GTX125 */
};
- ucc_pin@02 {
- linux,phandle = <e010002>;
+ pio2: ucc_pin@02 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
5 0a 1 0 2 0 /* TxD0 */
@@ -277,7 +264,7 @@
compatible = "fsl_spi";
reg = <4c0 40>;
interrupts = <2>;
- interrupt-parent = <80>;
+ interrupt-parent = <&qeic>;
mode = "cpu";
};
@@ -286,7 +273,7 @@
compatible = "fsl_spi";
reg = <500 40>;
interrupts = <1>;
- interrupt-parent = <80>;
+ interrupt-parent = <&qeic>;
mode = "cpu";
};
@@ -297,12 +284,12 @@
device-id = <1>;
reg = <2000 200>;
interrupts = <20>;
- interrupt-parent = <80>;
+ interrupt-parent = <&qeic>;
mac-address = [ 00 04 9f 00 23 23 ];
rx-clock = <0>;
tx-clock = <19>;
- phy-handle = <212000>;
- pio-handle = <e010001>;
+ phy-handle = <&qe_phy0>;
+ pio-handle = <&pio1>;
};
ucc@3000 {
@@ -312,12 +299,12 @@
device-id = <2>;
reg = <3000 200>;
interrupts = <21>;
- interrupt-parent = <80>;
+ interrupt-parent = <&qeic>;
mac-address = [ 00 11 22 33 44 55 ];
rx-clock = <0>;
tx-clock = <14>;
- phy-handle = <212001>;
- pio-handle = <e010002>;
+ phy-handle = <&qe_phy1>;
+ pio-handle = <&pio2>;
};
mdio@2120 {
@@ -329,33 +316,29 @@
/* These are the same PHYs as on
* gianfar's MDIO bus */
- ethernet-phy@00 {
- linux,phandle = <212000>;
- interrupt-parent = <40000>;
+ qe_phy0: ethernet-phy@00 {
+ interrupt-parent = <&mpic>;
interrupts = <31 1>;
reg = <0>;
device_type = "ethernet-phy";
interface = <6>; //ENET_1000_GMII
};
- ethernet-phy@01 {
- linux,phandle = <212001>;
- interrupt-parent = <40000>;
+ qe_phy1: ethernet-phy@01 {
+ interrupt-parent = <&mpic>;
interrupts = <32 1>;
reg = <1>;
device_type = "ethernet-phy";
interface = <6>;
};
- ethernet-phy@02 {
- linux,phandle = <212002>;
- interrupt-parent = <40000>;
+ qe_phy2: ethernet-phy@02 {
+ interrupt-parent = <&mpic>;
interrupts = <31 1>;
reg = <2>;
device_type = "ethernet-phy";
interface = <6>; //ENET_1000_GMII
};
- ethernet-phy@03 {
- linux,phandle = <212003>;
- interrupt-parent = <40000>;
+ qe_phy3: ethernet-phy@03 {
+ interrupt-parent = <&mpic>;
interrupts = <32 1>;
reg = <3>;
device_type = "ethernet-phy";
@@ -363,8 +346,7 @@
};
};
- qeic@80 {
- linux,phandle = <80>;
+ qeic: qeic@80 {
interrupt-controller;
device_type = "qeic";
#address-cells = <0>;
@@ -373,7 +355,7 @@
built-in;
big-endian;
interrupts = <1e 2 1e 2>; //high:30 low:30
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
};
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
index f0c7731743e..8a4995a85ba 100644
--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -32,7 +32,6 @@
bus-frequency = <0>; // From uboot
clock-frequency = <0>; // From uboot
32-bit;
- linux,boot-cpu;
};
PowerPC,8641@1 {
device_type = "cpu";
@@ -67,7 +66,7 @@
compatible = "fsl-i2c";
reg = <3000 100>;
interrupts = <2b 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
dfsrr;
};
@@ -76,7 +75,7 @@
compatible = "fsl-i2c";
reg = <3100 100>;
interrupts = <2b 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
dfsrr;
};
@@ -86,31 +85,26 @@
device_type = "mdio";
compatible = "gianfar";
reg = <24520 20>;
- linux,phandle = <24520>;
- ethernet-phy@0 {
- linux,phandle = <2452000>;
- interrupt-parent = <40000>;
+ phy0: ethernet-phy@0 {
+ interrupt-parent = <&mpic>;
interrupts = <4a 1>;
reg = <0>;
device_type = "ethernet-phy";
};
- ethernet-phy@1 {
- linux,phandle = <2452001>;
- interrupt-parent = <40000>;
+ phy1: ethernet-phy@1 {
+ interrupt-parent = <&mpic>;
interrupts = <4a 1>;
reg = <1>;
device_type = "ethernet-phy";
};
- ethernet-phy@2 {
- linux,phandle = <2452002>;
- interrupt-parent = <40000>;
+ phy2: ethernet-phy@2 {
+ interrupt-parent = <&mpic>;
interrupts = <4a 1>;
reg = <2>;
device_type = "ethernet-phy";
};
- ethernet-phy@3 {
- linux,phandle = <2452003>;
- interrupt-parent = <40000>;
+ phy3: ethernet-phy@3 {
+ interrupt-parent = <&mpic>;
interrupts = <4a 1>;
reg = <3>;
device_type = "ethernet-phy";
@@ -126,8 +120,8 @@
reg = <24000 1000>;
mac-address = [ 00 E0 0C 00 73 00 ];
interrupts = <1d 2 1e 2 22 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452000>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy0>;
};
ethernet@25000 {
@@ -139,8 +133,8 @@
reg = <25000 1000>;
mac-address = [ 00 E0 0C 00 73 01 ];
interrupts = <23 2 24 2 28 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452001>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy1>;
};
ethernet@26000 {
@@ -152,8 +146,8 @@
reg = <26000 1000>;
mac-address = [ 00 E0 0C 00 02 FD ];
interrupts = <1F 2 20 2 21 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452002>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy2>;
};
ethernet@27000 {
@@ -165,8 +159,8 @@
reg = <27000 1000>;
mac-address = [ 00 E0 0C 00 03 FD ];
interrupts = <25 2 26 2 27 2>;
- interrupt-parent = <40000>;
- phy-handle = <2452003>;
+ interrupt-parent = <&mpic>;
+ phy-handle = <&phy3>;
};
serial@4500 {
device_type = "serial";
@@ -174,7 +168,7 @@
reg = <4500 100>;
clock-frequency = <0>;
interrupts = <2a 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
serial@4600 {
@@ -183,7 +177,7 @@
reg = <4600 100>;
clock-frequency = <0>;
interrupts = <1c 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
pci@8000 {
@@ -197,103 +191,102 @@
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 00100000>;
clock-frequency = <1fca055>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
interrupts = <18 2>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x11 */
- 8800 0 0 1 4d0 3 2
- 8800 0 0 2 4d0 4 2
- 8800 0 0 3 4d0 5 2
- 8800 0 0 4 4d0 6 2
+ 8800 0 0 1 &i8259 3 2
+ 8800 0 0 2 &i8259 4 2
+ 8800 0 0 3 &i8259 5 2
+ 8800 0 0 4 &i8259 6 2
/* IDSEL 0x12 */
- 9000 0 0 1 4d0 4 2
- 9000 0 0 2 4d0 5 2
- 9000 0 0 3 4d0 6 2
- 9000 0 0 4 4d0 3 2
+ 9000 0 0 1 &i8259 4 2
+ 9000 0 0 2 &i8259 5 2
+ 9000 0 0 3 &i8259 6 2
+ 9000 0 0 4 &i8259 3 2
/* IDSEL 0x13 */
- 9800 0 0 1 4d0 0 0
- 9800 0 0 2 4d0 0 0
- 9800 0 0 3 4d0 0 0
- 9800 0 0 4 4d0 0 0
+ 9800 0 0 1 &i8259 0 0
+ 9800 0 0 2 &i8259 0 0
+ 9800 0 0 3 &i8259 0 0
+ 9800 0 0 4 &i8259 0 0
/* IDSEL 0x14 */
- a000 0 0 1 4d0 0 0
- a000 0 0 2 4d0 0 0
- a000 0 0 3 4d0 0 0
- a000 0 0 4 4d0 0 0
+ a000 0 0 1 &i8259 0 0
+ a000 0 0 2 &i8259 0 0
+ a000 0 0 3 &i8259 0 0
+ a000 0 0 4 &i8259 0 0
/* IDSEL 0x15 */
- a800 0 0 1 4d0 0 0
- a800 0 0 2 4d0 0 0
- a800 0 0 3 4d0 0 0
- a800 0 0 4 4d0 0 0
+ a800 0 0 1 &i8259 0 0
+ a800 0 0 2 &i8259 0 0
+ a800 0 0 3 &i8259 0 0
+ a800 0 0 4 &i8259 0 0
/* IDSEL 0x16 */
- b000 0 0 1 4d0 0 0
- b000 0 0 2 4d0 0 0
- b000 0 0 3 4d0 0 0
- b000 0 0 4 4d0 0 0
+ b000 0 0 1 &i8259 0 0
+ b000 0 0 2 &i8259 0 0
+ b000 0 0 3 &i8259 0 0
+ b000 0 0 4 &i8259 0 0
/* IDSEL 0x17 */
- b800 0 0 1 4d0 0 0
- b800 0 0 2 4d0 0 0
- b800 0 0 3 4d0 0 0
- b800 0 0 4 4d0 0 0
+ b800 0 0 1 &i8259 0 0
+ b800 0 0 2 &i8259 0 0
+ b800 0 0 3 &i8259 0 0
+ b800 0 0 4 &i8259 0 0
/* IDSEL 0x18 */
- c000 0 0 1 4d0 0 0
- c000 0 0 2 4d0 0 0
- c000 0 0 3 4d0 0 0
- c000 0 0 4 4d0 0 0
+ c000 0 0 1 &i8259 0 0
+ c000 0 0 2 &i8259 0 0
+ c000 0 0 3 &i8259 0 0
+ c000 0 0 4 &i8259 0 0
/* IDSEL 0x19 */
- c800 0 0 1 4d0 0 0
- c800 0 0 2 4d0 0 0
- c800 0 0 3 4d0 0 0
- c800 0 0 4 4d0 0 0
+ c800 0 0 1 &i8259 0 0
+ c800 0 0 2 &i8259 0 0
+ c800 0 0 3 &i8259 0 0
+ c800 0 0 4 &i8259 0 0
/* IDSEL 0x1a */
- d000 0 0 1 4d0 6 2
- d000 0 0 2 4d0 3 2
- d000 0 0 3 4d0 4 2
- d000 0 0 4 4d0 5 2
+ d000 0 0 1 &i8259 6 2
+ d000 0 0 2 &i8259 3 2
+ d000 0 0 3 &i8259 4 2
+ d000 0 0 4 &i8259 5 2
/* IDSEL 0x1b */
- d800 0 0 1 4d0 5 2
- d800 0 0 2 4d0 0 0
- d800 0 0 3 4d0 0 0
- d800 0 0 4 4d0 0 0
+ d800 0 0 1 &i8259 5 2
+ d800 0 0 2 &i8259 0 0
+ d800 0 0 3 &i8259 0 0
+ d800 0 0 4 &i8259 0 0
/* IDSEL 0x1c */
- e000 0 0 1 4d0 9 2
- e000 0 0 2 4d0 a 2
- e000 0 0 3 4d0 c 2
- e000 0 0 4 4d0 7 2
+ e000 0 0 1 &i8259 9 2
+ e000 0 0 2 &i8259 a 2
+ e000 0 0 3 &i8259 c 2
+ e000 0 0 4 &i8259 7 2
/* IDSEL 0x1d */
- e800 0 0 1 4d0 9 2
- e800 0 0 2 4d0 a 2
- e800 0 0 3 4d0 b 2
- e800 0 0 4 4d0 0 0
+ e800 0 0 1 &i8259 9 2
+ e800 0 0 2 &i8259 a 2
+ e800 0 0 3 &i8259 b 2
+ e800 0 0 4 &i8259 0 0
/* IDSEL 0x1e */
- f000 0 0 1 4d0 c 2
- f000 0 0 2 4d0 0 0
- f000 0 0 3 4d0 0 0
- f000 0 0 4 4d0 0 0
+ f000 0 0 1 &i8259 c 2
+ f000 0 0 2 &i8259 0 0
+ f000 0 0 3 &i8259 0 0
+ f000 0 0 4 &i8259 0 0
/* IDSEL 0x1f */
- f800 0 0 1 4d0 6 2
- f800 0 0 2 4d0 0 0
- f800 0 0 3 4d0 0 0
- f800 0 0 4 4d0 0 0
+ f800 0 0 1 &i8259 6 2
+ f800 0 0 2 &i8259 0 0
+ f800 0 0 3 &i8259 0 0
+ f800 0 0 4 &i8259 0 0
>;
- i8259@4d0 {
- linux,phandle = <4d0>;
+ i8259: i8259@4d0 {
clock-frequency = <0>;
interrupt-controller;
device_type = "interrupt-controller";
@@ -303,12 +296,11 @@
compatible = "chrp,iic";
big-endian;
interrupts = <49 2>;
- interrupt-parent = <40000>;
+ interrupt-parent = <&mpic>;
};
};
- pic@40000 {
- linux,phandle = <40000>;
+ mpic: pic@40000 {
clock-frequency = <0>;
interrupt-controller;
#address-cells = <0>;
@@ -317,23 +309,7 @@
built-in;
compatible = "chrp,open-pic";
device_type = "open-pic";
- big-endian;
- interrupts = <
- 10 2 11 2 12 2 13 2
- 14 2 15 2 16 2 17 2
- 18 2 19 2 1a 2 1b 2
- 1c 2 1d 2 1e 2 1f 2
- 20 2 21 2 22 2 23 2
- 24 2 25 2 26 2 27 2
- 28 2 29 2 2a 2 2b 2
- 2c 2 2d 2 2e 2 2f 2
- 30 2 31 2 32 2 33 2
- 34 2 35 2 36 2 37 2
- 38 2 39 2 2a 2 3b 2
- 3c 2 3d 2 3e 2 3f 2
- 48 1 49 2 4a 1
- >;
- interrupt-parent = <40000>;
+ big-endian;
};
};
};
diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts
index 5d4005239b8..2b56b5df451 100644
--- a/arch/powerpc/boot/dts/mpc866ads.dts
+++ b/arch/powerpc/boot/dts/mpc866ads.dts
@@ -37,7 +37,6 @@
interrupts = <f 2>; // decrementer interrupt
interrupt-parent = <ff000000>;
linux,phandle = <201>;
- linux,boot-cpu;
};
};
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
index cf1a19f962c..faecd08c54d 100644
--- a/arch/powerpc/boot/dts/mpc885ads.dts
+++ b/arch/powerpc/boot/dts/mpc885ads.dts
@@ -37,7 +37,6 @@
interrupts = <f 2>; // decrementer interrupt
interrupt-parent = <ff000000>;
linux,phandle = <201>;
- linux,boot-cpu;
};
};
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index e956548da00..24367319ce2 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -147,6 +147,7 @@ CONFIG_PPC_RTAS=y
# CONFIG_RTAS_ERROR_LOGGING is not set
CONFIG_RTAS_PROC=y
CONFIG_RTAS_FLASH=y
+CONFIG_PPC_PMI=m
CONFIG_MMIO_NVRAM=y
# CONFIG_PPC_MPC106 is not set
# CONFIG_PPC_970_NAP is not set
diff --git a/arch/powerpc/configs/mpc832xemds_defconfig b/arch/powerpc/configs/mpc832x_mds_defconfig
index e1b36de6b38..e1b36de6b38 100644
--- a/arch/powerpc/configs/mpc832xemds_defconfig
+++ b/arch/powerpc/configs/mpc832x_mds_defconfig
diff --git a/arch/powerpc/configs/mpc8360emds_defconfig b/arch/powerpc/configs/mpc836x_mds_defconfig
index bbe38ccc3d8..8eb475cd0df 100644
--- a/arch/powerpc/configs/mpc8360emds_defconfig
+++ b/arch/powerpc/configs/mpc836x_mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Fri Jan 26 00:19:45 2007
+# Linux kernel version: 2.6.20
+# Sat Feb 17 10:09:26 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -34,9 +34,9 @@ CONFIG_DEFAULT_UIMAGE=y
CONFIG_PPC_83xx=y
# CONFIG_PPC_85xx is not set
# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_83xx=y
@@ -63,6 +63,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
@@ -129,10 +130,11 @@ CONFIG_PPC_GEN550=y
#
# Platform support
#
+# CONFIG_MPC8313_RDB is not set
# CONFIG_MPC832x_MDS is not set
-# CONFIG_MPC834x_SYS is not set
+# CONFIG_MPC834x_MDS is not set
# CONFIG_MPC834x_ITX is not set
-CONFIG_MPC8360E_PB=y
+CONFIG_MPC836x_MDS=y
CONFIG_PPC_MPC836x=y
# CONFIG_MPIC is not set
@@ -162,6 +164,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
@@ -171,6 +174,7 @@ CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
# CONFIG_MPIC_WEIRD is not set
# CONFIG_PPC_I8259 is not set
@@ -219,6 +223,7 @@ 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=y
@@ -528,6 +533,7 @@ CONFIG_UCC_GETH=y
# Ethernet (10000 Mbit)
#
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
@@ -620,6 +626,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -690,6 +697,7 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
# CONFIG_I2C_SIS5595 is not set
@@ -804,6 +812,7 @@ CONFIG_FIRMWARE_EDID=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
# USB support
@@ -868,6 +877,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
+# Auxiliary Display support
+#
+
+#
# Virtualization
#
@@ -1011,7 +1024,8 @@ CONFIG_BITREVERSE=y
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
#
# Instrumentation Support
@@ -1060,8 +1074,10 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -1075,6 +1091,7 @@ CONFIG_CRYPTO_DES=y
# 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
#
diff --git a/arch/powerpc/configs/mpc8568mds_defconfig b/arch/powerpc/configs/mpc8568mds_defconfig
index 058e06d88bc..7b3800674cb 100644
--- a/arch/powerpc/configs/mpc8568mds_defconfig
+++ b/arch/powerpc/configs/mpc8568mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Wed Feb 7 23:54:25 2007
+# Linux kernel version: 2.6.20
+# Sat Feb 17 16:26:53 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -34,9 +34,9 @@ CONFIG_DEFAULT_UIMAGE=y
# CONFIG_PPC_83xx is not set
CONFIG_PPC_85xx=y
# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_85xx=y
CONFIG_E500=y
@@ -63,6 +63,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
@@ -130,7 +131,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_MPC8540_ADS is not set
# CONFIG_MPC8560_ADS is not set
# CONFIG_MPC85xx_CDS is not set
-CONFIG_MPC8568_MDS=y
+CONFIG_MPC85xx_MDS=y
CONFIG_MPC85xx=y
CONFIG_PPC_INDIRECT_PCI_BE=y
CONFIG_MPIC=y
@@ -162,6 +163,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
@@ -171,6 +173,7 @@ CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
# CONFIG_MPIC_WEIRD is not set
# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
@@ -216,6 +219,7 @@ 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=y
@@ -301,6 +305,7 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
@@ -341,7 +346,6 @@ CONFIG_BLK_DEV_INITRD=y
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -543,6 +547,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -698,6 +703,7 @@ CONFIG_FIRMWARE_EDID=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
# USB support
@@ -760,6 +766,10 @@ CONFIG_HID=y
#
#
+# Auxiliary Display support
+#
+
+#
# Virtualization
#
@@ -896,7 +906,8 @@ CONFIG_BITREVERSE=y
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
#
# Instrumentation Support
@@ -914,6 +925,7 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
@@ -922,7 +934,6 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -932,6 +943,8 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
CONFIG_DEBUGGER=y
# CONFIG_XMON is not set
# CONFIG_BDI_SWITCH is not set
@@ -943,6 +956,8 @@ CONFIG_PPC_EARLY_DEBUG=y
# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
+# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
#
# Security options
@@ -970,8 +985,10 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -985,6 +1002,7 @@ CONFIG_CRYPTO_DES=y
# 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
#
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index debac66e825..a8da0aea3b8 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -500,7 +500,7 @@ CONFIG_BLK_DEV_AMD74XX=y
# CONFIG_BLK_DEV_PDC202XX_NEW is not set
# CONFIG_BLK_DEV_SVWKS is not set
# CONFIG_BLK_DEV_SIIMAGE is not set
-CONFIG_BLK_DEV_SL82C105=y
+# CONFIG_BLK_DEV_SL82C105 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -646,7 +646,7 @@ CONFIG_SATA_SVW=y
# CONFIG_PATA_SIL680 is not set
# CONFIG_PATA_SIS is not set
# CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_WINBOND=y
#
# Multi-device support (RAID and LVM)
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 1c794fe718f..6e96e50c362 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -483,7 +483,7 @@ CONFIG_BLK_DEV_AMD74XX=y
# CONFIG_BLK_DEV_PDC202XX_NEW is not set
# CONFIG_BLK_DEV_SVWKS is not set
# CONFIG_BLK_DEV_SIIMAGE is not set
-CONFIG_BLK_DEV_SL82C105=y
+# CONFIG_BLK_DEV_SL82C105 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -628,7 +628,7 @@ CONFIG_ATA=y
# CONFIG_PATA_SIL680 is not set
# CONFIG_PATA_SIS is not set
# CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
+CONFIG_PATA_WINBOND=y
#
# Multi-device support (RAID and LVM)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 3e86e6e0f77..8d52b23348b 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1599,6 +1599,7 @@ struct property *of_find_property(const struct device_node *np,
return pp;
}
+EXPORT_SYMBOL(of_find_property);
/*
* Find a property with a given name for a given node
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 12c51e4ad2b..ea6fd552c7e 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -5,6 +5,7 @@
#include <linux/pci_regs.h>
#include <linux/module.h>
#include <linux/ioport.h>
+#include <linux/etherdevice.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
@@ -1003,3 +1004,42 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
return res;
}
EXPORT_SYMBOL_GPL(of_irq_map_one);
+
+/**
+ * Search the device tree for the best MAC address to use. 'mac-address' is
+ * checked first, because that is supposed to contain to "most recent" MAC
+ * address. If that isn't set, then 'local-mac-address' is checked next,
+ * because that is the default address. If that isn't set, then the obsolete
+ * 'address' is checked, just in case we're using an old device tree.
+ *
+ * Note that the 'address' property is supposed to contain a virtual address of
+ * the register set, but some DTS files have redefined that property to be the
+ * MAC address.
+ *
+ * All-zero MAC addresses are rejected, because those could be properties that
+ * exist in the device tree, but were not set by U-Boot. For example, the
+ * DTS could define 'mac-address' and 'local-mac-address', with zero MAC
+ * addresses. Some older U-Boots only initialized 'local-mac-address'. In
+ * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
+ * but is all zeros.
+*/
+const void *of_get_mac_address(struct device_node *np)
+{
+ struct property *pp;
+
+ pp = of_find_property(np, "mac-address", NULL);
+ if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+ return pp->value;
+
+ pp = of_find_property(np, "local-mac-address", NULL);
+ if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+ return pp->value;
+
+ pp = of_find_property(np, "address", NULL);
+ if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+ return pp->value;
+
+ return NULL;
+}
+EXPORT_SYMBOL(of_get_mac_address);
+
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 16e4ee1c231..1d443407423 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -103,7 +103,7 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
*
*/
if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
- mmu_virtual_psize)) {
+ mmu_io_psize)) {
printk(KERN_ERR "Failed to do bolted mapping IO "
"memory at %016lx !\n", pa);
return -ENOMEM;
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 1aea1e69ff3..713b31a16ce 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -38,12 +38,12 @@ config MPC834x_ITX
Be aware that PCI initialization is the bootloader's
responsibility.
-config MPC8360E_PB
- bool "Freescale MPC8360E PB"
+config MPC836x_MDS
+ bool "Freescale MPC836x MDS"
select DEFAULT_UIMAGE
select QUICC_ENGINE
help
- This option enables support for the MPC836x EMDS Processor Board.
+ This option enables support for the MPC836x MDS Processor Board.
endchoice
@@ -69,6 +69,6 @@ config PPC_MPC836x
bool
select PPC_UDBG_16550
select PPC_INDIRECT_PCI
- default y if MPC8360E_PB
+ default y if MPC836x_MDS
endmenu
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 6c8199c4c38..dfc970d0df1 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -6,5 +6,5 @@ obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o
obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o
-obj-$(CONFIG_MPC8360E_PB) += mpc8360e_pb.o
+obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o
obj-$(CONFIG_MPC832x_MDS) += mpc832x_mds.o
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
index c3b98c34eb6..32e9e949284 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -74,16 +74,9 @@ void __init mpc8313_rdb_init_IRQ(void)
*/
static int __init mpc8313_rdb_probe(void)
{
- char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
- "model", NULL);
- if (model == NULL)
- return 0;
- if (strcmp(model, "MPC8313ERDB"))
- return 0;
+ unsigned long root = of_get_flat_dt_root();
- DBG("MPC8313 RDB found\n");
-
- return 1;
+ return of_flat_dt_is_compatible(root, "MPC8313ERDB");
}
define_machine(mpc8313_rdb) {
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 3ecb55f8a6e..17e3a3c6d8b 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -57,11 +57,6 @@ unsigned long isa_mem_base = 0;
static u8 *bcsr_regs = NULL;
-u8 *get_bcsr(void)
-{
- return bcsr_regs;
-}
-
/* ************************************************************************
*
* Setup the architecture
@@ -74,17 +69,6 @@ static void __init mpc832x_sys_setup_arch(void)
if (ppc_md.progress)
ppc_md.progress("mpc832x_sys_setup_arch()", 0);
- np = of_find_node_by_type(NULL, "cpu");
- if (np != 0) {
- unsigned int *fp =
- (int *)get_property(np, "clock-frequency", NULL);
- if (fp != 0)
- loops_per_jiffy = *fp / HZ;
- else
- loops_per_jiffy = 50000000 / HZ;
- of_node_put(np);
- }
-
/* Map BCSR area */
np = of_find_node_by_name(NULL, "bcsr");
if (np != 0) {
@@ -121,34 +105,23 @@ static void __init mpc832x_sys_setup_arch(void)
iounmap(bcsr_regs);
of_node_put(np);
}
-
#endif /* CONFIG_QUICC_ENGINE */
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
+static struct of_device_id mpc832x_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ { .type = "qe", },
+ {},
+};
+
static int __init mpc832x_declare_of_platform_devices(void)
{
- struct device_node *np;
-
- for (np = NULL; (np = of_find_compatible_node(np, "network",
- "ucc_geth")) != NULL;) {
- int ucc_num;
- char bus_id[BUS_ID_SIZE];
+ if (!machine_is(mpc832x_mds))
+ return 0;
- ucc_num = *((uint *) get_property(np, "device-id", NULL)) - 1;
- snprintf(bus_id, BUS_ID_SIZE, "ucc_geth.%u", ucc_num);
- of_platform_device_create(np, bus_id, NULL);
- }
+ /* Publish the QE devices */
+ of_platform_bus_probe(NULL, mpc832x_ids, NULL);
return 0;
}
@@ -156,7 +129,6 @@ device_initcall(mpc832x_declare_of_platform_devices);
static void __init mpc832x_sys_init_IRQ(void)
{
-
struct device_node *np;
np = of_find_node_by_type(NULL, "ipic");
@@ -189,6 +161,9 @@ static int __init mpc832x_rtc_hookup(void)
{
struct timespec tv;
+ if (!machine_is(mpc832x_mds))
+ return 0;
+
ppc_md.get_rtc_time = ds1374_get_rtc_time;
ppc_md.set_rtc_time = ds1374_set_rtc_time;
@@ -207,17 +182,9 @@ late_initcall(mpc832x_rtc_hookup);
*/
static int __init mpc832x_sys_probe(void)
{
- char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
- "model", NULL);
-
- if (model == NULL)
- return 0;
- if (strcmp(model, "MPC8323EMDS"))
- return 0;
-
- DBG("%s found\n", model);
+ unsigned long root = of_get_flat_dt_root();
- return 1;
+ return of_flat_dt_is_compatible(root, "MPC832xMDS");
}
define_machine(mpc832x_mds) {
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 443a3172f37..3c009f6d4a4 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -55,28 +55,12 @@ static void __init mpc834x_itx_setup_arch(void)
if (ppc_md.progress)
ppc_md.progress("mpc834x_itx_setup_arch()", 0);
- np = of_find_node_by_type(NULL, "cpu");
- if (np != 0) {
- const unsigned int *fp =
- get_property(np, "clock-frequency", NULL);
- if (fp != 0)
- loops_per_jiffy = *fp / HZ;
- else
- loops_per_jiffy = 50000000 / HZ;
- of_node_put(np);
- }
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif
-
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
static void __init mpc834x_itx_init_IRQ(void)
@@ -100,10 +84,9 @@ static void __init mpc834x_itx_init_IRQ(void)
*/
static int __init mpc834x_itx_probe(void)
{
- /* We always match for now, eventually we should look at the flat
- dev tree to ensure this is the board we are suppose to run on
- */
- return 1;
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "MPC834xMITX");
}
define_machine(mpc834x_itx) {
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index d2736da76c4..e5d81916687 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -125,17 +125,6 @@ static void __init mpc834x_mds_setup_arch(void)
if (ppc_md.progress)
ppc_md.progress("mpc834x_mds_setup_arch()", 0);
- np = of_find_node_by_type(NULL, "cpu");
- if (np != 0) {
- const unsigned int *fp =
- get_property(np, "clock-frequency", NULL);
- if (fp != 0)
- loops_per_jiffy = *fp / HZ;
- else
- loops_per_jiffy = 50000000 / HZ;
- of_node_put(np);
- }
-
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
@@ -144,12 +133,6 @@ static void __init mpc834x_mds_setup_arch(void)
#endif
mpc834x_usb_cfg();
-
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
static void __init mpc834x_mds_init_IRQ(void)
@@ -176,6 +159,9 @@ static int __init mpc834x_rtc_hookup(void)
{
struct timespec tv;
+ if (!machine_is(mpc834x_mds))
+ return 0;
+
ppc_md.get_rtc_time = ds1374_get_rtc_time;
ppc_md.set_rtc_time = ds1374_set_rtc_time;
@@ -194,10 +180,9 @@ late_initcall(mpc834x_rtc_hookup);
*/
static int __init mpc834x_mds_probe(void)
{
- /* We always match for now, eventually we should look at the flat
- dev tree to ensure this is the board we are suppose to run on
- */
- return 1;
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "MPC834xMDS");
}
define_machine(mpc834x_mds) {
diff --git a/arch/powerpc/platforms/83xx/mpc8360e_pb.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index ccce2f9f283..526ed090a44 100644
--- a/arch/powerpc/platforms/83xx/mpc8360e_pb.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -5,12 +5,12 @@
* Yin Olivia <Hong-hua.Yin@freescale.com>
*
* Description:
- * MPC8360E MDS PB board specific routines.
+ * MPC8360E MDS board specific routines.
*
* Changelog:
* Jun 21, 2006 Initial version
*
- * This program is free software; you can redistribute it and/or modify it
+ * 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.
@@ -62,33 +62,17 @@ unsigned long isa_mem_base = 0;
static u8 *bcsr_regs = NULL;
-u8 *get_bcsr(void)
-{
- return bcsr_regs;
-}
-
/* ************************************************************************
*
* Setup the architecture
*
*/
-static void __init mpc8360_sys_setup_arch(void)
+static void __init mpc836x_mds_setup_arch(void)
{
struct device_node *np;
if (ppc_md.progress)
- ppc_md.progress("mpc8360_sys_setup_arch()", 0);
-
- np = of_find_node_by_type(NULL, "cpu");
- if (np != 0) {
- const unsigned int *fp =
- get_property(np, "clock-frequency", NULL);
- if (fp != 0)
- loops_per_jiffy = *fp / HZ;
- else
- loops_per_jiffy = 50000000 / HZ;
- of_node_put(np);
- }
+ ppc_md.progress("mpc836x_mds_setup_arch()", 0);
/* Map BCSR area */
np = of_find_node_by_name(NULL, "bcsr");
@@ -128,40 +112,29 @@ static void __init mpc8360_sys_setup_arch(void)
}
#endif /* CONFIG_QUICC_ENGINE */
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
-static int __init mpc8360_declare_of_platform_devices(void)
-{
- struct device_node *np;
+static struct of_device_id mpc836x_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ { .type = "qe", },
+ {},
+};
- for (np = NULL; (np = of_find_compatible_node(np, "network",
- "ucc_geth")) != NULL;) {
- int ucc_num;
- char bus_id[BUS_ID_SIZE];
+static int __init mpc836x_declare_of_platform_devices(void)
+{
+ if (!machine_is(mpc836x_mds))
+ return 0;
- ucc_num = *((uint *) get_property(np, "device-id", NULL)) - 1;
- snprintf(bus_id, BUS_ID_SIZE, "ucc_geth.%u", ucc_num);
- of_platform_device_create(np, bus_id, NULL);
- }
+ /* Publish the QE devices */
+ of_platform_bus_probe(NULL, mpc836x_ids, NULL);
return 0;
}
-device_initcall(mpc8360_declare_of_platform_devices);
+device_initcall(mpc836x_declare_of_platform_devices);
-static void __init mpc8360_sys_init_IRQ(void)
+static void __init mpc836x_mds_init_IRQ(void)
{
-
struct device_node *np;
np = of_find_node_by_type(NULL, "ipic");
@@ -194,6 +167,9 @@ static int __init mpc8360_rtc_hookup(void)
{
struct timespec tv;
+ if (!machine_is(mpc836x_mds))
+ return 0;
+
ppc_md.get_rtc_time = ds1374_get_rtc_time;
ppc_md.set_rtc_time = ds1374_set_rtc_time;
@@ -210,28 +186,21 @@ late_initcall(mpc8360_rtc_hookup);
/*
* Called very early, MMU is off, device-tree isn't unflattened
*/
-static int __init mpc8360_sys_probe(void)
+static int __init mpc836x_mds_probe(void)
{
- char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
- "model", NULL);
- if (model == NULL)
- return 0;
- if (strcmp(model, "MPC8360EPB"))
- return 0;
-
- DBG("MPC8360EMDS-PB found\n");
+ unsigned long root = of_get_flat_dt_root();
- return 1;
+ return of_flat_dt_is_compatible(root, "MPC836xMDS");
}
-define_machine(mpc8360_sys) {
- .name = "MPC8360E PB",
- .probe = mpc8360_sys_probe,
- .setup_arch = mpc8360_sys_setup_arch,
- .init_IRQ = mpc8360_sys_init_IRQ,
- .get_irq = ipic_get_irq,
- .restart = mpc83xx_restart,
- .time_init = mpc83xx_time_init,
+define_machine(mpc836x_mds) {
+ .name = "MPC836x MDS",
+ .probe = mpc836x_mds_probe,
+ .setup_arch = mpc836x_mds_setup_arch,
+ .init_IRQ = mpc836x_mds_init_IRQ,
+ .get_irq = ipic_get_irq,
+ .restart = mpc83xx_restart,
+ .time_init = mpc83xx_time_init,
.calibrate_decr = generic_calibrate_decr,
- .progress = udbg_progress,
+ .progress = udbg_progress,
};
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 0efdd2f1bab..eb661ccf2da 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -23,12 +23,12 @@ config MPC85xx_CDS
help
This option enables support for the MPC85xx CDS board
-config MPC8568_MDS
- bool "Freescale MPC8568 MDS"
+config MPC85xx_MDS
+ bool "Freescale MPC85xx MDS"
select DEFAULT_UIMAGE
# select QUICC_ENGINE
help
- This option enables support for the MPC8568 MDS board
+ This option enables support for the MPC85xx MDS board
endchoice
@@ -47,7 +47,7 @@ config MPC85xx
bool
select PPC_UDBG_16550
select PPC_INDIRECT_PCI
- default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS || MPC8568_MDS
+ default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS || MPC85xx_MDS
config PPC_INDIRECT_PCI_BE
bool
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index e40e521816b..4e63917ada9 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -5,4 +5,4 @@ obj-$(CONFIG_PPC_85xx) += misc.o pci.o
obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
-obj-$(CONFIG_MPC8568_MDS) += mpc8568_mds.o
+obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index c56fce57621..8ed034aeca5 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -17,7 +17,6 @@
#include <linux/kdev_t.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
-#include <linux/root_dev.h>
#include <asm/system.h>
#include <asm/time.h>
@@ -245,12 +244,6 @@ static void __init mpc85xx_ads_setup_arch(void)
add_bridge(np);
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
-
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
@@ -279,10 +272,9 @@ static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
*/
static int __init mpc85xx_ads_probe(void)
{
- /* We always match for now, eventually we should look at the flat
- dev tree to ensure this is the board we are suppose to run on
- */
- return 1;
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "MPC85xxADS");
}
define_machine(mpc85xx_ads) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index abc0aca6de4..4232686be44 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -22,7 +22,6 @@
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
-#include <linux/root_dev.h>
#include <linux/initrd.h>
#include <linux/module.h>
#include <linux/fsl_devices.h>
@@ -263,12 +262,6 @@ static void __init mpc85xx_cds_setup_arch(void)
ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
-
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
}
static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
@@ -298,11 +291,9 @@ static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
*/
static int __init mpc85xx_cds_probe(void)
{
- /* We always match for now, eventually we should look at
- * the flat dev tree to ensure this is the board we are
- * supposed to run on
- */
- return 1;
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "MPC85xxCDS");
}
define_machine(mpc85xx_cds) {
diff --git a/arch/powerpc/platforms/85xx/mpc8568_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 0861d1107bc..81144d2ae45 100644
--- a/arch/powerpc/platforms/85xx/mpc8568_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -8,7 +8,7 @@
* Yin Olivia <Hong-hua.Yin@freescale.com>
*
* Description:
- * MPC8568E MDS PB board specific routines.
+ * MPC85xx MDS board specific routines.
*
* 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
@@ -27,7 +27,6 @@
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
-#include <linux/root_dev.h>
#include <linux/initrd.h>
#include <linux/module.h>
#include <linux/fsl_devices.h>
@@ -70,14 +69,13 @@ unsigned long isa_mem_base = 0;
* Setup the architecture
*
*/
-static void __init mpc8568_mds_setup_arch(void)
+static void __init mpc85xx_mds_setup_arch(void)
{
struct device_node *np;
static u8 *bcsr_regs = NULL;
-
if (ppc_md.progress)
- ppc_md.progress("mpc8568_mds_setup_arch()", 0);
+ ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
np = of_find_node_by_type(NULL, "cpu");
if (np != NULL) {
@@ -145,26 +143,26 @@ static void __init mpc8568_mds_setup_arch(void)
#endif /* CONFIG_QUICC_ENGINE */
}
-static struct of_device_id mpc8568_ids[] = {
+static struct of_device_id mpc85xx_ids[] = {
{ .type = "soc", },
{ .compatible = "soc", },
{ .type = "qe", },
{},
};
-static int __init mpc8568_publish_devices(void)
+static int __init mpc85xx_publish_devices(void)
{
- if (!machine_is(mpc8568_mds))
+ if (!machine_is(mpc85xx_mds))
return 0;
/* Publish the QE devices */
- of_platform_bus_probe(NULL,mpc8568_ids,NULL);
+ of_platform_bus_probe(NULL,mpc85xx_ids,NULL);
return 0;
}
-device_initcall(mpc8568_publish_devices);
+device_initcall(mpc85xx_publish_devices);
-static void __init mpc8568_mds_pic_init(void)
+static void __init mpc85xx_mds_pic_init(void)
{
struct mpic *mpic;
struct resource r;
@@ -207,7 +205,6 @@ static void __init mpc8568_mds_pic_init(void)
mpic_init(mpic);
-
#ifdef CONFIG_QUICC_ENGINE
np = of_find_node_by_type(NULL, "qeic");
if (!np)
@@ -218,27 +215,18 @@ static void __init mpc8568_mds_pic_init(void)
#endif /* CONFIG_QUICC_ENGINE */
}
-
-static int __init mpc8568_mds_probe(void)
+static int __init mpc85xx_mds_probe(void)
{
- char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
- "model", NULL);
- if (model == NULL)
- return 0;
- if (strcmp(model, "MPC8568EMDS"))
- return 0;
-
- DBG("MPC8568EMDS found\n");
+ unsigned long root = of_get_flat_dt_root();
- return 1;
+ return of_flat_dt_is_compatible(root, "MPC85xxMDS");
}
-
-define_machine(mpc8568_mds) {
- .name = "MPC8568E MDS",
- .probe = mpc8568_mds_probe,
- .setup_arch = mpc8568_mds_setup_arch,
- .init_IRQ = mpc8568_mds_pic_init,
+define_machine(mpc85xx_mds) {
+ .name = "MPC85xx MDS",
+ .probe = mpc85xx_mds_probe,
+ .setup_arch = mpc85xx_mds_setup_arch,
+ .init_IRQ = mpc85xx_mds_pic_init,
.get_irq = mpic_get_irq,
.restart = mpc85xx_restart,
.calibrate_decr = generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index f4dd5f2f8a2..f42f801cf84 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -18,7 +18,6 @@
#include <linux/kdev_t.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
-#include <linux/root_dev.h>
#include <asm/system.h>
#include <asm/time.h>
@@ -120,6 +119,8 @@ mpc86xx_hpcn_init_irq(void)
DBG("mpc86xxhpcn: cascade mapped to irq %d\n", cascade_irq);
i8259_init(cascade_node, 0);
+ of_node_put(cascade_node);
+
set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade);
#endif
}
@@ -365,12 +366,6 @@ mpc86xx_hpcn_setup_arch(void)
printk("MPC86xx HPCN board from Freescale Semiconductor\n");
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
-
#ifdef CONFIG_SMP
mpc86xx_smp_init();
#endif
diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile
index 3baf658ac54..f4f82520dc4 100644
--- a/arch/powerpc/platforms/celleb/Makefile
+++ b/arch/powerpc/platforms/celleb/Makefile
@@ -1,9 +1,8 @@
obj-y += interrupt.o iommu.o setup.o \
htab.o beat.o pci.o \
- scc_epci.o hvCall.o
+ scc_epci.o scc_uhc.o hvCall.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o
-obj-$(CONFIG_USB) += scc_uhc.o
obj-$(CONFIG_HAS_TXX9_SERIAL) += scc_sio.o
obj-$(CONFIG_SPU_BASE) += spu_priv1.o
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
index 1de63acfda8..5f4d0d93323 100644
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -137,10 +137,12 @@ static int celleb_check_legacy_ioport(unsigned int baseport)
return -ENODEV;
}
+#ifdef CONFIG_KEXEC
static void celleb_kexec_cpu_down(int crash, int secondary)
{
beatic_deinit_IRQ();
}
+#endif
static struct of_device_id celleb_bus_ids[] = {
{ .type = "scc", },
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 4be3943d1c0..d270a1e374d 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -62,4 +62,14 @@ config PS3_PS3AV
This support is required for graphics and sound. In
general, all users will say Y or M.
+config PS3_SYS_MANAGER
+ bool "PS3 System Manager driver"
+ select PS3_VUART
+ default y
+ help
+ Include support for the PS3 System Manager.
+
+ This support is required for system control. In
+ general, all users will say Y.
+
endmenu
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 13d669a8eca..ac5df9688dc 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -42,6 +42,10 @@
#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
#endif
+#if !defined(CONFIG_SMP)
+static void smp_send_stop(void) {}
+#endif
+
int ps3_get_firmware_version(union ps3_firmware_version *v)
{
int result = lv1_get_version_info(&v->raw);
@@ -66,22 +70,35 @@ static void ps3_power_save(void)
lv1_pause(0);
}
+static void ps3_restart(char *cmd)
+{
+ DBG("%s:%d cmd '%s'\n", __func__, __LINE__, cmd);
+
+ smp_send_stop();
+ ps3_sys_manager_restart(); /* never returns */
+}
+
+static void ps3_power_off(void)
+{
+ DBG("%s:%d\n", __func__, __LINE__);
+
+ smp_send_stop();
+ ps3_sys_manager_power_off(); /* never returns */
+}
+
static void ps3_panic(char *str)
{
DBG("%s:%d %s\n", __func__, __LINE__, str);
-#ifdef CONFIG_SMP
smp_send_stop();
-#endif
printk("\n");
printk(" System does not reboot automatically.\n");
printk(" Please press POWER button.\n");
printk("\n");
- for (;;) ;
+ while(1);
}
-
static void prealloc(struct ps3_prealloc *p)
{
if (!p->size)
@@ -219,6 +236,8 @@ define_machine(ps3) {
.get_rtc_time = ps3_get_rtc_time,
.calibrate_decr = ps3_calibrate_decr,
.progress = ps3_progress,
+ .restart = ps3_restart,
+ .power_off = ps3_power_off,
#if defined(CONFIG_KEXEC)
.kexec_cpu_down = ps3_kexec_cpu_down,
.machine_kexec = ps3_machine_kexec,
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index dc0583bdbc6..2dfd05095a2 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -4,7 +4,7 @@ endif
obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \
setup.o iommu.o ras.o rtasd.o pci_dlpar.o \
- firmware.o
+ firmware.o power.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_SCANLOG) += scanlog.o
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c
new file mode 100644
index 00000000000..2624b71df73
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/power.c
@@ -0,0 +1,87 @@
+/*
+ * Interface for power-management for ppc64 compliant platform
+ *
+ * Manish Ahuja <mahuja@us.ibm.com>
+ *
+ * Feb 2007
+ *
+ * Copyright (C) 2007 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+unsigned long rtas_poweron_auto; /* default and normal state is 0 */
+
+static ssize_t auto_poweron_show(struct subsystem *subsys, char *buf)
+{
+ return sprintf(buf, "%lu\n", rtas_poweron_auto);
+}
+
+static ssize_t
+auto_poweron_store(struct subsystem *subsys, const char *buf, size_t n)
+{
+ int ret;
+ unsigned long ups_restart;
+ ret = sscanf(buf, "%lu", &ups_restart);
+
+ if ((ret == 1) && ((ups_restart == 1) || (ups_restart == 0))){
+ rtas_poweron_auto = ups_restart;
+ return n;
+ }
+ return -EINVAL;
+}
+
+static struct subsys_attribute auto_poweron_attr = {
+ .attr = {
+ .name = __stringify(auto_poweron),
+ .mode = 0644,
+ },
+ .show = auto_poweron_show,
+ .store = auto_poweron_store,
+};
+
+#ifndef CONFIG_PM
+decl_subsys(power,NULL,NULL);
+
+static struct attribute *g[] = {
+ &auto_poweron_attr.attr,
+ NULL,
+};
+
+static struct attribute_group attr_group = {
+ .attrs = g,
+};
+
+static int __init pm_init(void)
+{
+ int error = subsystem_register(&power_subsys);
+ if (!error)
+ error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+ return error;
+}
+core_initcall(pm_init);
+#else
+extern struct subsystem power_subsys;
+
+static int __init apo_pm_init(void)
+{
+ return (subsys_create_file(&power_subsys, &auto_poweron_attr));
+}
+__initcall(apo_pm_init);
+#endif
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index b43f1397a5b..22bc0198974 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -29,8 +29,11 @@ static inline smp_init_pseries_xics(void) { };
extern void setup_kexec_cpu_down_xics(void);
extern void setup_kexec_cpu_down_mpic(void);
#else
-static inline setup_kexec_cpu_down_xics(void) { };
-static inline setup_kexec_cpu_down_mpic(void) { };
+static inline void setup_kexec_cpu_down_xics(void) { }
+static inline void setup_kexec_cpu_down_mpic(void) { }
#endif
+/* Poweron flag used for enabling auto ups restart */
+extern unsigned long rtas_poweron_auto;
+
#endif /* _PSERIES_PSERIES_H */
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 435a0459652..34aff47b1f5 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -486,6 +486,34 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus)
return PCI_PROBE_NORMAL;
}
+/**
+ * pSeries_power_off - tell firmware about how to power off the system.
+ *
+ * This function calls either the power-off rtas token in normal cases
+ * or the ibm,power-off-ups token (if present & requested) in case of
+ * a power failure. If power-off token is used, power on will only be
+ * possible with power button press. If ibm,power-off-ups token is used
+ * it will allow auto poweron after power is restored.
+ */
+void pSeries_power_off(void)
+{
+ int rc;
+ int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups");
+
+ if (rtas_flash_term_hook)
+ rtas_flash_term_hook(SYS_POWER_OFF);
+
+ if (rtas_poweron_auto == 0 ||
+ rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) {
+ rc = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1);
+ printk(KERN_INFO "RTAS power-off returned %d\n", rc);
+ } else {
+ rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL);
+ printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n", rc);
+ }
+ for (;;);
+}
+
define_machine(pseries) {
.name = "pSeries",
.probe = pSeries_probe,
@@ -496,7 +524,7 @@ define_machine(pseries) {
.pcibios_fixup = pSeries_final_fixup,
.pci_probe_mode = pSeries_pci_probe_mode,
.restart = rtas_restart,
- .power_off = rtas_power_off,
+ .power_off = pSeries_power_off,
.halt = rtas_halt,
.panic = rtas_os_term,
.get_boot_time = rtas_get_boot_time,
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 85dcdf17841..26ca3ffbc1d 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_MPC106) += grackle.o
obj-$(CONFIG_PPC_DCR) += dcr.o
obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o
+obj-$(CONFIG_PPC_PMI) += pmi.o
obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 34161bc5a02..d20f02927f7 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -233,14 +233,7 @@ static int __init gfar_of_init(void)
goto err;
}
- mac_addr = get_property(np, "local-mac-address", NULL);
- if (mac_addr == NULL)
- mac_addr = get_property(np, "mac-address", NULL);
- if (mac_addr == NULL) {
- /* Obsolete */
- mac_addr = get_property(np, "address", NULL);
- }
-
+ mac_addr = of_get_mac_address(np);
if (mac_addr)
memcpy(gfar_data.mac_addr, mac_addr, 6);
@@ -646,8 +639,9 @@ static int __init fs_enet_of_init(void)
goto unreg;
}
- mac_addr = get_property(np, "mac-address", NULL);
- memcpy(fs_enet_data.macaddr, mac_addr, 6);
+ mac_addr = of_get_mac_address(np);
+ if (mac_addr)
+ memcpy(fs_enet_data.macaddr, mac_addr, 6);
ph = get_property(np, "phy-handle", NULL);
phy = of_find_node_by_phandle(*ph);
@@ -931,8 +925,9 @@ static int __init fs_enet_of_init(void)
goto err;
r[0].name = enet_regs;
- mac_addr = (void *)get_property(np, "mac-address", NULL);
- memcpy(fs_enet_data.macaddr, mac_addr, 6);
+ mac_addr = of_get_mac_address(np);
+ if (mac_addr)
+ memcpy(fs_enet_data.macaddr, mac_addr, 6);
ph = (phandle *) get_property(np, "phy-handle", NULL);
if (ph != NULL)
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 4e54a09dd33..bcfb900481f 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1370,7 +1370,7 @@ void mpic_request_ipis(void)
printk(KERN_ERR "Failed to map IPI %d\n", i);
break;
}
- request_irq(vipi, mpic_ipi_action, IRQF_DISABLED,
+ request_irq(vipi, mpic_ipi_action, IRQF_DISABLED|IRQF_PERCPU,
ipi_names[i], mpic);
}
}
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
new file mode 100644
index 00000000000..a5282011d39
--- /dev/null
+++ b/arch/powerpc/sysdev/pmi.c
@@ -0,0 +1,305 @@
+/*
+ * pmi driver
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * PMI (Platform Management Interrupt) is a way to communicate
+ * with the BMC (Baseboard Management Controller) via interrupts.
+ * Unlike IPMI it is bidirectional and has a low latency.
+ *
+ * Author: Christian Krafft <krafft@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+#include <asm/io.h>
+#include <asm/pmi.h>
+
+
+struct pmi_data {
+ struct list_head handler;
+ spinlock_t handler_spinlock;
+ spinlock_t pmi_spinlock;
+ struct mutex msg_mutex;
+ pmi_message_t msg;
+ struct completion *completion;
+ struct of_device *dev;
+ int irq;
+ u8 __iomem *pmi_reg;
+ struct work_struct work;
+};
+
+
+
+static void __iomem *of_iomap(struct device_node *np)
+{
+ struct resource res;
+
+ if (of_address_to_resource(np, 0, &res))
+ return NULL;
+
+ pr_debug("Resource start: 0x%lx\n", res.start);
+ pr_debug("Resource end: 0x%lx\n", res.end);
+
+ return ioremap(res.start, 1 + res.end - res.start);
+}
+
+
+static int pmi_irq_handler(int irq, void *dev_id)
+{
+ struct pmi_data *data;
+ u8 type;
+ int rc;
+
+ data = dev_id;
+
+ spin_lock(&data->pmi_spinlock);
+
+ type = ioread8(data->pmi_reg + PMI_READ_TYPE);
+ pr_debug("pmi: got message of type %d\n", type);
+
+ if (type & PMI_ACK && !data->completion) {
+ printk(KERN_WARNING "pmi: got unexpected ACK message.\n");
+ rc = -EIO;
+ goto unlock;
+ }
+
+ if (data->completion && !(type & PMI_ACK)) {
+ printk(KERN_WARNING "pmi: expected ACK, but got %d\n", type);
+ rc = -EIO;
+ goto unlock;
+ }
+
+ data->msg.type = type;
+ data->msg.data0 = ioread8(data->pmi_reg + PMI_READ_DATA0);
+ data->msg.data1 = ioread8(data->pmi_reg + PMI_READ_DATA1);
+ data->msg.data2 = ioread8(data->pmi_reg + PMI_READ_DATA2);
+ rc = 0;
+unlock:
+ spin_unlock(&data->pmi_spinlock);
+
+ if (rc == -EIO) {
+ rc = IRQ_HANDLED;
+ goto out;
+ }
+
+ if (data->msg.type & PMI_ACK) {
+ complete(data->completion);
+ rc = IRQ_HANDLED;
+ goto out;
+ }
+
+ schedule_work(&data->work);
+
+ rc = IRQ_HANDLED;
+out:
+ return rc;
+}
+
+
+static struct of_device_id pmi_match[] = {
+ { .type = "ibm,pmi", .name = "ibm,pmi" },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, pmi_match);
+
+static void pmi_notify_handlers(struct work_struct *work)
+{
+ struct pmi_data *data;
+ struct pmi_handler *handler;
+
+ data = container_of(work, struct pmi_data, work);
+
+ spin_lock(&data->handler_spinlock);
+ list_for_each_entry(handler, &data->handler, node) {
+ pr_debug(KERN_INFO "pmi: notifying handler %p\n", handler);
+ if (handler->type == data->msg.type)
+ handler->handle_pmi_message(data->dev, data->msg);
+ }
+ spin_unlock(&data->handler_spinlock);
+}
+
+static int pmi_of_probe(struct of_device *dev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = dev->node;
+ struct pmi_data *data;
+ int rc;
+
+ data = kzalloc(sizeof(struct pmi_data), GFP_KERNEL);
+ if (!data) {
+ printk(KERN_ERR "pmi: could not allocate memory.\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ data->pmi_reg = of_iomap(np);
+ if (!data->pmi_reg) {
+ printk(KERN_ERR "pmi: invalid register address.\n");
+ rc = -EFAULT;
+ goto error_cleanup_data;
+ }
+
+ INIT_LIST_HEAD(&data->handler);
+
+ mutex_init(&data->msg_mutex);
+ spin_lock_init(&data->pmi_spinlock);
+ spin_lock_init(&data->handler_spinlock);
+
+ INIT_WORK(&data->work, pmi_notify_handlers);
+
+ dev->dev.driver_data = data;
+ data->dev = dev;
+
+ data->irq = irq_of_parse_and_map(np, 0);
+ if (data->irq == NO_IRQ) {
+ printk(KERN_ERR "pmi: invalid interrupt.\n");
+ rc = -EFAULT;
+ goto error_cleanup_iomap;
+ }
+
+ rc = request_irq(data->irq, pmi_irq_handler, 0, "pmi", data);
+ if (rc) {
+ printk(KERN_ERR "pmi: can't request IRQ %d: returned %d\n",
+ data->irq, rc);
+ goto error_cleanup_iomap;
+ }
+
+ printk(KERN_INFO "pmi: found pmi device at addr %p.\n", data->pmi_reg);
+
+ goto out;
+
+error_cleanup_iomap:
+ iounmap(data->pmi_reg);
+
+error_cleanup_data:
+ kfree(data);
+
+out:
+ return rc;
+}
+
+static int pmi_of_remove(struct of_device *dev)
+{
+ struct pmi_data *data;
+ struct pmi_handler *handler, *tmp;
+
+ data = dev->dev.driver_data;
+
+ free_irq(data->irq, data);
+ iounmap(data->pmi_reg);
+
+ spin_lock(&data->handler_spinlock);
+
+ list_for_each_entry_safe(handler, tmp, &data->handler, node)
+ list_del(&handler->node);
+
+ spin_unlock(&data->handler_spinlock);
+
+ kfree(dev->dev.driver_data);
+
+ return 0;
+}
+
+static struct of_platform_driver pmi_of_platform_driver = {
+ .name = "pmi",
+ .match_table = pmi_match,
+ .probe = pmi_of_probe,
+ .remove = pmi_of_remove
+};
+
+static int __init pmi_module_init(void)
+{
+ return of_register_platform_driver(&pmi_of_platform_driver);
+}
+module_init(pmi_module_init);
+
+static void __exit pmi_module_exit(void)
+{
+ of_unregister_platform_driver(&pmi_of_platform_driver);
+}
+module_exit(pmi_module_exit);
+
+void pmi_send_message(struct of_device *device, pmi_message_t msg)
+{
+ struct pmi_data *data;
+ unsigned long flags;
+ DECLARE_COMPLETION_ONSTACK(completion);
+
+ data = device->dev.driver_data;
+
+ mutex_lock(&data->msg_mutex);
+
+ data->msg = msg;
+ pr_debug("pmi_send_message: msg is %08x\n", *(u32*)&msg);
+
+ data->completion = &completion;
+
+ spin_lock_irqsave(&data->pmi_spinlock, flags);
+ iowrite8(msg.data0, data->pmi_reg + PMI_WRITE_DATA0);
+ iowrite8(msg.data1, data->pmi_reg + PMI_WRITE_DATA1);
+ iowrite8(msg.data2, data->pmi_reg + PMI_WRITE_DATA2);
+ iowrite8(msg.type, data->pmi_reg + PMI_WRITE_TYPE);
+ spin_unlock_irqrestore(&data->pmi_spinlock, flags);
+
+ pr_debug("pmi_send_message: wait for completion\n");
+
+ wait_for_completion_interruptible_timeout(data->completion,
+ PMI_TIMEOUT);
+
+ data->completion = NULL;
+
+ mutex_unlock(&data->msg_mutex);
+}
+EXPORT_SYMBOL_GPL(pmi_send_message);
+
+void pmi_register_handler(struct of_device *device,
+ struct pmi_handler *handler)
+{
+ struct pmi_data *data;
+ data = device->dev.driver_data;
+
+ spin_lock(&data->handler_spinlock);
+ list_add_tail(&handler->node, &data->handler);
+ spin_unlock(&data->handler_spinlock);
+}
+EXPORT_SYMBOL_GPL(pmi_register_handler);
+
+void pmi_unregister_handler(struct of_device *device,
+ struct pmi_handler *handler)
+{
+ struct pmi_data *data;
+
+ pr_debug("pmi: unregistering handler %p\n", handler);
+
+ data = device->dev.driver_data;
+
+ spin_lock(&data->handler_spinlock);
+ list_del(&handler->node);
+ spin_unlock(&data->handler_spinlock);
+}
+EXPORT_SYMBOL_GPL(pmi_unregister_handler);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
+MODULE_DESCRIPTION("IBM Platform Management Interrupt driver");
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index e657559bea9..a457ac1c663 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -1,13 +1,12 @@
/*
- * arch/powerpc/sysdev/qe_lib/ucc_fast.c
- *
- * QE UCC Fast API Set - UCC Fast specific routines implementations.
- *
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
*
* Authors: Shlomi Gridish <gridish@freescale.com>
* Li Yang <leoli@freescale.com>
*
+ * Description:
+ * QE UCC Fast API Set - UCC Fast specific routines implementations.
+ *
* 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
@@ -27,79 +26,61 @@
#include <asm/ucc.h>
#include <asm/ucc_fast.h>
-#define uccf_printk(level, format, arg...) \
- printk(level format "\n", ## arg)
-
-#define uccf_dbg(format, arg...) \
- uccf_printk(KERN_DEBUG , format , ## arg)
-#define uccf_err(format, arg...) \
- uccf_printk(KERN_ERR , format , ## arg)
-#define uccf_info(format, arg...) \
- uccf_printk(KERN_INFO , format , ## arg)
-#define uccf_warn(format, arg...) \
- uccf_printk(KERN_WARNING , format , ## arg)
-
-#ifdef UCCF_VERBOSE_DEBUG
-#define uccf_vdbg uccf_dbg
-#else
-#define uccf_vdbg(fmt, args...) do { } while (0)
-#endif /* UCCF_VERBOSE_DEBUG */
-
void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
{
- uccf_info("UCC%d Fast registers:", uccf->uf_info->ucc_num);
- uccf_info("Base address: 0x%08x", (u32) uccf->uf_regs);
+ printk(KERN_INFO "UCC%d Fast registers:", uccf->uf_info->ucc_num);
+ printk(KERN_INFO "Base address: 0x%08x", (u32) uccf->uf_regs);
- uccf_info("gumr : addr - 0x%08x, val - 0x%08x",
+ printk(KERN_INFO "gumr : addr - 0x%08x, val - 0x%08x",
(u32) & uccf->uf_regs->gumr, in_be32(&uccf->uf_regs->gumr));
- uccf_info("upsmr : addr - 0x%08x, val - 0x%08x",
+ printk(KERN_INFO "upsmr : addr - 0x%08x, val - 0x%08x",
(u32) & uccf->uf_regs->upsmr, in_be32(&uccf->uf_regs->upsmr));
- uccf_info("utodr : addr - 0x%08x, val - 0x%04x",
+ printk(KERN_INFO "utodr : addr - 0x%08x, val - 0x%04x",
(u32) & uccf->uf_regs->utodr, in_be16(&uccf->uf_regs->utodr));
- uccf_info("udsr : addr - 0x%08x, val - 0x%04x",
+ printk(KERN_INFO "udsr : addr - 0x%08x, val - 0x%04x",
(u32) & uccf->uf_regs->udsr, in_be16(&uccf->uf_regs->udsr));
- uccf_info("ucce : addr - 0x%08x, val - 0x%08x",
+ printk(KERN_INFO "ucce : addr - 0x%08x, val - 0x%08x",
(u32) & uccf->uf_regs->ucce, in_be32(&uccf->uf_regs->ucce));
- uccf_info("uccm : addr - 0x%08x, val - 0x%08x",
+ printk(KERN_INFO "uccm : addr - 0x%08x, val - 0x%08x",
(u32) & uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
- uccf_info("uccs : addr - 0x%08x, val - 0x%02x",
+ printk(KERN_INFO "uccs : addr - 0x%08x, val - 0x%02x",
(u32) & uccf->uf_regs->uccs, uccf->uf_regs->uccs);
- uccf_info("urfb : addr - 0x%08x, val - 0x%08x",
+ printk(KERN_INFO "urfb : addr - 0x%08x, val - 0x%08x",
(u32) & uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
- uccf_info("urfs : addr - 0x%08x, val - 0x%04x",
+ printk(KERN_INFO "urfs : addr - 0x%08x, val - 0x%04x",
(u32) & uccf->uf_regs->urfs, in_be16(&uccf->uf_regs->urfs));
- uccf_info("urfet : addr - 0x%08x, val - 0x%04x",
+ printk(KERN_INFO "urfet : addr - 0x%08x, val - 0x%04x",
(u32) & uccf->uf_regs->urfet, in_be16(&uccf->uf_regs->urfet));
- uccf_info("urfset: addr - 0x%08x, val - 0x%04x",
+ printk(KERN_INFO "urfset: addr - 0x%08x, val - 0x%04x",
(u32) & uccf->uf_regs->urfset,
in_be16(&uccf->uf_regs->urfset));
- uccf_info("utfb : addr - 0x%08x, val - 0x%08x",
+ printk(KERN_INFO "utfb : addr - 0x%08x, val - 0x%08x",
(u32) & uccf->uf_regs->utfb, in_be32(&uccf->uf_regs->utfb));
- uccf_info("utfs : addr - 0x%08x, val - 0x%04x",
+ printk(KERN_INFO "utfs : addr - 0x%08x, val - 0x%04x",
(u32) & uccf->uf_regs->utfs, in_be16(&uccf->uf_regs->utfs));
- uccf_info("utfet : addr - 0x%08x, val - 0x%04x",
+ printk(KERN_INFO "utfet : addr - 0x%08x, val - 0x%04x",
(u32) & uccf->uf_regs->utfet, in_be16(&uccf->uf_regs->utfet));
- uccf_info("utftt : addr - 0x%08x, val - 0x%04x",
+ printk(KERN_INFO "utftt : addr - 0x%08x, val - 0x%04x",
(u32) & uccf->uf_regs->utftt, in_be16(&uccf->uf_regs->utftt));
- uccf_info("utpt : addr - 0x%08x, val - 0x%04x",
+ printk(KERN_INFO "utpt : addr - 0x%08x, val - 0x%04x",
(u32) & uccf->uf_regs->utpt, in_be16(&uccf->uf_regs->utpt));
- uccf_info("urtry : addr - 0x%08x, val - 0x%08x",
+ printk(KERN_INFO "urtry : addr - 0x%08x, val - 0x%08x",
(u32) & uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
- uccf_info("guemr : addr - 0x%08x, val - 0x%02x",
+ printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x",
(u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr);
}
u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
{
switch (uccf_num) {
- case 0: return QE_CR_SUBBLOCK_UCCFAST1;
+ case 0: return QE_CR_SUBBLOCK_UCCFAST1;
case 1: return QE_CR_SUBBLOCK_UCCFAST2;
case 2: return QE_CR_SUBBLOCK_UCCFAST3;
case 3: return QE_CR_SUBBLOCK_UCCFAST4;
case 4: return QE_CR_SUBBLOCK_UCCFAST5;
case 5: return QE_CR_SUBBLOCK_UCCFAST6;
case 6: return QE_CR_SUBBLOCK_UCCFAST7;
- case 7: return QE_CR_SUBBLOCK_UCCFAST8;
+ case 7: return QE_CR_SUBBLOCK_UCCFAST8;
default: return QE_CR_SUBBLOCK_INVALID;
}
}
@@ -153,84 +134,72 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
{
struct ucc_fast_private *uccf;
struct ucc_fast *uf_regs;
- u32 gumr = 0;
+ u32 gumr;
int ret;
- uccf_vdbg("%s: IN", __FUNCTION__);
-
if (!uf_info)
return -EINVAL;
/* check if the UCC port number is in range. */
if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
- uccf_err("ucc_fast_init: Illegal UCC number!");
+ printk(KERN_ERR "%s: illegal UCC number", __FUNCTION__);
return -EINVAL;
}
/* Check that 'max_rx_buf_length' is properly aligned (4). */
if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) {
- uccf_err("ucc_fast_init: max_rx_buf_length not aligned.");
+ printk(KERN_ERR "%s: max_rx_buf_length not aligned", __FUNCTION__);
return -EINVAL;
}
/* Validate Virtual Fifo register values */
if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) {
- uccf_err
- ("ucc_fast_init: Virtual Fifo register urfs too small.");
+ printk(KERN_ERR "%s: urfs is too small", __FUNCTION__);
return -EINVAL;
}
if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- uccf_err
- ("ucc_fast_init: Virtual Fifo register urfs not aligned.");
+ printk(KERN_ERR "%s: urfs is not aligned", __FUNCTION__);
return -EINVAL;
}
if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- uccf_err
- ("ucc_fast_init: Virtual Fifo register urfet not aligned.");
+ printk(KERN_ERR "%s: urfet is not aligned.", __FUNCTION__);
return -EINVAL;
}
if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- uccf_err
- ("ucc_fast_init: Virtual Fifo register urfset not aligned.");
+ printk(KERN_ERR "%s: urfset is not aligned", __FUNCTION__);
return -EINVAL;
}
if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- uccf_err
- ("ucc_fast_init: Virtual Fifo register utfs not aligned.");
+ printk(KERN_ERR "%s: utfs is not aligned", __FUNCTION__);
return -EINVAL;
}
if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- uccf_err
- ("ucc_fast_init: Virtual Fifo register utfet not aligned.");
+ printk(KERN_ERR "%s: utfet is not aligned", __FUNCTION__);
return -EINVAL;
}
if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- uccf_err
- ("ucc_fast_init: Virtual Fifo register utftt not aligned.");
+ printk(KERN_ERR "%s: utftt is not aligned", __FUNCTION__);
return -EINVAL;
}
uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
if (!uccf) {
- uccf_err
- ("ucc_fast_init: No memory for UCC slow data structure!");
+ printk(KERN_ERR "%s: Cannot allocate private data", __FUNCTION__);
return -ENOMEM;
}
/* Fill fast UCC structure */
uccf->uf_info = uf_info;
/* Set the PHY base address */
- uccf->uf_regs =
- (struct ucc_fast *) ioremap(uf_info->regs, sizeof(struct ucc_fast));
+ uccf->uf_regs = ioremap(uf_info->regs, sizeof(struct ucc_fast));
if (uccf->uf_regs == NULL) {
- uccf_err
- ("ucc_fast_init: No memory map for UCC slow controller!");
+ printk(KERN_ERR "%s: Cannot map UCC registers", __FUNCTION__);
return -ENOMEM;
}
@@ -249,7 +218,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
/* Init Guemr register */
if ((ret = ucc_init_guemr((struct ucc_common *) (uf_regs)))) {
- uccf_err("ucc_fast_init: Could not init the guemr register.");
+ printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__);
ucc_fast_free(uccf);
return ret;
}
@@ -258,7 +227,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
if ((ret = ucc_set_type(uf_info->ucc_num,
(struct ucc_common *) (uf_regs),
UCC_SPEED_TYPE_FAST))) {
- uccf_err("ucc_fast_init: Could not set type to fast.");
+ printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
ucc_fast_free(uccf);
return ret;
}
@@ -267,10 +236,9 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
/* Set GUMR */
/* For more details see the hardware spec. */
- /* gumr starts as zero. */
+ gumr = uf_info->ttx_trx;
if (uf_info->tci)
gumr |= UCC_FAST_GUMR_TCI;
- gumr |= uf_info->ttx_trx;
if (uf_info->cdp)
gumr |= UCC_FAST_GUMR_CDP;
if (uf_info->ctsp)
@@ -298,9 +266,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
uccf->ucc_fast_tx_virtual_fifo_base_offset =
qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
if (IS_MURAM_ERR(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
- uccf_err
- ("ucc_fast_init: Can not allocate MURAM memory for "
- "struct ucc_fastx_virtual_fifo_base_offset.");
+ printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO", __FUNCTION__);
uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
ucc_fast_free(uccf);
return -ENOMEM;
@@ -308,14 +274,11 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
/* Allocate memory for Rx Virtual Fifo */
uccf->ucc_fast_rx_virtual_fifo_base_offset =
- qe_muram_alloc(uf_info->urfs +
- (u32)
+ qe_muram_alloc(uf_info->urfs +
UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
if (IS_MURAM_ERR(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
- uccf_err
- ("ucc_fast_init: Can not allocate MURAM memory for "
- "ucc_fast_rx_virtual_fifo_base_offset.");
+ printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO", __FUNCTION__);
uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
ucc_fast_free(uccf);
return -ENOMEM;
@@ -342,26 +305,22 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
/* If NMSI (not Tsa), set Tx and Rx clock. */
if (!uf_info->tsa) {
/* Rx clock routing */
- if (uf_info->rx_clock != QE_CLK_NONE) {
- if (ucc_set_qe_mux_rxtx
- (uf_info->ucc_num, uf_info->rx_clock,
- COMM_DIR_RX)) {
- uccf_err
- ("ucc_fast_init: Illegal value for parameter 'RxClock'.");
- ucc_fast_free(uccf);
- return -EINVAL;
- }
+ if ((uf_info->rx_clock != QE_CLK_NONE) &&
+ ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->rx_clock,
+ COMM_DIR_RX)) {
+ printk(KERN_ERR "%s: illegal value for RX clock",
+ __FUNCTION__);
+ ucc_fast_free(uccf);
+ return -EINVAL;
}
/* Tx clock routing */
- if (uf_info->tx_clock != QE_CLK_NONE) {
- if (ucc_set_qe_mux_rxtx
- (uf_info->ucc_num, uf_info->tx_clock,
- COMM_DIR_TX)) {
- uccf_err
- ("ucc_fast_init: Illegal value for parameter 'TxClock'.");
- ucc_fast_free(uccf);
- return -EINVAL;
- }
+ if ((uf_info->tx_clock != QE_CLK_NONE) &&
+ ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->tx_clock,
+ COMM_DIR_TX)) {
+ printk(KERN_ERR "%s: illegal value for TX clock",
+ __FUNCTION__);
+ ucc_fast_free(uccf);
+ return -EINVAL;
}
}
@@ -370,9 +329,9 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
/* First, clear anything pending at UCC level,
* otherwise, old garbage may come through
- * as soon as the dam is opened
- * Writing '1' clears
- */
+ * as soon as the dam is opened. */
+
+ /* Writing '1' clears */
out_be32(&uf_regs->ucce, 0xffffffff);
*uccf_ret = uccf;
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
index 0e97e5c94f8..817df73ecf5 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -19,7 +19,6 @@
#include <linux/stddef.h>
#include <linux/interrupt.h>
-#include <asm/irq.h>
#include <asm/io.h>
#include <asm/immap_qe.h>
#include <asm/qe.h>
@@ -27,24 +26,6 @@
#include <asm/ucc.h>
#include <asm/ucc_slow.h>
-#define uccs_printk(level, format, arg...) \
- printk(level format "\n", ## arg)
-
-#define uccs_dbg(format, arg...) \
- uccs_printk(KERN_DEBUG , format , ## arg)
-#define uccs_err(format, arg...) \
- uccs_printk(KERN_ERR , format , ## arg)
-#define uccs_info(format, arg...) \
- uccs_printk(KERN_INFO , format , ## arg)
-#define uccs_warn(format, arg...) \
- uccs_printk(KERN_WARNING , format , ## arg)
-
-#ifdef UCCS_VERBOSE_DEBUG
-#define uccs_vdbg uccs_dbg
-#else
-#define uccs_vdbg(fmt, args...) do { } while (0)
-#endif /* UCCS_VERBOSE_DEBUG */
-
u32 ucc_slow_get_qe_cr_subblock(int uccs_num)
{
switch (uccs_num) {
@@ -135,51 +116,53 @@ void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode)
int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret)
{
+ struct ucc_slow_private *uccs;
u32 i;
struct ucc_slow *us_regs;
u32 gumr;
- u8 function_code = 0;
- u8 *bd;
- struct ucc_slow_private *uccs;
+ struct qe_bd *bd;
u32 id;
u32 command;
- int ret;
-
- uccs_vdbg("%s: IN", __FUNCTION__);
+ int ret = 0;
if (!us_info)
return -EINVAL;
/* check if the UCC port number is in range. */
if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) {
- uccs_err("ucc_slow_init: Illegal UCC number!");
+ printk(KERN_ERR "%s: illegal UCC number", __FUNCTION__);
return -EINVAL;
}
/*
* Set mrblr
* Check that 'max_rx_buf_length' is properly aligned (4), unless
- * rfw is 1, meaning that QE accepts one byte at a time, unlike normal
+ * rfw is 1, meaning that QE accepts one byte at a time, unlike normal
* case when QE accepts 32 bits at a time.
*/
if ((!us_info->rfw) &&
(us_info->max_rx_buf_length & (UCC_SLOW_MRBLR_ALIGNMENT - 1))) {
- uccs_err("max_rx_buf_length not aligned.");
+ printk(KERN_ERR "max_rx_buf_length not aligned.");
return -EINVAL;
}
uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
if (!uccs) {
- uccs_err
- ("ucc_slow_init: No memory for UCC slow data structure!");
+ printk(KERN_ERR "%s: Cannot allocate private data", __FUNCTION__);
return -ENOMEM;
}
/* Fill slow UCC structure */
uccs->us_info = us_info;
+ /* Set the PHY base address */
+ uccs->us_regs = ioremap(us_info->regs, sizeof(struct ucc_slow));
+ if (uccs->us_regs == NULL) {
+ printk(KERN_ERR "%s: Cannot map UCC registers", __FUNCTION__);
+ return -ENOMEM;
+ }
+
uccs->saved_uccm = 0;
uccs->p_rx_frame = 0;
- uccs->us_regs = us_info->regs;
us_regs = uccs->us_regs;
uccs->p_ucce = (u16 *) & (us_regs->ucce);
uccs->p_uccm = (u16 *) & (us_regs->uccm);
@@ -190,24 +173,22 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
#endif /* STATISTICS */
/* Get PRAM base */
- uccs->us_pram_offset = qe_muram_alloc(UCC_SLOW_PRAM_SIZE,
- ALIGNMENT_OF_UCC_SLOW_PRAM);
+ uccs->us_pram_offset =
+ qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM);
if (IS_MURAM_ERR(uccs->us_pram_offset)) {
- uccs_err
- ("ucc_slow_init: Can not allocate MURAM memory "
- "for Slow UCC.");
+ printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __FUNCTION__);
ucc_slow_free(uccs);
return -ENOMEM;
}
id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, QE_CR_PROTOCOL_UNSPECIFIED,
- (u32) uccs->us_pram_offset);
+ uccs->us_pram_offset);
uccs->us_pram = qe_muram_addr(uccs->us_pram_offset);
/* Init Guemr register */
if ((ret = ucc_init_guemr((struct ucc_common *) (us_info->regs)))) {
- uccs_err("ucc_slow_init: Could not init the guemr register.");
+ printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__);
ucc_slow_free(uccs);
return ret;
}
@@ -216,7 +197,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
if ((ret = ucc_set_type(us_info->ucc_num,
(struct ucc_common *) (us_info->regs),
UCC_SPEED_TYPE_SLOW))) {
- uccs_err("ucc_slow_init: Could not init the guemr register.");
+ printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
ucc_slow_free(uccs);
return ret;
}
@@ -230,7 +211,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
QE_ALIGNMENT_OF_BD);
if (IS_MURAM_ERR(uccs->rx_base_offset)) {
- uccs_err("ucc_slow_init: No memory for Rx BD's.");
+ printk(KERN_ERR "%s: cannot allocate RX BDs", __FUNCTION__);
uccs->rx_base_offset = 0;
ucc_slow_free(uccs);
return -ENOMEM;
@@ -240,7 +221,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
QE_ALIGNMENT_OF_BD);
if (IS_MURAM_ERR(uccs->tx_base_offset)) {
- uccs_err("ucc_slow_init: No memory for Tx BD's.");
+ printk(KERN_ERR "%s: cannot allocate TX BDs", __FUNCTION__);
uccs->tx_base_offset = 0;
ucc_slow_free(uccs);
return -ENOMEM;
@@ -248,34 +229,33 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
/* Init Tx bds */
bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset);
- for (i = 0; i < us_info->tx_bd_ring_len; i++) {
+ for (i = 0; i < us_info->tx_bd_ring_len - 1; i++) {
/* clear bd buffer */
- out_be32(&(((struct qe_bd *)bd)->buf), 0);
+ out_be32(&bd->buf, 0);
/* set bd status and length */
- out_be32((u32*)bd, 0);
- bd += sizeof(struct qe_bd);
+ out_be32((u32 *) bd, 0);
+ bd++;
}
- bd -= sizeof(struct qe_bd);
- /* set bd status and length */
- out_be32((u32*)bd, T_W); /* for last BD set Wrap bit */
+ /* for last BD set Wrap bit */
+ out_be32(&bd->buf, 0);
+ out_be32((u32 *) bd, cpu_to_be32(T_W));
/* Init Rx bds */
bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset);
- for (i = 0; i < us_info->rx_bd_ring_len; i++) {
+ for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) {
/* set bd status and length */
out_be32((u32*)bd, 0);
/* clear bd buffer */
- out_be32(&(((struct qe_bd *)bd)->buf), 0);
- bd += sizeof(struct qe_bd);
+ out_be32(&bd->buf, 0);
+ bd++;
}
- bd -= sizeof(struct qe_bd);
- /* set bd status and length */
- out_be32((u32*)bd, R_W); /* for last BD set Wrap bit */
+ /* for last BD set Wrap bit */
+ out_be32((u32*)bd, cpu_to_be32(R_W));
+ out_be32(&bd->buf, 0);
/* Set GUMR (For more details see the hardware spec.). */
/* gumr_h */
- gumr = 0;
- gumr |= us_info->tcrc;
+ gumr = us_info->tcrc;
if (us_info->cdp)
gumr |= UCC_SLOW_GUMR_H_CDP;
if (us_info->ctsp)
@@ -295,7 +275,8 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
out_be32(&us_regs->gumr_h, gumr);
/* gumr_l */
- gumr = 0;
+ gumr = us_info->tdcr | us_info->rdcr | us_info->tenc | us_info->renc |
+ us_info->diag | us_info->mode;
if (us_info->tci)
gumr |= UCC_SLOW_GUMR_L_TCI;
if (us_info->rinv)
@@ -304,23 +285,14 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
gumr |= UCC_SLOW_GUMR_L_TINV;
if (us_info->tend)
gumr |= UCC_SLOW_GUMR_L_TEND;
- gumr |= us_info->tdcr;
- gumr |= us_info->rdcr;
- gumr |= us_info->tenc;
- gumr |= us_info->renc;
- gumr |= us_info->diag;
- gumr |= us_info->mode;
out_be32(&us_regs->gumr_l, gumr);
/* Function code registers */
- /* function_code has initial value 0 */
/* if the data is in cachable memory, the 'global' */
/* in the function code should be set. */
- function_code |= us_info->data_mem_part;
- function_code |= QE_BMR_BYTE_ORDER_BO_MOT; /* Required for QE */
- uccs->us_pram->tfcr = function_code;
- uccs->us_pram->rfcr = function_code;
+ uccs->us_pram->tfcr = uccs->us_pram->rfcr =
+ us_info->data_mem_part | QE_BMR_BYTE_ORDER_BO_MOT;
/* rbase, tbase are offsets from MURAM base */
out_be16(&uccs->us_pram->rbase, uccs->us_pram_offset);
@@ -336,34 +308,29 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
/* If NMSI (not Tsa), set Tx and Rx clock. */
if (!us_info->tsa) {
/* Rx clock routing */
- if (ucc_set_qe_mux_rxtx
- (us_info->ucc_num, us_info->rx_clock, COMM_DIR_RX)) {
- uccs_err
- ("ucc_slow_init: Illegal value for parameter"
- " 'RxClock'.");
+ if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->rx_clock,
+ COMM_DIR_RX)) {
+ printk(KERN_ERR "%s: illegal value for RX clock",
+ __FUNCTION__);
ucc_slow_free(uccs);
return -EINVAL;
}
/* Tx clock routing */
- if (ucc_set_qe_mux_rxtx(us_info->ucc_num,
- us_info->tx_clock, COMM_DIR_TX)) {
- uccs_err
- ("ucc_slow_init: Illegal value for parameter "
- "'TxClock'.");
+ if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->tx_clock,
+ COMM_DIR_TX)) {
+ printk(KERN_ERR "%s: illegal value for TX clock",
+ __FUNCTION__);
ucc_slow_free(uccs);
return -EINVAL;
}
}
- /*
- * INTERRUPTS
- */
/* Set interrupt mask register at UCC level. */
out_be16(&us_regs->uccm, us_info->uccm_mask);
- /* First, clear anything pending at UCC level, */
- /* otherwise, old garbage may come through */
- /* as soon as the dam is opened. */
+ /* First, clear anything pending at UCC level,
+ * otherwise, old garbage may come through
+ * as soon as the dam is opened. */
/* Writing '1' clears */
out_be16(&us_regs->ucce, 0xffff);
@@ -400,3 +367,5 @@ void ucc_slow_free(struct ucc_slow_private * uccs)
kfree(uccs);
}
+
+
diff --git a/arch/x86_64/kernel/early-quirks.c b/arch/x86_64/kernel/early-quirks.c
index bd30d138113..8047ea8c2ab 100644
--- a/arch/x86_64/kernel/early-quirks.c
+++ b/arch/x86_64/kernel/early-quirks.c
@@ -53,7 +53,9 @@ static void nvidia_bugs(void)
return;
nvidia_hpet_detected = 0;
- acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check);
+ if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check))
+ return;
+
if (nvidia_hpet_detected == 0) {
acpi_skip_timer_override = 1;
printk(KERN_INFO "Nvidia board "
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 20eacc2c9e0..e942ffe8b57 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -13,6 +13,7 @@ config ACPI
depends on IA64 || X86
depends on PCI
depends on PM
+ select PNP
default y
---help---
Advanced Configuration and Power Interface (ACPI) support for
@@ -132,15 +133,6 @@ config ACPI_VIDEO
Note that this is an ref. implementation only. It may or may not work
for your integrated video device.
-config ACPI_HOTKEY
- tristate "Generic Hotkey (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- depends on X86
- default n
- help
- Experimental consolidated hotkey driver.
- If you are unsure, say N.
-
config ACPI_FAN
tristate "Fan"
default y
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 856c32bccac..5956e9f64a8 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -46,7 +46,6 @@ obj-$(CONFIG_ACPI_FAN) += fan.o
obj-$(CONFIG_ACPI_DOCK) += dock.o
obj-$(CONFIG_ACPI_BAY) += bay.o
obj-$(CONFIG_ACPI_VIDEO) += video.o
-obj-$(CONFIG_ACPI_HOTKEY) += hotkey.o
obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
obj-$(CONFIG_ACPI_POWER) += power.o
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 6daeace796a..37c7dc4f9fe 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -35,7 +35,6 @@
#define ACPI_AC_COMPONENT 0x00020000
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_AC_HID "ACPI0003"
-#define ACPI_AC_DRIVER_NAME "ACPI AC Adapter Driver"
#define ACPI_AC_DEVICE_NAME "AC Adapter"
#define ACPI_AC_FILE_STATE "state"
#define ACPI_AC_NOTIFY_STATUS 0x80
@@ -44,10 +43,10 @@
#define ACPI_AC_STATUS_UNKNOWN 0xFF
#define _COMPONENT ACPI_AC_COMPONENT
-ACPI_MODULE_NAME("acpi_ac")
+ACPI_MODULE_NAME("ac");
- MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI AC Adapter Driver");
MODULE_LICENSE("GPL");
extern struct proc_dir_entry *acpi_lock_ac_dir(void);
@@ -58,7 +57,7 @@ static int acpi_ac_remove(struct acpi_device *device, int type);
static int acpi_ac_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_ac_driver = {
- .name = ACPI_AC_DRIVER_NAME,
+ .name = "ac",
.class = ACPI_AC_CLASS,
.ids = ACPI_AC_HID,
.ops = {
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index cd946ed192d..c26172671fd 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -35,14 +35,13 @@
#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL
#define ACPI_MEMORY_DEVICE_CLASS "memory"
#define ACPI_MEMORY_DEVICE_HID "PNP0C80"
-#define ACPI_MEMORY_DEVICE_DRIVER_NAME "Hotplug Mem Driver"
#define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device"
#define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT
-ACPI_MODULE_NAME("acpi_memory")
- MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
-MODULE_DESCRIPTION(ACPI_MEMORY_DEVICE_DRIVER_NAME);
+ACPI_MODULE_NAME("acpi_memhotplug");
+MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
+MODULE_DESCRIPTION("Hotplug Mem Driver");
MODULE_LICENSE("GPL");
/* ACPI _STA method values */
@@ -60,7 +59,7 @@ static int acpi_memory_device_remove(struct acpi_device *device, int type);
static int acpi_memory_device_start(struct acpi_device *device);
static struct acpi_driver acpi_memory_device_driver = {
- .name = ACPI_MEMORY_DEVICE_DRIVER_NAME,
+ .name = "acpi_memhotplug",
.class = ACPI_MEMORY_DEVICE_CLASS,
.ids = ACPI_MEMORY_DEVICE_HID,
.ops = {
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index 31ad70a6e22..772299fb5f9 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -141,6 +141,7 @@ struct asus_hotk {
W5A, //W5A
W3V, //W3030V
xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N
+ A4S, //Z81sp
//(Centrino)
END_MODEL
} model; //Models currently supported
@@ -397,7 +398,16 @@ static struct model_data model_conf[END_MODEL] = {
.brightness_set = "SPLV",
.brightness_get = "GPLV",
.display_set = "SDSP",
- .display_get = "\\ADVG"}
+ .display_get = "\\ADVG"},
+
+ {
+ .name = "A4S",
+ .brightness_set = "SPLV",
+ .brightness_get = "GPLV",
+ .mt_bt_switch = "BLED",
+ .mt_wled = "WLED"
+ }
+
};
/* procdir we use */
@@ -421,7 +431,7 @@ static struct asus_hotk *hotk;
static int asus_hotk_add(struct acpi_device *device);
static int asus_hotk_remove(struct acpi_device *device, int type);
static struct acpi_driver asus_hotk_driver = {
- .name = ACPI_HOTK_NAME,
+ .name = "asus_acpi",
.class = ACPI_HOTK_CLASS,
.ids = ACPI_HOTK_HID,
.ops = {
@@ -1117,6 +1127,8 @@ static int asus_model_match(char *model)
return W3V;
else if (strncmp(model, "W5A", 3) == 0)
return W5A;
+ else if (strncmp(model, "A4S", 3) == 0)
+ return A4S;
else
return END_MODEL;
}
@@ -1365,10 +1377,6 @@ static int __init asus_acpi_init(void)
if (acpi_disabled)
return -ENODEV;
- if (!acpi_specific_hotkey_enabled) {
- printk(KERN_ERR "Using generic hotkey driver\n");
- return -ENODEV;
- }
asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
if (!asus_proc_dir) {
printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n");
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 2f4521a48fe..e64c76c8b72 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -42,7 +42,6 @@
#define ACPI_BATTERY_COMPONENT 0x00040000
#define ACPI_BATTERY_CLASS "battery"
#define ACPI_BATTERY_HID "PNP0C0A"
-#define ACPI_BATTERY_DRIVER_NAME "ACPI Battery Driver"
#define ACPI_BATTERY_DEVICE_NAME "Battery"
#define ACPI_BATTERY_FILE_INFO "info"
#define ACPI_BATTERY_FILE_STATUS "state"
@@ -53,10 +52,10 @@
#define ACPI_BATTERY_UNITS_AMPS "mA"
#define _COMPONENT ACPI_BATTERY_COMPONENT
-ACPI_MODULE_NAME("acpi_battery")
+ACPI_MODULE_NAME("battery");
- MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Battery Driver");
MODULE_LICENSE("GPL");
extern struct proc_dir_entry *acpi_lock_battery_dir(void);
@@ -67,7 +66,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type);
static int acpi_battery_resume(struct acpi_device *device);
static struct acpi_driver acpi_battery_driver = {
- .name = ACPI_BATTERY_DRIVER_NAME,
+ .name = "battery",
.class = ACPI_BATTERY_CLASS,
.ids = ACPI_BATTERY_HID,
.ops = {
@@ -324,6 +323,13 @@ static int acpi_battery_check(struct acpi_battery *battery)
return result;
}
+static void acpi_battery_check_present(struct acpi_battery *battery)
+{
+ if (!battery->flags.present) {
+ acpi_battery_check(battery);
+ }
+}
+
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
@@ -340,6 +346,8 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
if (!battery)
goto end;
+ acpi_battery_check_present(battery);
+
if (battery->flags.present)
seq_printf(seq, "present: yes\n");
else {
@@ -424,6 +432,8 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
if (!battery)
goto end;
+ acpi_battery_check_present(battery);
+
if (battery->flags.present)
seq_printf(seq, "present: yes\n");
else {
@@ -499,6 +509,8 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
if (!battery)
goto end;
+ acpi_battery_check_present(battery);
+
if (!battery->flags.present) {
seq_printf(seq, "present: no\n");
goto end;
@@ -536,6 +548,8 @@ acpi_battery_write_alarm(struct file *file,
if (!battery || (count > sizeof(alarm_string) - 1))
return -EINVAL;
+ acpi_battery_check_present(battery);
+
if (!battery->flags.present)
return -ENODEV;
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
index 91082ce6f5d..fb3f31b5e69 100644
--- a/drivers/acpi/bay.c
+++ b/drivers/acpi/bay.c
@@ -32,11 +32,9 @@
#include <asm/uaccess.h>
#include <linux/platform_device.h>
-#define ACPI_BAY_DRIVER_NAME "ACPI Removable Drive Bay Driver"
-
-ACPI_MODULE_NAME("bay")
+ACPI_MODULE_NAME("bay");
MODULE_AUTHOR("Kristen Carlson Accardi");
-MODULE_DESCRIPTION(ACPI_BAY_DRIVER_NAME);
+MODULE_DESCRIPTION("ACPI Removable Drive Bay Driver");
MODULE_LICENSE("GPL");
#define ACPI_BAY_CLASS "bay"
#define ACPI_BAY_COMPONENT 0x10000000
@@ -47,18 +45,6 @@ MODULE_LICENSE("GPL");
acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); }
static void bay_notify(acpi_handle handle, u32 event, void *data);
-static int acpi_bay_add(struct acpi_device *device);
-static int acpi_bay_remove(struct acpi_device *device, int type);
-
-static struct acpi_driver acpi_bay_driver = {
- .name = ACPI_BAY_DRIVER_NAME,
- .class = ACPI_BAY_CLASS,
- .ids = ACPI_BAY_HID,
- .ops = {
- .add = acpi_bay_add,
- .remove = acpi_bay_remove,
- },
-};
struct bay {
acpi_handle handle;
@@ -234,14 +220,6 @@ int eject_removable_drive(struct device *dev)
}
EXPORT_SYMBOL_GPL(eject_removable_drive);
-static int acpi_bay_add(struct acpi_device *device)
-{
- bay_dprintk(device->handle, "adding bay device");
- strcpy(acpi_device_name(device), "Dockable Bay");
- strcpy(acpi_device_class(device), "bay");
- return 0;
-}
-
static int acpi_bay_add_fs(struct bay *bay)
{
int ret;
@@ -303,7 +281,7 @@ static int bay_add(acpi_handle handle, int id)
/* initialize platform device stuff */
pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0);
- if (pdev == NULL) {
+ if (IS_ERR(pdev)) {
printk(KERN_ERR PREFIX "Error registering bay device\n");
goto bay_add_err;
}
@@ -339,52 +317,6 @@ bay_add_err:
return -ENODEV;
}
-static int acpi_bay_remove(struct acpi_device *device, int type)
-{
- /*** FIXME: do something here */
- return 0;
-}
-
-/**
- * bay_create_acpi_device - add new devices to acpi
- * @handle - handle of the device to add
- *
- * This function will create a new acpi_device for the given
- * handle if one does not exist already. This should cause
- * acpi to scan for drivers for the given devices, and call
- * matching driver's add routine.
- *
- * Returns a pointer to the acpi_device corresponding to the handle.
- */
-static struct acpi_device * bay_create_acpi_device(acpi_handle handle)
-{
- struct acpi_device *device = NULL;
- struct acpi_device *parent_device;
- acpi_handle parent;
- int ret;
-
- bay_dprintk(handle, "Trying to get device");
- if (acpi_bus_get_device(handle, &device)) {
- /*
- * no device created for this object,
- * so we should create one.
- */
- bay_dprintk(handle, "No device for handle");
- acpi_get_parent(handle, &parent);
- if (acpi_bus_get_device(parent, &parent_device))
- parent_device = NULL;
-
- ret = acpi_bus_add(&device, parent_device, handle,
- ACPI_BUS_TYPE_DEVICE);
- if (ret) {
- pr_debug("error adding bus, %x\n",
- -ret);
- return NULL;
- }
- }
- return device;
-}
-
/**
* bay_notify - act upon an acpi bay notification
* @handle: the bay handle
@@ -394,38 +326,19 @@ static struct acpi_device * bay_create_acpi_device(acpi_handle handle)
*/
static void bay_notify(acpi_handle handle, u32 event, void *data)
{
- struct acpi_device *dev;
+ struct bay *bay_dev = (struct bay *)data;
+ struct device *dev = &bay_dev->pdev->dev;
bay_dprintk(handle, "Bay event");
switch(event) {
case ACPI_NOTIFY_BUS_CHECK:
- printk("Bus Check\n");
case ACPI_NOTIFY_DEVICE_CHECK:
- printk("Device Check\n");
- dev = bay_create_acpi_device(handle);
- if (dev)
- acpi_bus_generate_event(dev, event, 0);
- else
- printk("No device for generating event\n");
- /* wouldn't it be a good idea to just rescan SATA
- * right here?
- */
- break;
case ACPI_NOTIFY_EJECT_REQUEST:
- printk("Eject request\n");
- dev = bay_create_acpi_device(handle);
- if (dev)
- acpi_bus_generate_event(dev, event, 0);
- else
- printk("No device for generating eventn");
-
- /* wouldn't it be a good idea to just call the
- * eject_device here if we were a SATA device?
- */
+ kobject_uevent(&dev->kobj, KOBJ_CHANGE);
break;
default:
- printk("unknown event %d\n", event);
+ printk(KERN_ERR PREFIX "Bay: unknown event %d\n", event);
}
}
@@ -457,10 +370,6 @@ static int __init bay_init(void)
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, find_bay, &bays, NULL);
- if (bays)
- if ((acpi_bus_register_driver(&acpi_bay_driver) < 0))
- printk(KERN_ERR "Unable to register bay driver\n");
-
if (!bays)
return -ENODEV;
@@ -481,8 +390,6 @@ static void __exit bay_exit(void)
kfree(bay->name);
kfree(bay);
}
-
- acpi_bus_unregister_driver(&acpi_bay_driver);
}
postcore_initcall(bay_init);
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index c26468da429..dd49ea0d0ed 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -39,7 +39,7 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME("acpi_bus")
+ACPI_MODULE_NAME("bus");
#ifdef CONFIG_X86
extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
#endif
@@ -147,7 +147,7 @@ int acpi_bus_get_power(acpi_handle handle, int *state)
*state = ACPI_STATE_D0;
} else {
/*
- * Get the device's power state either directly (via _PSC) or
+ * Get the device's power state either directly (via _PSC) or
* indirectly (via power resources).
*/
if (device->power.flags.explicit_get) {
@@ -199,15 +199,14 @@ int acpi_bus_set_power(acpi_handle handle, int state)
* Get device's current power state if it's unknown
* This means device power state isn't initialized or previous setting failed
*/
- if (!device->flags.force_power_state) {
- if (device->power.state == ACPI_STATE_UNKNOWN)
- acpi_bus_get_power(device->handle, &device->power.state);
- if (state == device->power.state) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
- state));
- return 0;
- }
+ if ((device->power.state == ACPI_STATE_UNKNOWN) || device->flags.force_power_state)
+ acpi_bus_get_power(device->handle, &device->power.state);
+ if ((state == device->power.state) && !device->flags.force_power_state) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
+ state));
+ return 0;
}
+
if (!device->power.states[state].flags.valid) {
printk(KERN_WARNING PREFIX "Device does not support D%d\n", state);
return -ENODEV;
@@ -462,7 +461,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
"Received BUS CHECK notification for device [%s]\n",
device->pnp.bus_id));
result = acpi_bus_check_scope(device);
- /*
+ /*
* TBD: We'll need to outsource certain events to non-ACPI
* drivers via the device manager (device.c).
*/
@@ -473,7 +472,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
"Received DEVICE CHECK notification for device [%s]\n",
device->pnp.bus_id));
result = acpi_bus_check_device(device, NULL);
- /*
+ /*
* TBD: We'll need to outsource certain events to non-ACPI
* drivers via the device manager (device.c).
*/
@@ -543,7 +542,7 @@ static int __init acpi_bus_init_irq(void)
char *message = NULL;
- /*
+ /*
* Let the system know what interrupt model we are using by
* evaluating the \_PIC object, if exists.
*/
@@ -684,7 +683,7 @@ static int __init acpi_bus_init(void)
* the EC device is found in the namespace (i.e. before acpi_initialize_objects()
* is called).
*
- * This is accomplished by looking for the ECDT table, and getting
+ * This is accomplished by looking for the ECDT table, and getting
* the EC parameters out of that.
*/
status = acpi_ec_ecdt_probe();
@@ -699,6 +698,9 @@ static int __init acpi_bus_init(void)
printk(KERN_INFO PREFIX "Interpreter enabled\n");
+ /* Initialize sleep structures */
+ acpi_sleep_init();
+
/*
* Get the system interrupt model and evaluate \_PIC.
*/
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index c726612fafb..cb4110b50cd 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -34,7 +34,6 @@
#include <acpi/acpi_drivers.h>
#define ACPI_BUTTON_COMPONENT 0x00080000
-#define ACPI_BUTTON_DRIVER_NAME "ACPI Button Driver"
#define ACPI_BUTTON_CLASS "button"
#define ACPI_BUTTON_FILE_INFO "info"
#define ACPI_BUTTON_FILE_STATE "state"
@@ -61,10 +60,10 @@
#define ACPI_BUTTON_TYPE_LID 0x05
#define _COMPONENT ACPI_BUTTON_COMPONENT
-ACPI_MODULE_NAME("acpi_button")
+ACPI_MODULE_NAME("button");
MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
+MODULE_DESCRIPTION("ACPI Button Driver");
MODULE_LICENSE("GPL");
static int acpi_button_add(struct acpi_device *device);
@@ -73,7 +72,7 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_button_driver = {
- .name = ACPI_BUTTON_DRIVER_NAME,
+ .name = "button",
.class = ACPI_BUTTON_CLASS,
.ids = "button_power,button_sleep,PNP0C0D,PNP0C0C,PNP0C0E",
.ops = {
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
index 4a9b7bf6f44..f9db4f444bd 100644
--- a/drivers/acpi/cm_sbs.c
+++ b/drivers/acpi/cm_sbs.c
@@ -31,7 +31,7 @@
#include <acpi/actypes.h>
#include <acpi/acutils.h>
-ACPI_MODULE_NAME("cm_sbs")
+ACPI_MODULE_NAME("cm_sbs");
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_BATTERY_CLASS "battery"
#define ACPI_SBS_COMPONENT 0x00080000
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 69a68fd394c..0930d9413df 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -35,7 +35,6 @@
#include <acpi/acpi_drivers.h>
#include <acpi/container.h>
-#define ACPI_CONTAINER_DRIVER_NAME "ACPI container driver"
#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device"
#define ACPI_CONTAINER_CLASS "container"
@@ -44,10 +43,10 @@
#define ACPI_CONTAINER_COMPONENT 0x01000000
#define _COMPONENT ACPI_CONTAINER_COMPONENT
-ACPI_MODULE_NAME("acpi_container")
+ACPI_MODULE_NAME("container");
- MODULE_AUTHOR("Anil S Keshavamurthy");
-MODULE_DESCRIPTION(ACPI_CONTAINER_DRIVER_NAME);
+MODULE_AUTHOR("Anil S Keshavamurthy");
+MODULE_DESCRIPTION("ACPI container driver");
MODULE_LICENSE("GPL");
#define ACPI_STA_PRESENT (0x00000001)
@@ -56,7 +55,7 @@ static int acpi_container_add(struct acpi_device *device);
static int acpi_container_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_container_driver = {
- .name = ACPI_CONTAINER_DRIVER_NAME,
+ .name = "container",
.class = ACPI_CONTAINER_CLASS,
.ids = "ACPI0004,PNP0A05,PNP0A06",
.ops = {
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index d48f65a8f65..bf513e07b77 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -12,7 +12,7 @@
#include <acpi/acglobal.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME("debug")
+ACPI_MODULE_NAME("debug");
#ifdef MODULE_PARAM_PREFIX
#undef MODULE_PARAM_PREFIX
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 1cbe6190582..1683e5c5b94 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -231,10 +231,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
* Obtain the method mutex if necessary. Do not acquire mutex for a
* recursive call.
*/
- if (!walk_state ||
- !obj_desc->method.mutex->mutex.owner_thread ||
- (walk_state->thread !=
- obj_desc->method.mutex->mutex.owner_thread)) {
+ if (acpi_os_get_thread_id() !=
+ obj_desc->method.mutex->mutex.owner_thread_id) {
/*
* Acquire the method mutex. This releases the interpreter if we
* block (and reacquires it before it returns)
@@ -248,14 +246,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
}
/* Update the mutex and walk info and save the original sync_level */
+ obj_desc->method.mutex->mutex.owner_thread_id =
+ acpi_os_get_thread_id();
if (walk_state) {
obj_desc->method.mutex->mutex.
original_sync_level =
walk_state->thread->current_sync_level;
- obj_desc->method.mutex->mutex.owner_thread =
- walk_state->thread;
walk_state->thread->current_sync_level =
obj_desc->method.sync_level;
} else {
@@ -569,7 +567,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
acpi_os_release_mutex(method_desc->method.mutex->mutex.
os_mutex);
- method_desc->method.mutex->mutex.owner_thread = NULL;
+ method_desc->method.mutex->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
}
}
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 688e83a1690..54a697f9aa1 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -32,11 +32,11 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#define ACPI_DOCK_DRIVER_NAME "ACPI Dock Station Driver"
+#define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver"
-ACPI_MODULE_NAME("dock")
+ACPI_MODULE_NAME("dock");
MODULE_AUTHOR("Kristen Carlson Accardi");
-MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME);
+MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION);
MODULE_LICENSE("GPL");
static struct atomic_notifier_head dock_notifier_list;
@@ -741,7 +741,7 @@ static int dock_add(acpi_handle handle)
goto dock_add_err;
}
- printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_NAME);
+ printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION);
return 0;
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 743ce27fa0b..ab688837379 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -38,11 +38,10 @@
#include <acpi/actypes.h>
#define _COMPONENT ACPI_EC_COMPONENT
-ACPI_MODULE_NAME("acpi_ec")
+ACPI_MODULE_NAME("ec");
#define ACPI_EC_COMPONENT 0x00100000
#define ACPI_EC_CLASS "embedded_controller"
#define ACPI_EC_HID "PNP0C09"
-#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver"
#define ACPI_EC_DEVICE_NAME "Embedded Controller"
#define ACPI_EC_FILE_INFO "info"
#undef PREFIX
@@ -80,7 +79,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type);
static int acpi_ec_add(struct acpi_device *device);
static struct acpi_driver acpi_ec_driver = {
- .name = ACPI_EC_DRIVER_NAME,
+ .name = "ec",
.class = ACPI_EC_CLASS,
.ids = ACPI_EC_HID,
.ops = {
@@ -280,8 +279,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
mutex_lock(&ec->lock);
if (ec->global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
- if (ACPI_FAILURE(status))
+ if (ACPI_FAILURE(status)) {
+ mutex_unlock(&ec->lock);
return -ENODEV;
+ }
}
/* Make sure GPE is enabled before doing transaction */
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index 959a893c8d1..3b23562e6f9 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -13,7 +13,7 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME("event")
+ACPI_MODULE_NAME("event");
/* Global vars for handling event proc entry */
static DEFINE_SPINLOCK(acpi_system_event_lock);
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index dfac3ecc596..635ba449ebc 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -636,17 +636,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
}
}
- if (!acpi_gbl_system_awake_and_running) {
- /*
- * We just woke up because of a wake GPE. Disable any further GPEs
- * until we are fully up and running (Only wake GPEs should be enabled
- * at this time, but we just brute-force disable them all.)
- * 1) We must disable this particular wake GPE so it won't fire again
- * 2) We want to disable all wake GPEs, since we are now awake
- */
- (void)acpi_hw_disable_all_gpes();
- }
-
/*
* Dispatch the GPE to either an installed handler, or the control method
* associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 1b784ffe54c..d572700197f 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -196,12 +196,11 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
notify_info->notify.value = (u16) notify_value;
notify_info->notify.handler_obj = handler_obj;
- status =
- acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
- notify_info);
- if (ACPI_FAILURE(status)) {
- acpi_ut_delete_generic_state(notify_info);
- }
+ acpi_ex_relinquish_interpreter();
+
+ acpi_ev_notify_dispatch(notify_info);
+
+ acpi_ex_reacquire_interpreter();
}
if (!handler_obj) {
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index 68d283fd60e..1a73c14df2c 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -134,7 +134,7 @@ static struct acpi_exdump_info acpi_ex_dump_method[8] = {
static struct acpi_exdump_info acpi_ex_dump_mutex[5] = {
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL},
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"},
- {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread_id), "Owner Thread"},
{ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth),
"Acquire Depth"},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"}
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index 5101bad5baf..4eb883bda6a 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -66,10 +66,9 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc,
*
******************************************************************************/
-void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc,
+ struct acpi_thread_state *thread)
{
- struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
-
if (!thread) {
return;
}
@@ -174,16 +173,13 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
/* Support for multiple acquires by the owning thread */
- if (obj_desc->mutex.owner_thread) {
- if (obj_desc->mutex.owner_thread->thread_id ==
- walk_state->thread->thread_id) {
- /*
- * The mutex is already owned by this thread, just increment the
- * acquisition depth
- */
- obj_desc->mutex.acquisition_depth++;
- return_ACPI_STATUS(AE_OK);
- }
+ if (obj_desc->mutex.owner_thread_id == acpi_os_get_thread_id()) {
+ /*
+ * The mutex is already owned by this thread, just increment the
+ * acquisition depth
+ */
+ obj_desc->mutex.acquisition_depth++;
+ return_ACPI_STATUS(AE_OK);
}
/* Acquire the mutex, wait if necessary. Special case for Global Lock */
@@ -206,7 +202,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc,
/* Have the mutex: update mutex and walk info and save the sync_level */
- obj_desc->mutex.owner_thread = walk_state->thread;
+ obj_desc->mutex.owner_thread_id = acpi_os_get_thread_id();
obj_desc->mutex.acquisition_depth = 1;
obj_desc->mutex.original_sync_level =
walk_state->thread->current_sync_level;
@@ -246,7 +242,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
/* The mutex must have been previously acquired in order to release it */
- if (!obj_desc->mutex.owner_thread) {
+ if (!obj_desc->mutex.owner_thread_id) {
ACPI_ERROR((AE_INFO,
"Cannot release Mutex [%4.4s], not acquired",
acpi_ut_get_node_name(obj_desc->mutex.node)));
@@ -266,14 +262,14 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
* The Mutex is owned, but this thread must be the owner.
* Special case for Global Lock, any thread can release
*/
- if ((obj_desc->mutex.owner_thread->thread_id !=
+ if ((obj_desc->mutex.owner_thread_id !=
walk_state->thread->thread_id)
&& (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) {
ACPI_ERROR((AE_INFO,
"Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
(unsigned long)walk_state->thread->thread_id,
acpi_ut_get_node_name(obj_desc->mutex.node),
- (unsigned long)obj_desc->mutex.owner_thread->thread_id));
+ (unsigned long)obj_desc->mutex.owner_thread_id));
return_ACPI_STATUS(AE_AML_NOT_OWNER);
}
@@ -300,7 +296,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
/* Unlink the mutex from the owner's list */
- acpi_ex_unlink_mutex(obj_desc);
+ acpi_ex_unlink_mutex(obj_desc, walk_state->thread);
/* Release the mutex, special case for Global Lock */
@@ -312,7 +308,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
/* Update the mutex and restore sync_level */
- obj_desc->mutex.owner_thread = NULL;
+ obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
walk_state->thread->current_sync_level =
obj_desc->mutex.original_sync_level;
@@ -367,7 +363,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
/* Mark mutex unowned */
- obj_desc->mutex.owner_thread = NULL;
+ obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
/* Update Thread sync_level (Last mutex is the important one) */
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index af22fdf7341..ec655c53949 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -36,14 +36,13 @@
#define ACPI_FAN_COMPONENT 0x00200000
#define ACPI_FAN_CLASS "fan"
-#define ACPI_FAN_DRIVER_NAME "ACPI Fan Driver"
#define ACPI_FAN_FILE_STATE "state"
#define _COMPONENT ACPI_FAN_COMPONENT
-ACPI_MODULE_NAME("acpi_fan")
+ACPI_MODULE_NAME("fan");
- MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Fan Driver");
MODULE_LICENSE("GPL");
static int acpi_fan_add(struct acpi_device *device);
@@ -52,7 +51,7 @@ static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state);
static int acpi_fan_resume(struct acpi_device *device);
static struct acpi_driver acpi_fan_driver = {
- .name = ACPI_FAN_DRIVER_NAME,
+ .name = "fan",
.class = ACPI_FAN_CLASS,
.ids = "PNP0C0B",
.ops = {
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 7b6c9ff9beb..4334c208841 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -241,3 +241,65 @@ static int __init init_acpi_device_notify(void)
}
arch_initcall(init_acpi_device_notify);
+
+
+#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
+
+/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find
+ * its device node and pass extra config data. This helps its driver use
+ * capabilities that the now-obsolete mc146818 didn't have, and informs it
+ * that this board's RTC is wakeup-capable (per ACPI spec).
+ */
+#include <linux/mc146818rtc.h>
+
+static struct cmos_rtc_board_info rtc_info;
+
+
+/* PNP devices are registered in a subsys_initcall();
+ * ACPI specifies the PNP IDs to use.
+ */
+#include <linux/pnp.h>
+
+static int __init pnp_match(struct device *dev, void *data)
+{
+ static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", };
+ struct pnp_dev *pnp = to_pnp_dev(dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ids); i++) {
+ if (compare_pnp_id(pnp->id, ids[i]) != 0)
+ return 1;
+ }
+ return 0;
+}
+
+static struct device *__init get_rtc_dev(void)
+{
+ return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match);
+}
+
+static int __init acpi_rtc_init(void)
+{
+ struct device *dev = get_rtc_dev();
+
+ if (dev) {
+ rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm;
+ rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm;
+ rtc_info.rtc_century = acpi_gbl_FADT.century;
+
+ /* NOTE: acpi_gbl_FADT->rtcs4 is NOT currently useful */
+
+ dev->platform_data = &rtc_info;
+
+ /* RTC always wakes from S1/S2/S3, and often S4/STD */
+ device_init_wakeup(dev, 1);
+
+ put_device(dev);
+ } else
+ pr_debug("ACPI: RTC unavailable?\n");
+ return 0;
+}
+/* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */
+fs_initcall(acpi_rtc_init);
+
+#endif
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 57901ca3ade..8fa93125fd4 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -235,6 +235,14 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
"While executing method _SST"));
}
+ /*
+ * 1) Disable/Clear all GPEs
+ */
+ status = acpi_hw_disable_all_gpes();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
return_ACPI_STATUS(AE_OK);
}
@@ -290,13 +298,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
}
/*
- * 1) Disable/Clear all GPEs
* 2) Enable all wakeup GPEs
*/
- status = acpi_hw_disable_all_gpes();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
acpi_gbl_system_awake_and_running = FALSE;
status = acpi_hw_enable_all_wakeup_gpes();
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c
deleted file mode 100644
index 8edfb92f7ed..00000000000
--- a/drivers/acpi/hotkey.c
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- * hotkey.c - ACPI Hotkey Driver ($Revision: 0.2 $)
- *
- * Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/sched.h>
-#include <linux/kmod.h>
-#include <linux/seq_file.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
-#include <asm/uaccess.h>
-
-#define HOTKEY_ACPI_VERSION "0.1"
-
-#define HOTKEY_PROC "hotkey"
-#define HOTKEY_EV_CONFIG "event_config"
-#define HOTKEY_PL_CONFIG "poll_config"
-#define HOTKEY_ACTION "action"
-#define HOTKEY_INFO "info"
-
-#define ACPI_HOTK_NAME "Generic Hotkey Driver"
-#define ACPI_HOTK_CLASS "Hotkey"
-#define ACPI_HOTK_DEVICE_NAME "Hotkey"
-#define ACPI_HOTK_HID "Unknown?"
-#define ACPI_HOTKEY_COMPONENT 0x20000000
-
-#define ACPI_HOTKEY_EVENT 0x1
-#define ACPI_HOTKEY_POLLING 0x2
-#define ACPI_UNDEFINED_EVENT 0xf
-
-#define RESULT_STR_LEN 80
-
-#define ACTION_METHOD 0
-#define POLL_METHOD 1
-
-#define IS_EVENT(e) ((e) <= 10000 && (e) >0)
-#define IS_POLL(e) ((e) > 10000)
-#define IS_OTHERS(e) ((e)<=0 || (e)>=20000)
-#define _COMPONENT ACPI_HOTKEY_COMPONENT
-ACPI_MODULE_NAME("acpi_hotkey")
-
- MODULE_AUTHOR("luming.yu@intel.com");
-MODULE_DESCRIPTION(ACPI_HOTK_NAME);
-MODULE_LICENSE("GPL");
-
-/* standardized internal hotkey number/event */
-enum {
- /* Video Extension event */
- HK_EVENT_CYCLE_OUTPUT_DEVICE = 0x80,
- HK_EVENT_OUTPUT_DEVICE_STATUS_CHANGE,
- HK_EVENT_CYCLE_DISPLAY_OUTPUT,
- HK_EVENT_NEXT_DISPLAY_OUTPUT,
- HK_EVENT_PREVIOUS_DISPLAY_OUTPUT,
- HK_EVENT_CYCLE_BRIGHTNESS,
- HK_EVENT_INCREASE_BRIGHTNESS,
- HK_EVENT_DECREASE_BRIGHTNESS,
- HK_EVENT_ZERO_BRIGHTNESS,
- HK_EVENT_DISPLAY_DEVICE_OFF,
-
- /* Snd Card event */
- HK_EVENT_VOLUME_MUTE,
- HK_EVENT_VOLUME_INCLREASE,
- HK_EVENT_VOLUME_DECREASE,
-
- /* running state control */
- HK_EVENT_ENTERRING_S3,
- HK_EVENT_ENTERRING_S4,
- HK_EVENT_ENTERRING_S5,
-};
-
-enum conf_entry_enum {
- bus_handle = 0,
- bus_method = 1,
- action_handle = 2,
- method = 3,
- LAST_CONF_ENTRY
-};
-
-/* procdir we use */
-static struct proc_dir_entry *hotkey_proc_dir;
-static struct proc_dir_entry *hotkey_config;
-static struct proc_dir_entry *hotkey_poll_config;
-static struct proc_dir_entry *hotkey_action;
-static struct proc_dir_entry *hotkey_info;
-
-/* linkage for all type of hotkey */
-struct acpi_hotkey_link {
- struct list_head entries;
- int hotkey_type; /* event or polling based hotkey */
- int hotkey_standard_num; /* standardized hotkey(event) number */
-};
-
-/* event based hotkey */
-struct acpi_event_hotkey {
- struct acpi_hotkey_link hotkey_link;
- int flag;
- acpi_handle bus_handle; /* bus to install notify handler */
- int external_hotkey_num; /* external hotkey/event number */
- acpi_handle action_handle; /* acpi handle attached aml action method */
- char *action_method; /* action method */
-};
-
-/*
- * There are two ways to poll status
- * 1. directy call read_xxx method, without any arguments passed in
- * 2. call write_xxx method, with arguments passed in, you need
- * the result is saved in acpi_polling_hotkey.poll_result.
- * anthoer read command through polling interface.
- *
- */
-
-/* polling based hotkey */
-struct acpi_polling_hotkey {
- struct acpi_hotkey_link hotkey_link;
- int flag;
- acpi_handle poll_handle; /* acpi handle attached polling method */
- char *poll_method; /* poll method */
- acpi_handle action_handle; /* acpi handle attached action method */
- char *action_method; /* action method */
- union acpi_object *poll_result; /* polling_result */
- struct proc_dir_entry *proc;
-};
-
-/* hotkey object union */
-union acpi_hotkey {
- struct list_head entries;
- struct acpi_hotkey_link link;
- struct acpi_event_hotkey event_hotkey;
- struct acpi_polling_hotkey poll_hotkey;
-};
-
-/* hotkey object list */
-struct acpi_hotkey_list {
- struct list_head *entries;
- int count;
-};
-
-static int auto_hotkey_add(struct acpi_device *device);
-static int auto_hotkey_remove(struct acpi_device *device, int type);
-
-static struct acpi_driver hotkey_driver = {
- .name = ACPI_HOTK_NAME,
- .class = ACPI_HOTK_CLASS,
- .ids = ACPI_HOTK_HID,
- .ops = {
- .add = auto_hotkey_add,
- .remove = auto_hotkey_remove,
- },
-};
-
-static void free_hotkey_device(union acpi_hotkey *key);
-static void free_hotkey_buffer(union acpi_hotkey *key);
-static void free_poll_hotkey_buffer(union acpi_hotkey *key);
-static int hotkey_open_config(struct inode *inode, struct file *file);
-static int hotkey_poll_open_config(struct inode *inode, struct file *file);
-static ssize_t hotkey_write_config(struct file *file,
- const char __user * buffer,
- size_t count, loff_t * data);
-static int hotkey_info_open_fs(struct inode *inode, struct file *file);
-static int hotkey_action_open_fs(struct inode *inode, struct file *file);
-static ssize_t hotkey_execute_aml_method(struct file *file,
- const char __user * buffer,
- size_t count, loff_t * data);
-static int hotkey_config_seq_show(struct seq_file *seq, void *offset);
-static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset);
-static int hotkey_polling_open_fs(struct inode *inode, struct file *file);
-static union acpi_hotkey *get_hotkey_by_event(struct
- acpi_hotkey_list
- *hotkey_list, int event);
-
-/* event based config */
-static const struct file_operations hotkey_config_fops = {
- .open = hotkey_open_config,
- .read = seq_read,
- .write = hotkey_write_config,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-/* polling based config */
-static const struct file_operations hotkey_poll_config_fops = {
- .open = hotkey_poll_open_config,
- .read = seq_read,
- .write = hotkey_write_config,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-/* hotkey driver info */
-static const struct file_operations hotkey_info_fops = {
- .open = hotkey_info_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-/* action */
-static const struct file_operations hotkey_action_fops = {
- .open = hotkey_action_open_fs,
- .read = seq_read,
- .write = hotkey_execute_aml_method,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-/* polling results */
-static const struct file_operations hotkey_polling_fops = {
- .open = hotkey_polling_open_fs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-struct acpi_hotkey_list global_hotkey_list; /* link all ev or pl hotkey */
-struct list_head hotkey_entries; /* head of the list of hotkey_list */
-
-static int hotkey_info_seq_show(struct seq_file *seq, void *offset)
-{
-
- seq_printf(seq, "Hotkey generic driver ver: %s\n", HOTKEY_ACPI_VERSION);
-
- return 0;
-}
-
-static int hotkey_info_open_fs(struct inode *inode, struct file *file)
-{
- return single_open(file, hotkey_info_seq_show, PDE(inode)->data);
-}
-
-static char *format_result(union acpi_object *object)
-{
- char *buf;
-
- buf = kzalloc(RESULT_STR_LEN, GFP_KERNEL);
- if (!buf)
- return NULL;
- /* Now, just support integer type */
- if (object->type == ACPI_TYPE_INTEGER)
- sprintf(buf, "%d\n", (u32) object->integer.value);
- return buf;
-}
-
-static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
-{
- struct acpi_polling_hotkey *poll_hotkey = seq->private;
- char *buf;
-
-
- if (poll_hotkey->poll_result) {
- buf = format_result(poll_hotkey->poll_result);
- if (buf)
- seq_printf(seq, "%s", buf);
- kfree(buf);
- }
- return 0;
-}
-
-static int hotkey_polling_open_fs(struct inode *inode, struct file *file)
-{
- return single_open(file, hotkey_polling_seq_show, PDE(inode)->data);
-}
-
-static int hotkey_action_open_fs(struct inode *inode, struct file *file)
-{
- return single_open(file, hotkey_info_seq_show, PDE(inode)->data);
-}
-
-/* Mapping external hotkey number to standardized hotkey event num */
-static int hotkey_get_internal_event(int event, struct acpi_hotkey_list *list)
-{
- struct list_head *entries;
- int val = -1;
-
-
- list_for_each(entries, list->entries) {
- union acpi_hotkey *key =
- container_of(entries, union acpi_hotkey, entries);
- if (key->link.hotkey_type == ACPI_HOTKEY_EVENT
- && key->event_hotkey.external_hotkey_num == event) {
- val = key->link.hotkey_standard_num;
- break;
- }
- }
-
- return val;
-}
-
-static void
-acpi_hotkey_notify_handler(acpi_handle handle, u32 event, void *data)
-{
- struct acpi_device *device = NULL;
- u32 internal_event;
-
-
- if (acpi_bus_get_device(handle, &device))
- return;
-
- internal_event = hotkey_get_internal_event(event, &global_hotkey_list);
- acpi_bus_generate_event(device, internal_event, 0);
-
- return;
-}
-
-/* Need to invent automatically hotkey add method */
-static int auto_hotkey_add(struct acpi_device *device)
-{
- /* Implement me */
- return 0;
-}
-
-/* Need to invent automatically hotkey remove method */
-static int auto_hotkey_remove(struct acpi_device *device, int type)
-{
- /* Implement me */
- return 0;
-}
-
-/* Create a proc file for each polling method */
-static int create_polling_proc(union acpi_hotkey *device)
-{
- struct proc_dir_entry *proc;
- char proc_name[80];
- mode_t mode;
-
- mode = S_IFREG | S_IRUGO | S_IWUGO;
-
- sprintf(proc_name, "%d", device->link.hotkey_standard_num);
- /*
- strcat(proc_name, device->poll_hotkey.poll_method);
- */
- proc = create_proc_entry(proc_name, mode, hotkey_proc_dir);
-
- if (!proc) {
- return -ENODEV;
- } else {
- proc->proc_fops = &hotkey_polling_fops;
- proc->owner = THIS_MODULE;
- proc->data = device;
- proc->uid = 0;
- proc->gid = 0;
- device->poll_hotkey.proc = proc;
- }
- return 0;
-}
-
-static int hotkey_add(union acpi_hotkey *device)
-{
- int status = 0;
- struct acpi_device *dev = NULL;
-
-
- if (device->link.hotkey_type == ACPI_HOTKEY_EVENT) {
- acpi_bus_get_device(device->event_hotkey.bus_handle, &dev);
- status = acpi_install_notify_handler(dev->handle,
- ACPI_DEVICE_NOTIFY,
- acpi_hotkey_notify_handler,
- dev);
- } else /* Add polling hotkey */
- create_polling_proc(device);
-
- global_hotkey_list.count++;
-
- list_add_tail(&device->link.entries, global_hotkey_list.entries);
-
- return status;
-}
-
-static int hotkey_remove(union acpi_hotkey *device)
-{
- struct list_head *entries, *next;
-
-
- list_for_each_safe(entries, next, global_hotkey_list.entries) {
- union acpi_hotkey *key =
- container_of(entries, union acpi_hotkey, entries);
- if (key->link.hotkey_standard_num ==
- device->link.hotkey_standard_num) {
- list_del(&key->link.entries);
- free_hotkey_device(key);
- global_hotkey_list.count--;
- break;
- }
- }
- kfree(device);
- return 0;
-}
-
-static int hotkey_update(union acpi_hotkey *key)
-{
- struct list_head *entries;
-
-
- list_for_each(entries, global_hotkey_list.entries) {
- union acpi_hotkey *tmp =
- container_of(entries, union acpi_hotkey, entries);
- if (tmp->link.hotkey_standard_num ==
- key->link.hotkey_standard_num) {
- if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
- free_hotkey_buffer(tmp);
- tmp->event_hotkey.bus_handle =
- key->event_hotkey.bus_handle;
- tmp->event_hotkey.external_hotkey_num =
- key->event_hotkey.external_hotkey_num;
- tmp->event_hotkey.action_handle =
- key->event_hotkey.action_handle;
- tmp->event_hotkey.action_method =
- key->event_hotkey.action_method;
- kfree(key);
- } else {
- /*
- char proc_name[80];
-
- sprintf(proc_name, "%d", tmp->link.hotkey_standard_num);
- strcat(proc_name, tmp->poll_hotkey.poll_method);
- remove_proc_entry(proc_name,hotkey_proc_dir);
- */
- free_poll_hotkey_buffer(tmp);
- tmp->poll_hotkey.poll_handle =
- key->poll_hotkey.poll_handle;
- tmp->poll_hotkey.poll_method =
- key->poll_hotkey.poll_method;
- tmp->poll_hotkey.action_handle =
- key->poll_hotkey.action_handle;
- tmp->poll_hotkey.action_method =
- key->poll_hotkey.action_method;
- tmp->poll_hotkey.poll_result =
- key->poll_hotkey.poll_result;
- /*
- create_polling_proc(tmp);
- */
- kfree(key);
- }
- return 0;
- break;
- }
- }
-
- return -ENODEV;
-}
-
-static void free_hotkey_device(union acpi_hotkey *key)
-{
- struct acpi_device *dev;
-
-
- if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
- acpi_bus_get_device(key->event_hotkey.bus_handle, &dev);
- if (dev->handle)
- acpi_remove_notify_handler(dev->handle,
- ACPI_DEVICE_NOTIFY,
- acpi_hotkey_notify_handler);
- free_hotkey_buffer(key);
- } else {
- char proc_name[80];
-
- sprintf(proc_name, "%d", key->link.hotkey_standard_num);
- /*
- strcat(proc_name, key->poll_hotkey.poll_method);
- */
- remove_proc_entry(proc_name, hotkey_proc_dir);
- free_poll_hotkey_buffer(key);
- }
- kfree(key);
- return;
-}
-
-static void free_hotkey_buffer(union acpi_hotkey *key)
-{
- /* key would never be null, action method could be */
- kfree(key->event_hotkey.action_method);
-}
-
-static void free_poll_hotkey_buffer(union acpi_hotkey *key)
-{
- /* key would never be null, others could be*/
- kfree(key->poll_hotkey.action_method);
- kfree(key->poll_hotkey.poll_method);
- kfree(key->poll_hotkey.poll_result);
-}
-static int
-init_hotkey_device(union acpi_hotkey *key, char **config_entry,
- int std_num, int external_num)
-{
- acpi_handle tmp_handle;
- acpi_status status = AE_OK;
-
- if (std_num < 0 || IS_POLL(std_num) || !key)
- goto do_fail;
-
- if (!config_entry[bus_handle] || !config_entry[action_handle]
- || !config_entry[method])
- goto do_fail;
-
- key->link.hotkey_type = ACPI_HOTKEY_EVENT;
- key->link.hotkey_standard_num = std_num;
- key->event_hotkey.flag = 0;
- key->event_hotkey.action_method = config_entry[method];
-
- status = acpi_get_handle(NULL, config_entry[bus_handle],
- &(key->event_hotkey.bus_handle));
- if (ACPI_FAILURE(status))
- goto do_fail_zero;
- key->event_hotkey.external_hotkey_num = external_num;
- status = acpi_get_handle(NULL, config_entry[action_handle],
- &(key->event_hotkey.action_handle));
- if (ACPI_FAILURE(status))
- goto do_fail_zero;
- status = acpi_get_handle(key->event_hotkey.action_handle,
- config_entry[method], &tmp_handle);
- if (ACPI_FAILURE(status))
- goto do_fail_zero;
- return AE_OK;
-do_fail_zero:
- key->event_hotkey.action_method = NULL;
-do_fail:
- return -ENODEV;
-}
-
-static int
-init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry,
- int std_num)
-{
- acpi_status status = AE_OK;
- acpi_handle tmp_handle;
-
- if (std_num < 0 || IS_EVENT(std_num) || !key)
- goto do_fail;
- if (!config_entry[bus_handle] ||!config_entry[bus_method] ||
- !config_entry[action_handle] || !config_entry[method])
- goto do_fail;
-
- key->link.hotkey_type = ACPI_HOTKEY_POLLING;
- key->link.hotkey_standard_num = std_num;
- key->poll_hotkey.flag = 0;
- key->poll_hotkey.poll_method = config_entry[bus_method];
- key->poll_hotkey.action_method = config_entry[method];
-
- status = acpi_get_handle(NULL, config_entry[bus_handle],
- &(key->poll_hotkey.poll_handle));
- if (ACPI_FAILURE(status))
- goto do_fail_zero;
- status = acpi_get_handle(key->poll_hotkey.poll_handle,
- config_entry[bus_method], &tmp_handle);
- if (ACPI_FAILURE(status))
- goto do_fail_zero;
- status =
- acpi_get_handle(NULL, config_entry[action_handle],
- &(key->poll_hotkey.action_handle));
- if (ACPI_FAILURE(status))
- goto do_fail_zero;
- status = acpi_get_handle(key->poll_hotkey.action_handle,
- config_entry[method], &tmp_handle);
- if (ACPI_FAILURE(status))
- goto do_fail_zero;
- key->poll_hotkey.poll_result =
- kmalloc(sizeof(union acpi_object), GFP_KERNEL);
- if (!key->poll_hotkey.poll_result)
- goto do_fail_zero;
- return AE_OK;
-
-do_fail_zero:
- key->poll_hotkey.poll_method = NULL;
- key->poll_hotkey.action_method = NULL;
-do_fail:
- return -ENODEV;
-}
-
-static int hotkey_open_config(struct inode *inode, struct file *file)
-{
- return (single_open
- (file, hotkey_config_seq_show, PDE(inode)->data));
-}
-
-static int hotkey_poll_open_config(struct inode *inode, struct file *file)
-{
- return (single_open
- (file, hotkey_poll_config_seq_show, PDE(inode)->data));
-}
-
-static int hotkey_config_seq_show(struct seq_file *seq, void *offset)
-{
- struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
- struct list_head *entries;
- char bus_name[ACPI_PATHNAME_MAX] = { 0 };
- char action_name[ACPI_PATHNAME_MAX] = { 0 };
- struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name };
- struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name };
-
-
- list_for_each(entries, hotkey_list->entries) {
- union acpi_hotkey *key =
- container_of(entries, union acpi_hotkey, entries);
- if (key->link.hotkey_type == ACPI_HOTKEY_EVENT) {
- acpi_get_name(key->event_hotkey.bus_handle,
- ACPI_NAME_TYPE_MAX, &bus);
- acpi_get_name(key->event_hotkey.action_handle,
- ACPI_NAME_TYPE_MAX, &act);
- seq_printf(seq, "%s:%s:%s:%d:%d\n", bus_name,
- action_name,
- key->event_hotkey.action_method,
- key->link.hotkey_standard_num,
- key->event_hotkey.external_hotkey_num);
- }
- }
- seq_puts(seq, "\n");
- return 0;
-}
-
-static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset)
-{
- struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
- struct list_head *entries;
- char bus_name[ACPI_PATHNAME_MAX] = { 0 };
- char action_name[ACPI_PATHNAME_MAX] = { 0 };
- struct acpi_buffer bus = { ACPI_PATHNAME_MAX, bus_name };
- struct acpi_buffer act = { ACPI_PATHNAME_MAX, action_name };
-
-
- list_for_each(entries, hotkey_list->entries) {
- union acpi_hotkey *key =
- container_of(entries, union acpi_hotkey, entries);
- if (key->link.hotkey_type == ACPI_HOTKEY_POLLING) {
- acpi_get_name(key->poll_hotkey.poll_handle,
- ACPI_NAME_TYPE_MAX, &bus);
- acpi_get_name(key->poll_hotkey.action_handle,
- ACPI_NAME_TYPE_MAX, &act);
- seq_printf(seq, "%s:%s:%s:%s:%d\n", bus_name,
- key->poll_hotkey.poll_method,
- action_name,
- key->poll_hotkey.action_method,
- key->link.hotkey_standard_num);
- }
- }
- seq_puts(seq, "\n");
- return 0;
-}
-
-static int
-get_parms(char *config_record, int *cmd, char **config_entry,
- int *internal_event_num, int *external_event_num)
-{
-/* the format of *config_record =
- * "1:\d+:*" : "cmd:internal_event_num"
- * "\d+:\w+:\w+:\w+:\w+:\d+:\d+" :
- * "cmd:bus_handle:bus_method:action_handle:method:internal_event_num:external_event_num"
- */
- char *tmp, *tmp1, count;
- int i;
-
- sscanf(config_record, "%d", cmd);
- if (*cmd == 1) {
- if (sscanf(config_record, "%d:%d", cmd, internal_event_num) !=
- 2)
- goto do_fail;
- else
- return (6);
- }
- tmp = strchr(config_record, ':');
- if (!tmp)
- goto do_fail;
- tmp++;
- for (i = 0; i < LAST_CONF_ENTRY; i++) {
- tmp1 = strchr(tmp, ':');
- if (!tmp1) {
- goto do_fail;
- }
- count = tmp1 - tmp;
- config_entry[i] = kzalloc(count + 1, GFP_KERNEL);
- if (!config_entry[i])
- goto handle_failure;
- strncpy(config_entry[i], tmp, count);
- tmp = tmp1 + 1;
- }
- if (sscanf(tmp, "%d:%d", internal_event_num, external_event_num) <= 0)
- goto handle_failure;
- if (!IS_OTHERS(*internal_event_num)) {
- return 6;
- }
-handle_failure:
- while (i-- > 0)
- kfree(config_entry[i]);
-do_fail:
- return -1;
-}
-
-/* count is length for one input record */
-static ssize_t hotkey_write_config(struct file *file,
- const char __user * buffer,
- size_t count, loff_t * data)
-{
- char *config_record = NULL;
- char *config_entry[LAST_CONF_ENTRY];
- int cmd, internal_event_num, external_event_num;
- int ret = 0;
- union acpi_hotkey *key = kzalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
-
- if (!key)
- return -ENOMEM;
-
- config_record = kzalloc(count + 1, GFP_KERNEL);
- if (!config_record) {
- kfree(key);
- return -ENOMEM;
- }
-
- if (copy_from_user(config_record, buffer, count)) {
- kfree(config_record);
- kfree(key);
- printk(KERN_ERR PREFIX "Invalid data\n");
- return -EINVAL;
- }
- ret = get_parms(config_record, &cmd, config_entry,
- &internal_event_num, &external_event_num);
- kfree(config_record);
- if (ret != 6) {
- printk(KERN_ERR PREFIX "Invalid data format ret=%d\n", ret);
- return -EINVAL;
- }
-
- if (cmd == 1) {
- union acpi_hotkey *tmp = NULL;
- tmp = get_hotkey_by_event(&global_hotkey_list,
- internal_event_num);
- if (!tmp)
- printk(KERN_ERR PREFIX "Invalid key\n");
- else
- memcpy(key, tmp, sizeof(union acpi_hotkey));
- goto cont_cmd;
- }
- if (IS_EVENT(internal_event_num)) {
- if (init_hotkey_device(key, config_entry,
- internal_event_num, external_event_num))
- goto init_hotkey_fail;
- } else {
- if (init_poll_hotkey_device(key, config_entry,
- internal_event_num))
- goto init_poll_hotkey_fail;
- }
-cont_cmd:
- switch (cmd) {
- case 0:
- if (get_hotkey_by_event(&global_hotkey_list,
- key->link.hotkey_standard_num))
- goto fail_out;
- else
- hotkey_add(key);
- break;
- case 1:
- hotkey_remove(key);
- break;
- case 2:
- /* key is kfree()ed if matched*/
- if (hotkey_update(key))
- goto fail_out;
- break;
- default:
- goto fail_out;
- break;
- }
- return count;
-
-init_poll_hotkey_fail: /* failed init_poll_hotkey_device */
- kfree(config_entry[bus_method]);
- config_entry[bus_method] = NULL;
-init_hotkey_fail: /* failed init_hotkey_device */
- kfree(config_entry[method]);
-fail_out:
- kfree(config_entry[bus_handle]);
- kfree(config_entry[action_handle]);
- /* No double free since elements =NULL for error cases */
- if (IS_EVENT(internal_event_num)) {
- if (config_entry[bus_method])
- kfree(config_entry[bus_method]);
- free_hotkey_buffer(key); /* frees [method] */
- } else
- free_poll_hotkey_buffer(key); /* frees [bus_method]+[method] */
- kfree(key);
- printk(KERN_ERR PREFIX "invalid key\n");
- return -EINVAL;
-}
-
-/*
- * This function evaluates an ACPI method, given an int as parameter, the
- * method is searched within the scope of the handle, can be NULL. The output
- * of the method is written is output, which can also be NULL
- *
- * returns 1 if write is successful, 0 else.
- */
-static int write_acpi_int(acpi_handle handle, const char *method, int val,
- struct acpi_buffer *output)
-{
- struct acpi_object_list params; /* list of input parameters (an int here) */
- union acpi_object in_obj; /* the only param we use */
- acpi_status status;
-
- params.count = 1;
- params.pointer = &in_obj;
- in_obj.type = ACPI_TYPE_INTEGER;
- in_obj.integer.value = val;
-
- status = acpi_evaluate_object(handle, (char *)method, &params, output);
-
- return (status == AE_OK);
-}
-
-static int read_acpi_int(acpi_handle handle, const char *method,
- union acpi_object *val)
-{
- struct acpi_buffer output;
- union acpi_object out_obj;
- acpi_status status;
-
- output.length = sizeof(out_obj);
- output.pointer = &out_obj;
-
- status = acpi_evaluate_object(handle, (char *)method, NULL, &output);
- if (val) {
- val->integer.value = out_obj.integer.value;
- val->type = out_obj.type;
- } else
- printk(KERN_ERR PREFIX "null val pointer\n");
- return ((status == AE_OK)
- && (out_obj.type == ACPI_TYPE_INTEGER));
-}
-
-static union acpi_hotkey *get_hotkey_by_event(struct
- acpi_hotkey_list
- *hotkey_list, int event)
-{
- struct list_head *entries;
-
- list_for_each(entries, hotkey_list->entries) {
- union acpi_hotkey *key =
- container_of(entries, union acpi_hotkey, entries);
- if (key->link.hotkey_standard_num == event) {
- return (key);
- }
- }
- return (NULL);
-}
-
-/*
- * user call AML method interface:
- * Call convention:
- * echo "event_num: arg type : value"
- * example: echo "1:1:30" > /proc/acpi/action
- * Just support 1 integer arg passing to AML method
- */
-
-static ssize_t hotkey_execute_aml_method(struct file *file,
- const char __user * buffer,
- size_t count, loff_t * data)
-{
- struct acpi_hotkey_list *hotkey_list = &global_hotkey_list;
- char *arg;
- int event, method_type, type, value;
- union acpi_hotkey *key;
-
-
- arg = kzalloc(count + 1, GFP_KERNEL);
- if (!arg)
- return -ENOMEM;
-
- if (copy_from_user(arg, buffer, count)) {
- kfree(arg);
- printk(KERN_ERR PREFIX "Invalid argument 2\n");
- return -EINVAL;
- }
-
- if (sscanf(arg, "%d:%d:%d:%d", &event, &method_type, &type, &value) !=
- 4) {
- kfree(arg);
- printk(KERN_ERR PREFIX "Invalid argument 3\n");
- return -EINVAL;
- }
- kfree(arg);
- if (type == ACPI_TYPE_INTEGER) {
- key = get_hotkey_by_event(hotkey_list, event);
- if (!key)
- goto do_fail;
- if (IS_EVENT(event))
- write_acpi_int(key->event_hotkey.action_handle,
- key->event_hotkey.action_method, value,
- NULL);
- else if (IS_POLL(event)) {
- if (method_type == POLL_METHOD)
- read_acpi_int(key->poll_hotkey.poll_handle,
- key->poll_hotkey.poll_method,
- key->poll_hotkey.poll_result);
- else if (method_type == ACTION_METHOD)
- write_acpi_int(key->poll_hotkey.action_handle,
- key->poll_hotkey.action_method,
- value, NULL);
- else
- goto do_fail;
-
- }
- } else {
- printk(KERN_WARNING "Not supported\n");
- return -EINVAL;
- }
- return count;
- do_fail:
- return -EINVAL;
-
-}
-
-static int __init hotkey_init(void)
-{
- int result;
- mode_t mode = S_IFREG | S_IRUGO | S_IWUGO;
-
-
- if (acpi_disabled)
- return -ENODEV;
-
- if (acpi_specific_hotkey_enabled) {
- printk("Using specific hotkey driver\n");
- return -ENODEV;
- }
-
- hotkey_proc_dir = proc_mkdir(HOTKEY_PROC, acpi_root_dir);
- if (!hotkey_proc_dir) {
- return (-ENODEV);
- }
- hotkey_proc_dir->owner = THIS_MODULE;
-
- hotkey_config =
- create_proc_entry(HOTKEY_EV_CONFIG, mode, hotkey_proc_dir);
- if (!hotkey_config) {
- goto do_fail1;
- } else {
- hotkey_config->proc_fops = &hotkey_config_fops;
- hotkey_config->data = &global_hotkey_list;
- hotkey_config->owner = THIS_MODULE;
- hotkey_config->uid = 0;
- hotkey_config->gid = 0;
- }
-
- hotkey_poll_config =
- create_proc_entry(HOTKEY_PL_CONFIG, mode, hotkey_proc_dir);
- if (!hotkey_poll_config) {
- goto do_fail2;
- } else {
- hotkey_poll_config->proc_fops = &hotkey_poll_config_fops;
- hotkey_poll_config->data = &global_hotkey_list;
- hotkey_poll_config->owner = THIS_MODULE;
- hotkey_poll_config->uid = 0;
- hotkey_poll_config->gid = 0;
- }
-
- hotkey_action = create_proc_entry(HOTKEY_ACTION, mode, hotkey_proc_dir);
- if (!hotkey_action) {
- goto do_fail3;
- } else {
- hotkey_action->proc_fops = &hotkey_action_fops;
- hotkey_action->owner = THIS_MODULE;
- hotkey_action->uid = 0;
- hotkey_action->gid = 0;
- }
-
- hotkey_info = create_proc_entry(HOTKEY_INFO, mode, hotkey_proc_dir);
- if (!hotkey_info) {
- goto do_fail4;
- } else {
- hotkey_info->proc_fops = &hotkey_info_fops;
- hotkey_info->owner = THIS_MODULE;
- hotkey_info->uid = 0;
- hotkey_info->gid = 0;
- }
-
- result = acpi_bus_register_driver(&hotkey_driver);
- if (result < 0)
- goto do_fail5;
- global_hotkey_list.count = 0;
- global_hotkey_list.entries = &hotkey_entries;
-
- INIT_LIST_HEAD(&hotkey_entries);
-
- return (0);
-
- do_fail5:
- remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir);
- do_fail4:
- remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir);
- do_fail3:
- remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir);
- do_fail2:
- remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir);
- do_fail1:
- remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
- return (-ENODEV);
-}
-
-static void __exit hotkey_exit(void)
-{
- struct list_head *entries, *next;
-
-
- list_for_each_safe(entries, next, global_hotkey_list.entries) {
- union acpi_hotkey *key =
- container_of(entries, union acpi_hotkey, entries);
-
- acpi_os_wait_events_complete(NULL);
- list_del(&key->link.entries);
- global_hotkey_list.count--;
- free_hotkey_device(key);
- }
- acpi_bus_unregister_driver(&hotkey_driver);
- remove_proc_entry(HOTKEY_EV_CONFIG, hotkey_proc_dir);
- remove_proc_entry(HOTKEY_PL_CONFIG, hotkey_proc_dir);
- remove_proc_entry(HOTKEY_ACTION, hotkey_proc_dir);
- remove_proc_entry(HOTKEY_INFO, hotkey_proc_dir);
- remove_proc_entry(HOTKEY_PROC, acpi_root_dir);
- return;
-}
-
-module_init(hotkey_init);
-module_exit(hotkey_exit);
diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c
index 76ec8b63e69..acab4a48189 100644
--- a/drivers/acpi/i2c_ec.c
+++ b/drivers/acpi/i2c_ec.c
@@ -27,18 +27,17 @@
#define ACPI_EC_HC_COMPONENT 0x00080000
#define ACPI_EC_HC_CLASS "ec_hc_smbus"
#define ACPI_EC_HC_HID "ACPI0001"
-#define ACPI_EC_HC_DRIVER_NAME "ACPI EC HC smbus driver"
#define ACPI_EC_HC_DEVICE_NAME "EC HC smbus"
#define _COMPONENT ACPI_EC_HC_COMPONENT
-ACPI_MODULE_NAME("acpi_smbus")
+ACPI_MODULE_NAME("i2c_ec");
static int acpi_ec_hc_add(struct acpi_device *device);
static int acpi_ec_hc_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_ec_hc_driver = {
- .name = ACPI_EC_HC_DRIVER_NAME,
+ .name = "i2c_ec",
.class = ACPI_EC_HC_CLASS,
.ids = ACPI_EC_HC_HID,
.ops = {
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index c6144ca6663..1a0ed3dc409 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -496,6 +496,10 @@ static int ibm_acpi_driver_init(void)
printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION);
printk(IBM_INFO "%s\n", IBM_URL);
+ if (ibm_thinkpad_ec_found)
+ printk(IBM_INFO "ThinkPad EC firmware %s\n",
+ ibm_thinkpad_ec_found);
+
return 0;
}
@@ -2617,7 +2621,7 @@ static void __init ibm_handle_init(char *name,
ibm_handle_init(#object, &object##_handle, *object##_parent, \
object##_paths, ARRAY_SIZE(object##_paths), &object##_path)
-static int set_ibm_param(const char *val, struct kernel_param *kp)
+static int __init set_ibm_param(const char *val, struct kernel_param *kp)
{
unsigned int i;
@@ -2659,7 +2663,8 @@ static void acpi_ibm_exit(void)
for (i = ARRAY_SIZE(ibms) - 1; i >= 0; i--)
ibm_exit(&ibms[i]);
- remove_proc_entry(IBM_DIR, acpi_root_dir);
+ if (proc_dir)
+ remove_proc_entry(IBM_DIR, acpi_root_dir);
if (ibm_thinkpad_ec_found)
kfree(ibm_thinkpad_ec_found);
@@ -2696,11 +2701,6 @@ static int __init acpi_ibm_init(void)
if (acpi_disabled)
return -ENODEV;
- if (!acpi_specific_hotkey_enabled) {
- printk(IBM_ERR "using generic hotkey driver\n");
- return -ENODEV;
- }
-
/* ec is required because many other handles are relative to it */
IBM_HANDLE_INIT(ec);
if (!ec_handle) {
@@ -2710,9 +2710,6 @@ static int __init acpi_ibm_init(void)
/* Models with newer firmware report the EC in DMI */
ibm_thinkpad_ec_found = check_dmi_for_ec();
- if (ibm_thinkpad_ec_found)
- printk(IBM_INFO "ThinkPad EC firmware %s\n",
- ibm_thinkpad_ec_found);
/* these handles are not required */
IBM_HANDLE_INIT(vid);
@@ -2742,6 +2739,7 @@ static int __init acpi_ibm_init(void)
proc_dir = proc_mkdir(IBM_DIR, acpi_root_dir);
if (!proc_dir) {
printk(IBM_ERR "unable to create proc dir %s", IBM_DIR);
+ acpi_ibm_exit();
return -ENODEV;
}
proc_dir->owner = THIS_MODULE;
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 4a9faff4c01..8fcd6a15517 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -33,7 +33,7 @@
#define ACPI_NUMA 0x80000000
#define _COMPONENT ACPI_NUMA
-ACPI_MODULE_NAME("numa")
+ACPI_MODULE_NAME("numa");
static nodemask_t nodes_found_map = NODE_MASK_NONE;
#define PXM_INVAL -1
@@ -45,12 +45,6 @@ int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS]
int __cpuinitdata node_to_pxm_map[MAX_NUMNODES]
= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
-extern int __init acpi_table_parse_madt_family(char *id,
- unsigned long madt_size,
- int entry_id,
- acpi_madt_entry_handler handler,
- unsigned int max_entries);
-
int __cpuinit pxm_to_node(int pxm)
{
if (pxm < 0)
@@ -208,9 +202,9 @@ static int __init acpi_parse_srat(struct acpi_table_header *table)
int __init
acpi_table_parse_srat(enum acpi_srat_type id,
- acpi_madt_entry_handler handler, unsigned int max_entries)
+ acpi_table_entry_handler handler, unsigned int max_entries)
{
- return acpi_table_parse_madt_family(ACPI_SIG_SRAT,
+ return acpi_table_parse_entries(ACPI_SIG_SRAT,
sizeof(struct acpi_table_srat), id,
handler, max_entries);
}
@@ -220,9 +214,7 @@ int __init acpi_numa_init(void)
int result;
/* SRAT: Static Resource Affinity Table */
- result = acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat);
-
- if (result > 0) {
+ if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
result = acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
acpi_parse_processor_affinity,
NR_CPUS);
@@ -230,7 +222,7 @@ int __init acpi_numa_init(void)
}
/* SLIT: System Locality Information Table */
- result = acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
+ acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
acpi_numa_arch_fixup();
return 0;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 0f6f3bcbc8e..971eca4864f 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -46,7 +46,7 @@
#include <linux/efi.h>
#define _COMPONENT ACPI_OS_SERVICES
-ACPI_MODULE_NAME("osl")
+ACPI_MODULE_NAME("osl");
#define PREFIX "ACPI: "
struct acpi_os_dpc {
acpi_osd_exec_callback function;
@@ -68,9 +68,6 @@ EXPORT_SYMBOL(acpi_in_debugger);
extern char line_buf[80];
#endif /*ENABLE_DEBUGGER */
-int acpi_specific_hotkey_enabled = TRUE;
-EXPORT_SYMBOL(acpi_specific_hotkey_enabled);
-
static unsigned int acpi_irq_irq;
static acpi_osd_handler acpi_irq_handler;
static void *acpi_irq_context;
@@ -205,7 +202,7 @@ void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
{
if (phys > ULONG_MAX) {
printk(KERN_ERR PREFIX "Cannot map memory that high\n");
- return 0;
+ return NULL;
}
if (acpi_gbl_permanent_mmap)
/*
@@ -890,26 +887,6 @@ u32 acpi_os_get_line(char *buffer)
}
#endif /* ACPI_FUTURE_USAGE */
-/* Assumes no unreadable holes inbetween */
-u8 acpi_os_readable(void *ptr, acpi_size len)
-{
-#if defined(__i386__) || defined(__x86_64__)
- char tmp;
- return !__get_user(tmp, (char __user *)ptr)
- && !__get_user(tmp, (char __user *)ptr + len - 1);
-#endif
- return 1;
-}
-
-#ifdef ACPI_FUTURE_USAGE
-u8 acpi_os_writable(void *ptr, acpi_size len)
-{
- /* could do dummy write (racy) or a kernel page table lookup.
- The later may be difficult at early boot when kmap doesn't work yet. */
- return 1;
-}
-#endif
-
acpi_status acpi_os_signal(u32 function, void *info)
{
switch (function) {
@@ -1012,14 +989,6 @@ static int __init acpi_wake_gpes_always_on_setup(char *str)
__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
-static int __init acpi_hotkey_setup(char *str)
-{
- acpi_specific_hotkey_enabled = FALSE;
- return 1;
-}
-
-__setup("acpi_generic_hotkey", acpi_hotkey_setup);
-
/*
* max_cstate is defined in the base kernel so modules can
* change it w/o depending on the state of the processor module.
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 55f57a61c55..028969370bb 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -36,7 +36,7 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_bind")
+ACPI_MODULE_NAME("pci_bind");
struct acpi_pci_data {
struct acpi_pci_id id;
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index fe7d007833a..dd3186abe07 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -38,7 +38,7 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_irq")
+ACPI_MODULE_NAME("pci_irq");
static struct acpi_prt_list acpi_prt;
static DEFINE_SPINLOCK(acpi_prt_lock);
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 0f683c8c6fb..acc59477137 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -44,10 +44,9 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_link")
+ACPI_MODULE_NAME("pci_link");
#define ACPI_PCI_LINK_CLASS "pci_irq_routing"
#define ACPI_PCI_LINK_HID "PNP0C0F"
-#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver"
#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link"
#define ACPI_PCI_LINK_FILE_INFO "info"
#define ACPI_PCI_LINK_FILE_STATUS "state"
@@ -56,7 +55,7 @@ static int acpi_pci_link_add(struct acpi_device *device);
static int acpi_pci_link_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_pci_link_driver = {
- .name = ACPI_PCI_LINK_DRIVER_NAME,
+ .name = "pci_link",
.class = ACPI_PCI_LINK_CLASS,
.ids = ACPI_PCI_LINK_HID,
.ops = {
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 4ecf701687e..ad4145a3778 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -36,17 +36,16 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_root")
+ACPI_MODULE_NAME("pci_root");
#define ACPI_PCI_ROOT_CLASS "pci_bridge"
#define ACPI_PCI_ROOT_HID "PNP0A03"
-#define ACPI_PCI_ROOT_DRIVER_NAME "ACPI PCI Root Bridge Driver"
#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge"
static int acpi_pci_root_add(struct acpi_device *device);
static int acpi_pci_root_remove(struct acpi_device *device, int type);
static int acpi_pci_root_start(struct acpi_device *device);
static struct acpi_driver acpi_pci_root_driver = {
- .name = ACPI_PCI_ROOT_DRIVER_NAME,
+ .name = "pci_root",
.class = ACPI_PCI_ROOT_CLASS,
.ids = ACPI_PCI_ROOT_HID,
.ops = {
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 0ba7dfbbb2e..1ef338545df 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -45,10 +45,9 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_POWER_COMPONENT
-ACPI_MODULE_NAME("acpi_power")
+ACPI_MODULE_NAME("power");
#define ACPI_POWER_COMPONENT 0x00800000
#define ACPI_POWER_CLASS "power_resource"
-#define ACPI_POWER_DRIVER_NAME "ACPI Power Resource Driver"
#define ACPI_POWER_DEVICE_NAME "Power Resource"
#define ACPI_POWER_FILE_INFO "info"
#define ACPI_POWER_FILE_STATUS "state"
@@ -57,25 +56,33 @@ ACPI_MODULE_NAME("acpi_power")
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
static int acpi_power_add(struct acpi_device *device);
static int acpi_power_remove(struct acpi_device *device, int type);
+static int acpi_power_resume(struct acpi_device *device);
static int acpi_power_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_power_driver = {
- .name = ACPI_POWER_DRIVER_NAME,
+ .name = "power",
.class = ACPI_POWER_CLASS,
.ids = ACPI_POWER_HID,
.ops = {
.add = acpi_power_add,
.remove = acpi_power_remove,
+ .resume = acpi_power_resume,
},
};
+struct acpi_power_reference {
+ struct list_head node;
+ struct acpi_device *device;
+};
+
struct acpi_power_resource {
struct acpi_device * device;
acpi_bus_id name;
u32 system_level;
u32 order;
int state;
- int references;
+ struct mutex resource_lock;
+ struct list_head reference;
};
static struct list_head acpi_power_resource_list;
@@ -171,22 +178,47 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
return result;
}
-static int acpi_power_on(acpi_handle handle)
+static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
{
int result = 0;
+ int found = 0;
acpi_status status = AE_OK;
- struct acpi_device *device = NULL;
struct acpi_power_resource *resource = NULL;
+ struct list_head *node, *next;
+ struct acpi_power_reference *ref;
result = acpi_power_get_context(handle, &resource);
if (result)
return result;
- resource->references++;
+ mutex_lock(&resource->resource_lock);
+ list_for_each_safe(node, next, &resource->reference) {
+ ref = container_of(node, struct acpi_power_reference, node);
+ if (dev->handle == ref->device->handle) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already referenced by resource [%s]\n",
+ dev->pnp.bus_id, resource->name));
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ ref = kmalloc(sizeof (struct acpi_power_reference),
+ irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
+ if (!ref) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "kmalloc() failed\n"));
+ mutex_unlock(&resource->resource_lock);
+ return -ENOMEM;
+ }
+ list_add_tail(&ref->node, &resource->reference);
+ ref->device = dev;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] added to resource [%s] references\n",
+ dev->pnp.bus_id, resource->name));
+ }
+ mutex_unlock(&resource->resource_lock);
- if ((resource->references > 1)
- || (resource->state == ACPI_POWER_RESOURCE_STATE_ON)) {
+ if (resource->state == ACPI_POWER_RESOURCE_STATE_ON) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n",
resource->name));
return 0;
@@ -203,38 +235,49 @@ static int acpi_power_on(acpi_handle handle)
return -ENOEXEC;
/* Update the power resource's _device_ power state */
- device = resource->device;
resource->device->power.state = ACPI_STATE_D0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n",
resource->name));
-
return 0;
}
-static int acpi_power_off_device(acpi_handle handle)
+static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
{
int result = 0;
acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
+ struct list_head *node, *next;
+ struct acpi_power_reference *ref;
+
result = acpi_power_get_context(handle, &resource);
if (result)
return result;
- if (resource->references)
- resource->references--;
+ mutex_lock(&resource->resource_lock);
+ list_for_each_safe(node, next, &resource->reference) {
+ ref = container_of(node, struct acpi_power_reference, node);
+ if (dev->handle == ref->device->handle) {
+ list_del(&ref->node);
+ kfree(ref);
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] removed from resource [%s] references\n",
+ dev->pnp.bus_id, resource->name));
+ break;
+ }
+ }
- if (resource->references) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Resource [%s] is still in use, dereferencing\n",
- resource->device->pnp.bus_id));
+ if (!list_empty(&resource->reference)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cannot turn resource [%s] off - resource is in use\n",
+ resource->name));
+ mutex_unlock(&resource->resource_lock);
return 0;
}
+ mutex_unlock(&resource->resource_lock);
if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
- resource->device->pnp.bus_id));
+ resource->name));
return 0;
}
@@ -276,7 +319,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev)
arg.integer.value = 1;
/* Open power resource */
for (i = 0; i < dev->wakeup.resources.count; i++) {
- ret = acpi_power_on(dev->wakeup.resources.handles[i]);
+ ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
if (ret) {
printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0;
@@ -323,7 +366,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
/* Close power resource */
for (i = 0; i < dev->wakeup.resources.count; i++) {
- ret = acpi_power_off_device(dev->wakeup.resources.handles[i]);
+ ret = acpi_power_off_device(dev->wakeup.resources.handles[i], dev);
if (ret) {
printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0;
@@ -407,16 +450,20 @@ int acpi_power_transition(struct acpi_device *device, int state)
* (e.g. so the device doesn't lose power while transitioning).
*/
for (i = 0; i < tl->count; i++) {
- result = acpi_power_on(tl->handles[i]);
+ result = acpi_power_on(tl->handles[i], device);
if (result)
goto end;
}
+ if (device->power.state == state) {
+ goto end;
+ }
+
/*
* Then we dereference all power resources used in the current list.
*/
for (i = 0; i < cl->count; i++) {
- result = acpi_power_off_device(cl->handles[i]);
+ result = acpi_power_off_device(cl->handles[i], device);
if (result)
goto end;
}
@@ -439,7 +486,11 @@ static struct proc_dir_entry *acpi_power_dir;
static int acpi_power_seq_show(struct seq_file *seq, void *offset)
{
+ int count = 0;
+ int result = 0;
struct acpi_power_resource *resource = NULL;
+ struct list_head *node, *next;
+ struct acpi_power_reference *ref;
resource = seq->private;
@@ -447,6 +498,10 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
if (!resource)
goto end;
+ result = acpi_power_get_state(resource);
+ if (result)
+ goto end;
+
seq_puts(seq, "state: ");
switch (resource->state) {
case ACPI_POWER_RESOURCE_STATE_ON:
@@ -460,11 +515,18 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
break;
}
+ mutex_lock(&resource->resource_lock);
+ list_for_each_safe(node, next, &resource->reference) {
+ ref = container_of(node, struct acpi_power_reference, node);
+ count++;
+ }
+ mutex_unlock(&resource->resource_lock);
+
seq_printf(seq, "system level: S%d\n"
"order: %d\n"
"reference count: %d\n",
resource->system_level,
- resource->order, resource->references);
+ resource->order, count);
end:
return 0;
@@ -537,6 +599,8 @@ static int acpi_power_add(struct acpi_device *device)
return -ENOMEM;
resource->device = device;
+ mutex_init(&resource->resource_lock);
+ INIT_LIST_HEAD(&resource->reference);
strcpy(resource->name, device->pnp.bus_id);
strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
@@ -584,6 +648,7 @@ static int acpi_power_add(struct acpi_device *device)
static int acpi_power_remove(struct acpi_device *device, int type)
{
struct acpi_power_resource *resource = NULL;
+ struct list_head *node, *next;
if (!device || !acpi_driver_data(device))
@@ -593,11 +658,54 @@ static int acpi_power_remove(struct acpi_device *device, int type)
acpi_power_remove_fs(device);
+ mutex_lock(&resource->resource_lock);
+ list_for_each_safe(node, next, &resource->reference) {
+ struct acpi_power_reference *ref = container_of(node, struct acpi_power_reference, node);
+ list_del(&ref->node);
+ kfree(ref);
+ }
+ mutex_unlock(&resource->resource_lock);
+
kfree(resource);
return 0;
}
+static int acpi_power_resume(struct acpi_device *device)
+{
+ int result = 0;
+ struct acpi_power_resource *resource = NULL;
+ struct acpi_power_reference *ref;
+
+ if (!device || !acpi_driver_data(device))
+ return -EINVAL;
+
+ resource = (struct acpi_power_resource *)acpi_driver_data(device);
+
+ result = acpi_power_get_state(resource);
+ if (result)
+ return result;
+
+ mutex_lock(&resource->resource_lock);
+ if ((resource->state == ACPI_POWER_RESOURCE_STATE_ON) &&
+ list_empty(&resource->reference)) {
+ mutex_unlock(&resource->resource_lock);
+ result = acpi_power_off_device(device->handle, NULL);
+ return result;
+ }
+
+ if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) &&
+ !list_empty(&resource->reference)) {
+ ref = container_of(resource->reference.next, struct acpi_power_reference, node);
+ mutex_unlock(&resource->resource_lock);
+ result = acpi_power_on(device->handle, ref->device);
+ return result;
+ }
+
+ mutex_unlock(&resource->resource_lock);
+ return 0;
+}
+
static int __init acpi_power_init(void)
{
int result = 0;
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 0079bc51082..99d1516d1e7 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -60,7 +60,6 @@
#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define ACPI_PROCESSOR_DEVICE_NAME "Processor"
#define ACPI_PROCESSOR_FILE_INFO "info"
#define ACPI_PROCESSOR_FILE_THROTTLING "throttling"
@@ -74,10 +73,10 @@
#define ACPI_STA_PRESENT 0x00000001
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_core");
- MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
+MODULE_AUTHOR("Paul Diefenbaugh");
+MODULE_DESCRIPTION("ACPI Processor Driver");
MODULE_LICENSE("GPL");
static int acpi_processor_add(struct acpi_device *device);
@@ -89,7 +88,7 @@ static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
static int acpi_processor_handle_eject(struct acpi_processor *pr);
static struct acpi_driver acpi_processor_driver = {
- .name = ACPI_PROCESSOR_DRIVER_NAME,
+ .name = "processor",
.class = ACPI_PROCESSOR_CLASS,
.ids = ACPI_PROCESSOR_HID,
.ops = {
@@ -404,7 +403,7 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
if (lsapic->lapic_flags & ACPI_MADT_ENABLED) {
/* First check against id */
if (lsapic->processor_id == acpi_id) {
- *apic_id = lsapic->id;
+ *apic_id = (lsapic->id << 8) | lsapic->eid;
return 1;
/* Check against optional uid */
} else if (entry->length >= 16 &&
@@ -1005,7 +1004,7 @@ static int __init acpi_processor_init(void)
#ifdef CONFIG_SMP
if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
(struct acpi_table_header **)&madt)))
- madt = 0;
+ madt = NULL;
#endif
acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 8206fc1ecc5..60773005b8a 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -51,6 +51,14 @@
#include <asm/apic.h>
#endif
+/*
+ * Include the apic definitions for x86 to have the APIC timer related defines
+ * available also for UP (on SMP it gets magically included via linux/smp.h).
+ */
+#ifdef CONFIG_X86
+#include <asm/apic.h>
+#endif
+
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -59,9 +67,8 @@
#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_idle");
#define ACPI_PROCESSOR_FILE_POWER "power"
#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
#define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 058f13cf3b7..2f2e7964226 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -44,10 +44,9 @@
#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_perflib");
static DEFINE_MUTEX(performance_mutex);
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 40fecd67ad8..06e6f3fb882 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -41,9 +41,8 @@
#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_thermal");
/* --------------------------------------------------------------------------
Limit Interface
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 89dff3639ab..b33486009f4 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -41,9 +41,8 @@
#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_throttling");
/* --------------------------------------------------------------------------
Throttling Control
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index f58fc7447ab..59640d9a0ac 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -59,7 +59,6 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
#define ACPI_AC_CLASS "ac_adapter"
#define ACPI_BATTERY_CLASS "battery"
#define ACPI_SBS_HID "ACPI0002"
-#define ACPI_SBS_DRIVER_NAME "ACPI Smart Battery System Driver"
#define ACPI_SBS_DEVICE_NAME "Smart Battery System"
#define ACPI_SBS_FILE_INFO "info"
#define ACPI_SBS_FILE_STATE "state"
@@ -78,7 +77,7 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
#define MAX_SBS_BAT 4
#define MAX_SMBUS_ERR 1
-ACPI_MODULE_NAME("acpi_sbs");
+ACPI_MODULE_NAME("sbs");
MODULE_AUTHOR("Rich Townsend");
MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
@@ -110,7 +109,7 @@ static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus);
static void acpi_sbs_update_queue(void *data);
static struct acpi_driver acpi_sbs_driver = {
- .name = ACPI_SBS_DRIVER_NAME,
+ .name = "sbs",
.class = ACPI_SBS_CLASS,
.ids = ACPI_SBS_HID,
.ops = {
@@ -1034,21 +1033,19 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
} else {
seq_printf(seq, "capacity state: ok\n");
}
+
+ foo = (s16) battery->state.amperage * battery->info.ipscale;
+ if (battery->info.capacity_mode) {
+ foo = foo * battery->info.design_voltage / 1000;
+ }
if (battery->state.amperage < 0) {
seq_printf(seq, "charging state: discharging\n");
- foo = battery->state.remaining_capacity * cscale * 60 /
- (battery->state.average_time_to_empty == 0 ? 1 :
- battery->state.average_time_to_empty);
- seq_printf(seq, "present rate: %i%s\n",
- foo, battery->info.capacity_mode ? "0 mW" : " mA");
+ seq_printf(seq, "present rate: %d %s\n",
+ -foo, battery->info.capacity_mode ? "mW" : "mA");
} else if (battery->state.amperage > 0) {
seq_printf(seq, "charging state: charging\n");
- foo = (battery->info.full_charge_capacity -
- battery->state.remaining_capacity) * cscale * 60 /
- (battery->state.average_time_to_full == 0 ? 1 :
- battery->state.average_time_to_full);
- seq_printf(seq, "present rate: %i%s\n",
- foo, battery->info.capacity_mode ? "0 mW" : " mA");
+ seq_printf(seq, "present rate: %d %s\n",
+ foo, battery->info.capacity_mode ? "mW" : "mA");
} else {
seq_printf(seq, "charging state: charged\n");
seq_printf(seq, "present rate: 0 %s\n",
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 64f26db10c8..bb0e0da39fb 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -11,13 +11,12 @@
#include <acpi/acinterp.h> /* for acpi_ex_eisa_id_to_string() */
#define _COMPONENT ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME("scan")
+ACPI_MODULE_NAME("scan");
#define STRUCT_TO_INT(s) (*((int*)&s))
extern struct acpi_device *acpi_root;
#define ACPI_BUS_CLASS "system_bus"
#define ACPI_BUS_HID "ACPI_BUS"
-#define ACPI_BUS_DRIVER_NAME "ACPI Bus Driver"
#define ACPI_BUS_DEVICE_NAME "System Bus"
static LIST_HEAD(acpi_device_list);
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 62ce87d7165..37a0930fc0a 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -200,7 +200,7 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
{},
};
-static int __init acpi_sleep_init(void)
+int __init acpi_sleep_init(void)
{
int i = 0;
@@ -229,4 +229,3 @@ static int __init acpi_sleep_init(void)
return 0;
}
-late_initcall(acpi_sleep_init);
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index 7147b0bdab0..83a8d309790 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -31,14 +31,13 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME("acpi_system")
+ACPI_MODULE_NAME("system");
#ifdef MODULE_PARAM_PREFIX
#undef MODULE_PARAM_PREFIX
#endif
#define MODULE_PARAM_PREFIX "acpi."
#define ACPI_SYSTEM_CLASS "system"
-#define ACPI_SYSTEM_DRIVER_NAME "ACPI System Driver"
#define ACPI_SYSTEM_DEVICE_NAME "System"
#define ACPI_SYSTEM_FILE_INFO "info"
#define ACPI_SYSTEM_FILE_EVENT "event"
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 45bd17313c4..849e2c36180 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -169,40 +169,40 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header * header)
int __init
-acpi_table_parse_madt_family(char *id,
- unsigned long madt_size,
+acpi_table_parse_entries(char *id,
+ unsigned long table_size,
int entry_id,
- acpi_madt_entry_handler handler,
+ acpi_table_entry_handler handler,
unsigned int max_entries)
{
- struct acpi_table_header *madt = NULL;
+ struct acpi_table_header *table_header = NULL;
struct acpi_subtable_header *entry;
unsigned int count = 0;
- unsigned long madt_end;
+ unsigned long table_end;
if (!handler)
return -EINVAL;
- /* Locate the MADT (if exists). There should only be one. */
- acpi_get_table(id, 0, &madt);
+ /* Locate the table (if exists). There should only be one. */
+ acpi_get_table(id, 0, &table_header);
- if (!madt) {
+ if (!table_header) {
printk(KERN_WARNING PREFIX "%4.4s not present\n", id);
return -ENODEV;
}
- madt_end = (unsigned long)madt + madt->length;
+ table_end = (unsigned long)table_header + table_header->length;
/* Parse all entries looking for a match. */
entry = (struct acpi_subtable_header *)
- ((unsigned long)madt + madt_size);
+ ((unsigned long)table_header + table_size);
while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
- madt_end) {
+ table_end) {
if (entry->type == entry_id
&& (!max_entries || count++ < max_entries))
- if (handler(entry, madt_end))
+ if (handler(entry, table_end))
return -EINVAL;
entry = (struct acpi_subtable_header *)
@@ -218,13 +218,22 @@ acpi_table_parse_madt_family(char *id,
int __init
acpi_table_parse_madt(enum acpi_madt_type id,
- acpi_madt_entry_handler handler, unsigned int max_entries)
+ acpi_table_entry_handler handler, unsigned int max_entries)
{
- return acpi_table_parse_madt_family(ACPI_SIG_MADT,
+ return acpi_table_parse_entries(ACPI_SIG_MADT,
sizeof(struct acpi_table_madt), id,
handler, max_entries);
}
+/**
+ * acpi_table_parse - find table with @id, run @handler on it
+ *
+ * @id: table id to find
+ * @handler: handler to run
+ *
+ * Scan the ACPI System Descriptor Table (STD) for a table matching @id,
+ * run @handler on it. Return 0 if table found, return on if not.
+ */
int __init acpi_table_parse(char *id, acpi_table_handler handler)
{
struct acpi_table_header *table = NULL;
@@ -234,9 +243,9 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
acpi_get_table(id, 0, &table);
if (table) {
handler(table);
- return 1;
- } else
return 0;
+ } else
+ return 1;
}
/*
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 807978d5381..417ef5fa766 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -338,9 +338,9 @@ acpi_status acpi_unload_table_id(acpi_owner_id id)
int i;
acpi_status status = AE_NOT_EXIST;
- ACPI_FUNCTION_TRACE(acpi_unload_table);
+ ACPI_FUNCTION_TRACE(acpi_unload_table_id);
- /* Find table from the requested type list */
+ /* Find table in the global table list */
for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
if (id != acpi_gbl_root_table_list.tables[i].owner_id) {
continue;
@@ -352,8 +352,9 @@ acpi_status acpi_unload_table_id(acpi_owner_id id)
* simply a position within the hierarchy
*/
acpi_tb_delete_namespace_by_owner(i);
- acpi_tb_release_owner_id(i);
+ status = acpi_tb_release_owner_id(i);
acpi_tb_set_table_loaded_flag(i, FALSE);
+ break;
}
return_ACPI_STATUS(status);
}
@@ -408,7 +409,7 @@ acpi_get_table(char *signature,
}
if (!acpi_gbl_permanent_mmap) {
- acpi_gbl_root_table_list.tables[i].pointer = 0;
+ acpi_gbl_root_table_list.tables[i].pointer = NULL;
}
return (status);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 986afd470a1..0ae8b9310cb 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -47,7 +47,6 @@
#define ACPI_THERMAL_COMPONENT 0x04000000
#define ACPI_THERMAL_CLASS "thermal_zone"
-#define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver"
#define ACPI_THERMAL_DEVICE_NAME "Thermal Zone"
#define ACPI_THERMAL_FILE_STATE "state"
#define ACPI_THERMAL_FILE_TEMPERATURE "temperature"
@@ -71,10 +70,10 @@
#define CELSIUS_TO_KELVIN(t) ((t+273)*10)
#define _COMPONENT ACPI_THERMAL_COMPONENT
-ACPI_MODULE_NAME("acpi_thermal")
+ACPI_MODULE_NAME("thermal");
MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
+MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
MODULE_LICENSE("GPL");
static int tzp;
@@ -99,7 +98,7 @@ static ssize_t acpi_thermal_write_polling(struct file *, const char __user *,
size_t, loff_t *);
static struct acpi_driver acpi_thermal_driver = {
- .name = ACPI_THERMAL_DRIVER_NAME,
+ .name = "thermal",
.class = ACPI_THERMAL_CLASS,
.ids = ACPI_THERMAL_HID,
.ops = {
@@ -270,7 +269,7 @@ static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Polling frequency set to %lu seconds\n",
- tz->polling_frequency));
+ tz->polling_frequency/10));
return 0;
}
@@ -1357,28 +1356,32 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
static int acpi_thermal_resume(struct acpi_device *device)
{
struct acpi_thermal *tz = NULL;
- int i;
+ int i, j, power_state, result;
+
if (!device || !acpi_driver_data(device))
return -EINVAL;
tz = acpi_driver_data(device);
- acpi_thermal_get_temperature(tz);
-
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
- if (tz->trips.active[i].flags.valid) {
- tz->temperature = tz->trips.active[i].temperature;
- tz->trips.active[i].flags.enabled = 0;
-
- acpi_thermal_active(tz);
-
- tz->state.active |= tz->trips.active[i].flags.enabled;
- tz->state.active_index = i;
+ if (!(&tz->trips.active[i]))
+ break;
+ if (!tz->trips.active[i].flags.valid)
+ break;
+ tz->trips.active[i].flags.enabled = 1;
+ for (j = 0; j < tz->trips.active[i].devices.count; j++) {
+ result = acpi_bus_get_power(tz->trips.active[i].devices.
+ handles[j], &power_state);
+ if (result || (power_state != ACPI_STATE_D0)) {
+ tz->trips.active[i].flags.enabled = 0;
+ break;
+ }
}
+ tz->state.active |= tz->trips.active[i].flags.enabled;
}
- acpi_thermal_check(tz);
+ acpi_thermal_check(tz);
return AE_OK;
}
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index d9b651ffcdc..faf8a5232d8 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -125,7 +125,7 @@ static int write_acpi_int(const char *methodName, int val)
union acpi_object in_objs[1];
acpi_status status;
- params.count = sizeof(in_objs) / sizeof(in_objs[0]);
+ params.count = ARRAY_SIZE(in_objs);
params.pointer = in_objs;
in_objs[0].type = ACPI_TYPE_INTEGER;
in_objs[0].integer.value = val;
@@ -561,10 +561,6 @@ static int __init toshiba_acpi_init(void)
if (acpi_disabled)
return -ENODEV;
- if (!acpi_specific_hotkey_enabled) {
- printk(MY_INFO "Using generic hotkey driver\n");
- return -ENODEV;
- }
/* simple device detection: look for HCI method */
if (is_valid_acpi_path(METHOD_HCI_1))
method_hci = METHOD_HCI_1;
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index f777cebdc46..673a0caa407 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -170,7 +170,6 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
acpi_os_delete_mutex(object->mutex.os_mutex);
acpi_gbl_global_lock_mutex = NULL;
} else {
- acpi_ex_unlink_mutex(object);
acpi_os_delete_mutex(object->mutex.os_mutex);
}
break;
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 68a809fa7b1..34f15757108 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -31,7 +31,7 @@
#include <acpi/acpi_drivers.h>
#define _COMPONENT ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME("acpi_utils")
+ACPI_MODULE_NAME("utils");
/* --------------------------------------------------------------------------
Object Evaluation Helpers
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index e0b97add8c6..bf525cca3b6 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -40,7 +40,6 @@
#define ACPI_VIDEO_COMPONENT 0x08000000
#define ACPI_VIDEO_CLASS "video"
-#define ACPI_VIDEO_DRIVER_NAME "ACPI Video Driver"
#define ACPI_VIDEO_BUS_NAME "Video Bus"
#define ACPI_VIDEO_DEVICE_NAME "Video Device"
#define ACPI_VIDEO_NOTIFY_SWITCH 0x80
@@ -65,17 +64,17 @@
#define ACPI_VIDEO_DISPLAY_LCD 4
#define _COMPONENT ACPI_VIDEO_COMPONENT
-ACPI_MODULE_NAME("acpi_video")
+ACPI_MODULE_NAME("video");
- MODULE_AUTHOR("Bruno Ducrot");
-MODULE_DESCRIPTION(ACPI_VIDEO_DRIVER_NAME);
+MODULE_AUTHOR("Bruno Ducrot");
+MODULE_DESCRIPTION("ACPI Video Driver");
MODULE_LICENSE("GPL");
static int acpi_video_bus_add(struct acpi_device *device);
static int acpi_video_bus_remove(struct acpi_device *device, int type);
static struct acpi_driver acpi_video_bus = {
- .name = ACPI_VIDEO_DRIVER_NAME,
+ .name = "video",
.class = ACPI_VIDEO_CLASS,
.ids = ACPI_VIDEO_HID,
.ops = {
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 3747457fee7..4af0a4bb578 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -161,6 +161,19 @@ config SATA_INTEL_COMBINED
depends on IDE=y && !BLK_DEV_IDE_SATA && (SATA_AHCI || ATA_PIIX)
default y
+config SATA_ACPI
+ bool
+ depends on ACPI && PCI
+ default y
+ help
+ This option adds support for SATA-related ACPI objects.
+ These ACPI objects add the ability to retrieve taskfiles
+ from the ACPI BIOS and write them to the disk controller.
+ These objects may be related to performance, security,
+ power management, or other areas.
+ You can disable this at kernel boot time by using the
+ option libata.noacpi=1
+
config PATA_ALI
tristate "ALi PATA support (Experimental)"
depends on PCI && EXPERIMENTAL
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index cd096f0c78a..74298afbbaa 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -66,4 +66,4 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o
obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o
libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o
-
+libata-$(CONFIG_SATA_ACPI) += libata-acpi.o
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
new file mode 100644
index 00000000000..b4e8be5d292
--- /dev/null
+++ b/drivers/ata/libata-acpi.c
@@ -0,0 +1,698 @@
+/*
+ * libata-acpi.c
+ * Provides ACPI support for PATA/SATA.
+ *
+ * Copyright (C) 2006 Intel Corp.
+ * Copyright (C) 2006 Randy Dunlap
+ */
+
+#include <linux/ata.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/acpi.h>
+#include <linux/libata.h>
+#include <linux/pci.h>
+#include "libata.h"
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acnames.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acparser.h>
+#include <acpi/acexcep.h>
+#include <acpi/acmacros.h>
+#include <acpi/actypes.h>
+
+#define SATA_ROOT_PORT(x) (((x) >> 16) & 0xffff)
+#define SATA_PORT_NUMBER(x) ((x) & 0xffff) /* or NO_PORT_MULT */
+#define NO_PORT_MULT 0xffff
+#define SATA_ADR_RSVD 0xffffffff
+
+#define REGS_PER_GTF 7
+struct taskfile_array {
+ u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */
+};
+
+
+/**
+ * sata_get_dev_handle - finds acpi_handle and PCI device.function
+ * @dev: device to locate
+ * @handle: returned acpi_handle for @dev
+ * @pcidevfn: return PCI device.func for @dev
+ *
+ * This function is somewhat SATA-specific. Or at least the
+ * PATA & SATA versions of this function are different,
+ * so it's not entirely generic code.
+ *
+ * Returns 0 on success, <0 on error.
+ */
+static int sata_get_dev_handle(struct device *dev, acpi_handle *handle,
+ acpi_integer *pcidevfn)
+{
+ struct pci_dev *pci_dev;
+ acpi_integer addr;
+
+ pci_dev = to_pci_dev(dev); /* NOTE: PCI-specific */
+ /* Please refer to the ACPI spec for the syntax of _ADR. */
+ addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
+ *pcidevfn = addr;
+ *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
+ if (!*handle)
+ return -ENODEV;
+ return 0;
+}
+
+/**
+ * pata_get_dev_handle - finds acpi_handle and PCI device.function
+ * @dev: device to locate
+ * @handle: returned acpi_handle for @dev
+ * @pcidevfn: return PCI device.func for @dev
+ *
+ * The PATA and SATA versions of this function are different.
+ *
+ * Returns 0 on success, <0 on error.
+ */
+static int pata_get_dev_handle(struct device *dev, acpi_handle *handle,
+ acpi_integer *pcidevfn)
+{
+ unsigned int bus, devnum, func;
+ acpi_integer addr;
+ acpi_handle dev_handle, parent_handle;
+ struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER,
+ .pointer = NULL};
+ acpi_status status;
+ struct acpi_device_info *dinfo = NULL;
+ int ret = -ENODEV;
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ bus = pdev->bus->number;
+ devnum = PCI_SLOT(pdev->devfn);
+ func = PCI_FUNC(pdev->devfn);
+
+ dev_handle = DEVICE_ACPI_HANDLE(dev);
+ parent_handle = DEVICE_ACPI_HANDLE(dev->parent);
+
+ status = acpi_get_object_info(parent_handle, &buffer);
+ if (ACPI_FAILURE(status))
+ goto err;
+
+ dinfo = buffer.pointer;
+ if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
+ dinfo->address == bus) {
+ /* ACPI spec for _ADR for PCI bus: */
+ addr = (acpi_integer)(devnum << 16 | func);
+ *pcidevfn = addr;
+ *handle = dev_handle;
+ } else {
+ goto err;
+ }
+
+ if (!*handle)
+ goto err;
+ ret = 0;
+err:
+ kfree(dinfo);
+ return ret;
+}
+
+struct walk_info { /* can be trimmed some */
+ struct device *dev;
+ struct acpi_device *adev;
+ acpi_handle handle;
+ acpi_integer pcidevfn;
+ unsigned int drivenum;
+ acpi_handle obj_handle;
+ struct ata_port *ataport;
+ struct ata_device *atadev;
+ u32 sata_adr;
+ int status;
+ char basepath[ACPI_PATHNAME_MAX];
+ int basepath_len;
+};
+
+static acpi_status get_devices(acpi_handle handle,
+ u32 level, void *context, void **return_value)
+{
+ acpi_status status;
+ struct walk_info *winfo = context;
+ struct acpi_buffer namebuf = {ACPI_ALLOCATE_BUFFER, NULL};
+ char *pathname;
+ struct acpi_buffer buffer;
+ struct acpi_device_info *dinfo;
+
+ status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &namebuf);
+ if (status)
+ goto ret;
+ pathname = namebuf.pointer;
+
+ buffer.length = ACPI_ALLOCATE_BUFFER;
+ buffer.pointer = NULL;
+ status = acpi_get_object_info(handle, &buffer);
+ if (ACPI_FAILURE(status))
+ goto out2;
+
+ dinfo = buffer.pointer;
+
+ /* find full device path name for pcidevfn */
+ if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
+ dinfo->address == winfo->pcidevfn) {
+ if (ata_msg_probe(winfo->ataport))
+ ata_dev_printk(winfo->atadev, KERN_DEBUG,
+ ":%s: matches pcidevfn (0x%llx)\n",
+ pathname, winfo->pcidevfn);
+ strlcpy(winfo->basepath, pathname,
+ sizeof(winfo->basepath));
+ winfo->basepath_len = strlen(pathname);
+ goto out;
+ }
+
+ /* if basepath is not yet known, ignore this object */
+ if (!winfo->basepath_len)
+ goto out;
+
+ /* if this object is in scope of basepath, maybe use it */
+ if (strncmp(pathname, winfo->basepath,
+ winfo->basepath_len) == 0) {
+ if (!(dinfo->valid & ACPI_VALID_ADR))
+ goto out;
+ if (ata_msg_probe(winfo->ataport))
+ ata_dev_printk(winfo->atadev, KERN_DEBUG,
+ "GOT ONE: (%s) root_port = 0x%llx,"
+ " port_num = 0x%llx\n", pathname,
+ SATA_ROOT_PORT(dinfo->address),
+ SATA_PORT_NUMBER(dinfo->address));
+ /* heuristics: */
+ if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT)
+ if (ata_msg_probe(winfo->ataport))
+ ata_dev_printk(winfo->atadev,
+ KERN_DEBUG, "warning: don't"
+ " know how to handle SATA port"
+ " multiplier\n");
+ if (SATA_ROOT_PORT(dinfo->address) ==
+ winfo->ataport->port_no &&
+ SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) {
+ if (ata_msg_probe(winfo->ataport))
+ ata_dev_printk(winfo->atadev,
+ KERN_DEBUG,
+ "THIS ^^^^^ is the requested"
+ " SATA drive (handle = 0x%p)\n",
+ handle);
+ winfo->sata_adr = dinfo->address;
+ winfo->obj_handle = handle;
+ }
+ }
+out:
+ kfree(dinfo);
+out2:
+ kfree(pathname);
+
+ret:
+ return status;
+}
+
+/* Get the SATA drive _ADR object. */
+static int get_sata_adr(struct device *dev, acpi_handle handle,
+ acpi_integer pcidevfn, unsigned int drive,
+ struct ata_port *ap,
+ struct ata_device *atadev, u32 *dev_adr)
+{
+ acpi_status status;
+ struct walk_info *winfo;
+ int err = -ENOMEM;
+
+ winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL);
+ if (!winfo)
+ goto out;
+
+ winfo->dev = dev;
+ winfo->atadev = atadev;
+ winfo->ataport = ap;
+ if (acpi_bus_get_device(handle, &winfo->adev) < 0)
+ if (ata_msg_probe(ap))
+ ata_dev_printk(winfo->atadev, KERN_DEBUG,
+ "acpi_bus_get_device failed\n");
+ winfo->handle = handle;
+ winfo->pcidevfn = pcidevfn;
+ winfo->drivenum = drive;
+
+ status = acpi_get_devices(NULL, get_devices, winfo, NULL);
+ if (ACPI_FAILURE(status)) {
+ if (ata_msg_probe(ap))
+ ata_dev_printk(winfo->atadev, KERN_DEBUG,
+ "%s: acpi_get_devices failed\n",
+ __FUNCTION__);
+ err = -ENODEV;
+ } else {
+ *dev_adr = winfo->sata_adr;
+ atadev->obj_handle = winfo->obj_handle;
+ err = 0;
+ }
+ kfree(winfo);
+out:
+ return err;
+}
+
+/**
+ * do_drive_get_GTF - get the drive bootup default taskfile settings
+ * @ap: the ata_port for the drive
+ * @ix: target ata_device (drive) index
+ * @gtf_length: number of bytes of _GTF data returned at @gtf_address
+ * @gtf_address: buffer containing _GTF taskfile arrays
+ *
+ * This applies to both PATA and SATA drives.
+ *
+ * The _GTF method has no input parameters.
+ * It returns a variable number of register set values (registers
+ * hex 1F1..1F7, taskfiles).
+ * The <variable number> is not known in advance, so have ACPI-CA
+ * allocate the buffer as needed and return it, then free it later.
+ *
+ * The returned @gtf_length and @gtf_address are only valid if the
+ * function return value is 0.
+ */
+static int do_drive_get_GTF(struct ata_port *ap, int ix,
+ unsigned int *gtf_length, unsigned long *gtf_address,
+ unsigned long *obj_loc)
+{
+ acpi_status status;
+ acpi_handle dev_handle = NULL;
+ acpi_handle chan_handle, drive_handle;
+ acpi_integer pcidevfn = 0;
+ u32 dev_adr;
+ struct acpi_buffer output;
+ union acpi_object *out_obj;
+ struct device *dev = ap->host->dev;
+ struct ata_device *atadev = &ap->device[ix];
+ int err = -ENODEV;
+
+ *gtf_length = 0;
+ *gtf_address = 0UL;
+ *obj_loc = 0UL;
+
+ if (noacpi)
+ return 0;
+
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "%s: ENTER: ap->id: %d, port#: %d\n",
+ __FUNCTION__, ap->id, ap->port_no);
+
+ if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED)) {
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG, "%s: ERR: "
+ "ata_dev_present: %d, PORT_DISABLED: %lu\n",
+ __FUNCTION__, ata_dev_enabled(atadev),
+ ap->flags & ATA_FLAG_DISABLED);
+ goto out;
+ }
+
+ /* Don't continue if device has no _ADR method.
+ * _GTF is intended for known motherboard devices. */
+ if (!(ap->cbl == ATA_CBL_SATA)) {
+ err = pata_get_dev_handle(dev, &dev_handle, &pcidevfn);
+ if (err < 0) {
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "%s: pata_get_dev_handle failed (%d)\n",
+ __FUNCTION__, err);
+ goto out;
+ }
+ } else {
+ err = sata_get_dev_handle(dev, &dev_handle, &pcidevfn);
+ if (err < 0) {
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "%s: sata_get_dev_handle failed (%d\n",
+ __FUNCTION__, err);
+ goto out;
+ }
+ }
+
+ /* Get this drive's _ADR info. if not already known. */
+ if (!atadev->obj_handle) {
+ if (!(ap->cbl == ATA_CBL_SATA)) {
+ /* get child objects of dev_handle == channel objects,
+ * + _their_ children == drive objects */
+ /* channel is ap->port_no */
+ chan_handle = acpi_get_child(dev_handle,
+ ap->port_no);
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "%s: chan adr=%d: chan_handle=0x%p\n",
+ __FUNCTION__, ap->port_no,
+ chan_handle);
+ if (!chan_handle) {
+ err = -ENODEV;
+ goto out;
+ }
+ /* TBD: could also check ACPI object VALID bits */
+ drive_handle = acpi_get_child(chan_handle, ix);
+ if (!drive_handle) {
+ err = -ENODEV;
+ goto out;
+ }
+ dev_adr = ix;
+ atadev->obj_handle = drive_handle;
+ } else { /* for SATA mode */
+ dev_adr = SATA_ADR_RSVD;
+ err = get_sata_adr(dev, dev_handle, pcidevfn, 0,
+ ap, atadev, &dev_adr);
+ }
+ if (err < 0 || dev_adr == SATA_ADR_RSVD ||
+ !atadev->obj_handle) {
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "%s: get_sata/pata_adr failed: "
+ "err=%d, dev_adr=%u, obj_handle=0x%p\n",
+ __FUNCTION__, err, dev_adr,
+ atadev->obj_handle);
+ goto out;
+ }
+ }
+
+ /* Setting up output buffer */
+ output.length = ACPI_ALLOCATE_BUFFER;
+ output.pointer = NULL; /* ACPI-CA sets this; save/free it later */
+
+ /* _GTF has no input parameters */
+ err = -EIO;
+ status = acpi_evaluate_object(atadev->obj_handle, "_GTF",
+ NULL, &output);
+ if (ACPI_FAILURE(status)) {
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "%s: Run _GTF error: status = 0x%x\n",
+ __FUNCTION__, status);
+ goto out;
+ }
+
+ if (!output.length || !output.pointer) {
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: "
+ "length or ptr is NULL (0x%llx, 0x%p)\n",
+ __FUNCTION__,
+ (unsigned long long)output.length,
+ output.pointer);
+ kfree(output.pointer);
+ goto out;
+ }
+
+ out_obj = output.pointer;
+ if (out_obj->type != ACPI_TYPE_BUFFER) {
+ kfree(output.pointer);
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: "
+ "error: expected object type of "
+ " ACPI_TYPE_BUFFER, got 0x%x\n",
+ __FUNCTION__, out_obj->type);
+ err = -ENOENT;
+ goto out;
+ }
+
+ if (!out_obj->buffer.length || !out_obj->buffer.pointer ||
+ out_obj->buffer.length % REGS_PER_GTF) {
+ if (ata_msg_drv(ap))
+ ata_dev_printk(atadev, KERN_ERR,
+ "%s: unexpected GTF length (%d) or addr (0x%p)\n",
+ __FUNCTION__, out_obj->buffer.length,
+ out_obj->buffer.pointer);
+ err = -ENOENT;
+ goto out;
+ }
+
+ *gtf_length = out_obj->buffer.length;
+ *gtf_address = (unsigned long)out_obj->buffer.pointer;
+ *obj_loc = (unsigned long)out_obj;
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG, "%s: returning "
+ "gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n",
+ __FUNCTION__, *gtf_length, *gtf_address, *obj_loc);
+ err = 0;
+out:
+ return err;
+}
+
+/**
+ * taskfile_load_raw - send taskfile registers to host controller
+ * @ap: Port to which output is sent
+ * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
+ *
+ * Outputs ATA taskfile to standard ATA host controller using MMIO
+ * or PIO as indicated by the ATA_FLAG_MMIO flag.
+ * Writes the control, feature, nsect, lbal, lbam, and lbah registers.
+ * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
+ * hob_lbal, hob_lbam, and hob_lbah.
+ *
+ * This function waits for idle (!BUSY and !DRQ) after writing
+ * registers. If the control register has a new value, this
+ * function also waits for idle after writing control and before
+ * writing the remaining registers.
+ *
+ * LOCKING: TBD:
+ * Inherited from caller.
+ */
+static void taskfile_load_raw(struct ata_port *ap,
+ struct ata_device *atadev,
+ const struct taskfile_array *gtf)
+{
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: "
+ "%02x %02x %02x %02x %02x %02x %02x\n",
+ __FUNCTION__,
+ gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
+ gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
+
+ if ((gtf->tfa[0] == 0) && (gtf->tfa[1] == 0) && (gtf->tfa[2] == 0)
+ && (gtf->tfa[3] == 0) && (gtf->tfa[4] == 0) && (gtf->tfa[5] == 0)
+ && (gtf->tfa[6] == 0))
+ return;
+
+ if (ap->ops->qc_issue) {
+ struct ata_taskfile tf;
+ unsigned int err;
+
+ ata_tf_init(atadev, &tf);
+
+ /* convert gtf to tf */
+ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
+ tf.protocol = atadev->class == ATA_DEV_ATAPI ?
+ ATA_PROT_ATAPI_NODATA : ATA_PROT_NODATA;
+ tf.feature = gtf->tfa[0]; /* 0x1f1 */
+ tf.nsect = gtf->tfa[1]; /* 0x1f2 */
+ tf.lbal = gtf->tfa[2]; /* 0x1f3 */
+ tf.lbam = gtf->tfa[3]; /* 0x1f4 */
+ tf.lbah = gtf->tfa[4]; /* 0x1f5 */
+ tf.device = gtf->tfa[5]; /* 0x1f6 */
+ tf.command = gtf->tfa[6]; /* 0x1f7 */
+
+ err = ata_exec_internal(atadev, &tf, NULL, DMA_NONE, NULL, 0);
+ if (err && ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_ERR,
+ "%s: ata_exec_internal failed: %u\n",
+ __FUNCTION__, err);
+ } else
+ if (ata_msg_warn(ap))
+ ata_dev_printk(atadev, KERN_WARNING,
+ "%s: SATA driver is missing qc_issue function"
+ " entry points\n",
+ __FUNCTION__);
+}
+
+/**
+ * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
+ * @ap: the ata_port for the drive
+ * @atadev: target ata_device
+ * @gtf_length: total number of bytes of _GTF taskfiles
+ * @gtf_address: location of _GTF taskfile arrays
+ *
+ * This applies to both PATA and SATA drives.
+ *
+ * Write {gtf_address, length gtf_length} in groups of
+ * REGS_PER_GTF bytes.
+ */
+static int do_drive_set_taskfiles(struct ata_port *ap,
+ struct ata_device *atadev, unsigned int gtf_length,
+ unsigned long gtf_address)
+{
+ int err = -ENODEV;
+ int gtf_count = gtf_length / REGS_PER_GTF;
+ int ix;
+ struct taskfile_array *gtf;
+
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "%s: ENTER: ap->id: %d, port#: %d\n",
+ __FUNCTION__, ap->id, ap->port_no);
+
+ if (noacpi || !(ap->cbl == ATA_CBL_SATA))
+ return 0;
+
+ if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED))
+ goto out;
+ if (!gtf_count) /* shouldn't be here */
+ goto out;
+
+ if (gtf_length % REGS_PER_GTF) {
+ if (ata_msg_drv(ap))
+ ata_dev_printk(atadev, KERN_ERR,
+ "%s: unexpected GTF length (%d)\n",
+ __FUNCTION__, gtf_length);
+ goto out;
+ }
+
+ for (ix = 0; ix < gtf_count; ix++) {
+ gtf = (struct taskfile_array *)
+ (gtf_address + ix * REGS_PER_GTF);
+
+ /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
+ taskfile_load_raw(ap, atadev, gtf);
+ }
+
+ err = 0;
+out:
+ return err;
+}
+
+/**
+ * ata_acpi_exec_tfs - get then write drive taskfile settings
+ * @ap: the ata_port for the drive
+ *
+ * This applies to both PATA and SATA drives.
+ */
+int ata_acpi_exec_tfs(struct ata_port *ap)
+{
+ int ix;
+ int ret =0;
+ unsigned int gtf_length;
+ unsigned long gtf_address;
+ unsigned long obj_loc;
+
+ if (noacpi)
+ return 0;
+
+ for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
+ if (!ata_dev_enabled(&ap->device[ix]))
+ continue;
+
+ ret = do_drive_get_GTF(ap, ix,
+ &gtf_length, &gtf_address, &obj_loc);
+ if (ret < 0) {
+ if (ata_msg_probe(ap))
+ ata_port_printk(ap, KERN_DEBUG,
+ "%s: get_GTF error (%d)\n",
+ __FUNCTION__, ret);
+ break;
+ }
+
+ ret = do_drive_set_taskfiles(ap, &ap->device[ix],
+ gtf_length, gtf_address);
+ kfree((void *)obj_loc);
+ if (ret < 0) {
+ if (ata_msg_probe(ap))
+ ata_port_printk(ap, KERN_DEBUG,
+ "%s: set_taskfiles error (%d)\n",
+ __FUNCTION__, ret);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * ata_acpi_push_id - send Identify data to drive
+ * @ap: the ata_port for the drive
+ * @ix: drive index
+ *
+ * _SDD ACPI object: for SATA mode only
+ * Must be after Identify (Packet) Device -- uses its data
+ * ATM this function never returns a failure. It is an optional
+ * method and if it fails for whatever reason, we should still
+ * just keep going.
+ */
+int ata_acpi_push_id(struct ata_port *ap, unsigned int ix)
+{
+ acpi_handle handle;
+ acpi_integer pcidevfn;
+ int err;
+ struct device *dev = ap->host->dev;
+ struct ata_device *atadev = &ap->device[ix];
+ u32 dev_adr;
+ acpi_status status;
+ struct acpi_object_list input;
+ union acpi_object in_params[1];
+
+ if (noacpi)
+ return 0;
+
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "%s: ap->id: %d, ix = %d, port#: %d\n",
+ __FUNCTION__, ap->id, ix, ap->port_no);
+
+ /* Don't continue if not a SATA device. */
+ if (!(ap->cbl == ATA_CBL_SATA)) {
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "%s: Not a SATA device\n", __FUNCTION__);
+ goto out;
+ }
+
+ /* Don't continue if device has no _ADR method.
+ * _SDD is intended for known motherboard devices. */
+ err = sata_get_dev_handle(dev, &handle, &pcidevfn);
+ if (err < 0) {
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "%s: sata_get_dev_handle failed (%d\n",
+ __FUNCTION__, err);
+ goto out;
+ }
+
+ /* Get this drive's _ADR info, if not already known */
+ if (!atadev->obj_handle) {
+ dev_adr = SATA_ADR_RSVD;
+ err = get_sata_adr(dev, handle, pcidevfn, ix, ap, atadev,
+ &dev_adr);
+ if (err < 0 || dev_adr == SATA_ADR_RSVD ||
+ !atadev->obj_handle) {
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "%s: get_sata_adr failed: "
+ "err=%d, dev_adr=%u, obj_handle=0x%p\n",
+ __FUNCTION__, err, dev_adr,
+ atadev->obj_handle);
+ goto out;
+ }
+ }
+
+ /* Give the drive Identify data to the drive via the _SDD method */
+ /* _SDD: set up input parameters */
+ input.count = 1;
+ input.pointer = in_params;
+ in_params[0].type = ACPI_TYPE_BUFFER;
+ in_params[0].buffer.length = sizeof(atadev->id[0]) * ATA_ID_WORDS;
+ in_params[0].buffer.pointer = (u8 *)atadev->id;
+ /* Output buffer: _SDD has no output */
+
+ /* It's OK for _SDD to be missing too. */
+ swap_buf_le16(atadev->id, ATA_ID_WORDS);
+ status = acpi_evaluate_object(atadev->obj_handle, "_SDD", &input, NULL);
+ swap_buf_le16(atadev->id, ATA_ID_WORDS);
+
+ err = ACPI_FAILURE(status) ? -EIO : 0;
+ if (err < 0) {
+ if (ata_msg_probe(ap))
+ ata_dev_printk(atadev, KERN_DEBUG,
+ "ata%u(%u): %s _SDD error: status = 0x%x\n",
+ ap->id, ap->device->devno,
+ __FUNCTION__, status);
+ }
+
+ /* always return success */
+out:
+ return 0;
+}
+
+
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 2cf8251728d..e900c5edefc 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -93,6 +93,10 @@ static int ata_probe_timeout = ATA_TMOUT_INTERNAL / HZ;
module_param(ata_probe_timeout, int, 0444);
MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)");
+int noacpi;
+module_param(noacpi, int, 0444);
+MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when set");
+
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("Library module for ATA devices");
MODULE_LICENSE("GPL");
@@ -1564,6 +1568,16 @@ int ata_dev_configure(struct ata_device *dev)
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
__FUNCTION__, ap->id, dev->devno);
+ /* set _SDD */
+ rc = ata_acpi_push_id(ap, dev->devno);
+ if (rc) {
+ ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n",
+ rc);
+ }
+
+ /* retrieve and execute the ATA task file of _GTF */
+ ata_acpi_exec_tfs(ap);
+
/* print device capabilities */
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG,
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 06ccf230e3c..0ad7781d72a 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -47,6 +47,7 @@ extern struct workqueue_struct *ata_aux_wq;
extern int atapi_enabled;
extern int atapi_dmadir;
extern int libata_fua;
+extern int noacpi;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
u64 block, u32 n_block, unsigned int tf_flags,
@@ -87,6 +88,20 @@ extern void ata_port_init(struct ata_port *ap, struct ata_host *host,
extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev,
const struct ata_port_info *port);
+/* libata-acpi.c */
+#ifdef CONFIG_SATA_ACPI
+extern int ata_acpi_exec_tfs(struct ata_port *ap);
+extern int ata_acpi_push_id(struct ata_port *ap, unsigned int ix);
+#else
+static inline int ata_acpi_exec_tfs(struct ata_port *ap)
+{
+ return 0;
+}
+static inline int ata_acpi_push_id(struct ata_port *ap, unsigned int ix)
+{
+ return 0;
+}
+#endif
/* libata-scsi.c */
extern struct scsi_transport_template ata_scsi_transport_template;
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index db33f6f4dd2..8510026b690 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -3017,7 +3017,7 @@ read_prom_byte(struct he_dev *he_dev, int addr)
he_writel(he_dev, val, HOST_CNTL);
/* Send READ instruction */
- for (i = 0; i < sizeof(readtab)/sizeof(readtab[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(readtab); i++) {
he_writel(he_dev, val | readtab[i], HOST_CNTL);
udelay(EEPROM_DELAY);
}
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index f4078612194..b4b80140c39 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -388,7 +388,7 @@ idt77252_eeprom_read_status(struct idt77252_dev *card)
gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
- for (i = 0; i < sizeof(rdsrtab)/sizeof(rdsrtab[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
idt77252_write_gp(card, gp | rdsrtab[i]);
udelay(5);
}
@@ -422,7 +422,7 @@ idt77252_eeprom_read_byte(struct idt77252_dev *card, u8 offset)
gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
- for (i = 0; i < sizeof(rdtab)/sizeof(rdtab[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(rdtab); i++) {
idt77252_write_gp(card, gp | rdtab[i]);
udelay(5);
}
@@ -469,14 +469,14 @@ idt77252_eeprom_write_byte(struct idt77252_dev *card, u8 offset, u8 data)
gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
- for (i = 0; i < sizeof(wrentab)/sizeof(wrentab[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(wrentab); i++) {
idt77252_write_gp(card, gp | wrentab[i]);
udelay(5);
}
idt77252_write_gp(card, gp | SAR_GP_EECS);
udelay(5);
- for (i = 0; i < sizeof(wrtab)/sizeof(wrtab[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(wrtab); i++) {
idt77252_write_gp(card, gp | wrtab[i]);
udelay(5);
}
diff --git a/drivers/atm/nicstarmac.c b/drivers/atm/nicstarmac.c
index 2c5e3ae7750..480947f4e01 100644
--- a/drivers/atm/nicstarmac.c
+++ b/drivers/atm/nicstarmac.c
@@ -7,6 +7,8 @@
* Read this ForeRunner's MAC address from eprom/eeprom
*/
+#include <linux/kernel.h>
+
typedef void __iomem *virt_addr_t;
#define CYCLE_DELAY 5
@@ -176,7 +178,7 @@ read_eprom_byte(virt_addr_t base, u_int8_t offset)
val = NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) & 0xFFFFFFF0;
/* Send READ instruction */
- for (i=0; i<sizeof readtab/sizeof readtab[0]; i++)
+ for (i=0; i<ARRAY_SIZE(readtab); i++)
{
NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
(val | readtab[i]) );
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 472810f8e6e..253868e03c7 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -324,27 +324,25 @@ int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
return error;
}
-static int device_add_attrs(struct bus_type * bus, struct device * dev)
+static int device_add_attrs(struct bus_type *bus, struct device *dev)
{
int error = 0;
int i;
- if (bus->dev_attrs) {
- for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
- error = device_create_file(dev,&bus->dev_attrs[i]);
- if (error)
- goto Err;
+ if (!bus->dev_attrs)
+ return 0;
+
+ for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
+ error = device_create_file(dev,&bus->dev_attrs[i]);
+ if (error) {
+ while (--i >= 0)
+ device_remove_file(dev, &bus->dev_attrs[i]);
+ break;
}
}
- Done:
return error;
- Err:
- while (--i >= 0)
- device_remove_file(dev,&bus->dev_attrs[i]);
- goto Done;
}
-
static void device_remove_attrs(struct bus_type * bus, struct device * dev)
{
int i;
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 96def1ddba1..1417e5cd4c6 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -163,8 +163,7 @@ int class_register(struct class * cls)
void class_unregister(struct class * cls)
{
pr_debug("device class '%s': unregistering\n", cls->name);
- if (cls->virtual_dir)
- kobject_unregister(cls->virtual_dir);
+ kobject_unregister(cls->virtual_dir);
remove_class_attrs(cls);
subsystem_unregister(&cls->subsys);
}
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 20ee4f7c53a..90e2d9350c1 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -83,7 +83,7 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
* Every time unit enable is asserted, GPOD needs to be cleared
* on IOP3XX to avoid data corruption on the bus.
*/
-#ifdef CONFIG_PLAT_IOP
+#if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X)
if (iop3xx_adap->id == 0) {
gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW);
gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW);
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index c3b1567c852..14e83d0aac8 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -34,6 +34,7 @@
#include <asm/hardware.h>
#include <asm/irq.h>
+#include <asm/io.h>
#include <asm/arch/i2c.h>
#include <asm/arch/pxa-regs.h>
@@ -54,8 +55,21 @@ struct pxa_i2c {
unsigned int irqlogidx;
u32 isrlog[32];
u32 icrlog[32];
+
+ void __iomem *reg_base;
+
+ unsigned long iobase;
+ unsigned long iosize;
+
+ int irq;
};
+#define _IBMR(i2c) ((i2c)->reg_base + 0)
+#define _IDBR(i2c) ((i2c)->reg_base + 8)
+#define _ICR(i2c) ((i2c)->reg_base + 0x10)
+#define _ISR(i2c) ((i2c)->reg_base + 0x18)
+#define _ISAR(i2c) ((i2c)->reg_base + 0x20)
+
/*
* I2C Slave mode address
*/
@@ -130,7 +144,8 @@ static unsigned int i2c_debug = DEBUG;
static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
{
- dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno, ISR, ICR, IBMR);
+ dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno,
+ readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
}
#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__)
@@ -153,7 +168,7 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
printk("i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n",
i2c->msg_num, i2c->msg_idx, i2c->msg_ptr);
printk("i2c: ICR: %08x ISR: %08x\n"
- "i2c: log: ", ICR, ISR);
+ "i2c: log: ", readl(_ICR(i2c)), readl(_ISR(i2c)));
for (i = 0; i < i2c->irqlogidx; i++)
printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]);
printk("\n");
@@ -161,7 +176,7 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
{
- return !(ICR & ICR_SCLE);
+ return !(readl(_ICR(i2c)) & ICR_SCLE);
}
static void i2c_pxa_abort(struct pxa_i2c *i2c)
@@ -173,28 +188,29 @@ static void i2c_pxa_abort(struct pxa_i2c *i2c)
return;
}
- while (time_before(jiffies, timeout) && (IBMR & 0x1) == 0) {
- unsigned long icr = ICR;
+ while (time_before(jiffies, timeout) && (readl(_IBMR(i2c)) & 0x1) == 0) {
+ unsigned long icr = readl(_ICR(i2c));
icr &= ~ICR_START;
icr |= ICR_ACKNAK | ICR_STOP | ICR_TB;
- ICR = icr;
+ writel(icr, _ICR(i2c));
show_state(i2c);
msleep(1);
}
- ICR &= ~(ICR_MA | ICR_START | ICR_STOP);
+ writel(readl(_ICR(i2c)) & ~(ICR_MA | ICR_START | ICR_STOP),
+ _ICR(i2c));
}
static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
{
int timeout = DEF_TIMEOUT;
- while (timeout-- && ISR & (ISR_IBB | ISR_UB)) {
- if ((ISR & ISR_SAD) != 0)
+ while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) {
+ if ((readl(_ISR(i2c)) & ISR_SAD) != 0)
timeout += 4;
msleep(2);
@@ -214,9 +230,9 @@ static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
while (time_before(jiffies, timeout)) {
if (i2c_debug > 1)
dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
- __func__, (long)jiffies, ISR, ICR, IBMR);
+ __func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
- if (ISR & ISR_SAD) {
+ if (readl(_ISR(i2c)) & ISR_SAD) {
if (i2c_debug > 0)
dev_dbg(&i2c->adap.dev, "%s: Slave detected\n", __func__);
goto out;
@@ -226,7 +242,7 @@ static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
* quick check of the i2c lines themselves to ensure they've
* gone high...
*/
- if ((ISR & (ISR_UB | ISR_IBB)) == 0 && IBMR == 3) {
+ if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) == 0 && readl(_IBMR(i2c)) == 3) {
if (i2c_debug > 0)
dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
return 1;
@@ -246,7 +262,7 @@ static int i2c_pxa_set_master(struct pxa_i2c *i2c)
if (i2c_debug)
dev_dbg(&i2c->adap.dev, "setting to bus master\n");
- if ((ISR & (ISR_UB | ISR_IBB)) != 0) {
+ if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) != 0) {
dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__);
if (!i2c_pxa_wait_master(i2c)) {
dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__);
@@ -254,7 +270,7 @@ static int i2c_pxa_set_master(struct pxa_i2c *i2c)
}
}
- ICR |= ICR_SCLE;
+ writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c));
return 0;
}
@@ -270,11 +286,11 @@ static int i2c_pxa_wait_slave(struct pxa_i2c *i2c)
while (time_before(jiffies, timeout)) {
if (i2c_debug > 1)
dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
- __func__, (long)jiffies, ISR, ICR, IBMR);
+ __func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
- if ((ISR & (ISR_UB|ISR_IBB)) == 0 ||
- (ISR & ISR_SAD) != 0 ||
- (ICR & ICR_SCLE) == 0) {
+ if ((readl(_ISR(i2c)) & (ISR_UB|ISR_IBB)) == 0 ||
+ (readl(_ISR(i2c)) & ISR_SAD) != 0 ||
+ (readl(_ICR(i2c)) & ICR_SCLE) == 0) {
if (i2c_debug > 1)
dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
return 1;
@@ -302,9 +318,9 @@ static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode)
/* we need to wait for the stop condition to end */
/* if we where in stop, then clear... */
- if (ICR & ICR_STOP) {
+ if (readl(_ICR(i2c)) & ICR_STOP) {
udelay(100);
- ICR &= ~ICR_STOP;
+ writel(readl(_ICR(i2c)) & ~ICR_STOP, _ICR(i2c));
}
if (!i2c_pxa_wait_slave(i2c)) {
@@ -314,12 +330,12 @@ static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode)
}
}
- ICR &= ~(ICR_STOP|ICR_ACKNAK|ICR_MA);
- ICR &= ~ICR_SCLE;
+ writel(readl(_ICR(i2c)) & ~(ICR_STOP|ICR_ACKNAK|ICR_MA), _ICR(i2c));
+ writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
if (i2c_debug) {
- dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", ICR, ISR);
- decode_ICR(ICR);
+ dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", readl(_ICR(i2c)), readl(_ISR(i2c)));
+ decode_ICR(readl(_ICR(i2c)));
}
}
#else
@@ -334,24 +350,24 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
i2c_pxa_abort(i2c);
/* reset according to 9.8 */
- ICR = ICR_UR;
- ISR = I2C_ISR_INIT;
- ICR &= ~ICR_UR;
+ writel(ICR_UR, _ICR(i2c));
+ writel(I2C_ISR_INIT, _ISR(i2c));
+ writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c));
- ISAR = i2c->slave_addr;
+ writel(i2c->slave_addr, _ISAR(i2c));
/* set control register values */
- ICR = I2C_ICR_INIT;
+ writel(I2C_ICR_INIT, _ICR(i2c));
#ifdef CONFIG_I2C_PXA_SLAVE
dev_info(&i2c->adap.dev, "Enabling slave mode\n");
- ICR |= ICR_SADIE | ICR_ALDIE | ICR_SSDIE;
+ writel(readl(_ICR(i2c)) | ICR_SADIE | ICR_ALDIE | ICR_SSDIE, _ICR(i2c));
#endif
i2c_pxa_set_slave(i2c, 0);
/* enable unit */
- ICR |= ICR_IUE;
+ writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
udelay(100);
}
@@ -371,19 +387,19 @@ static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
if (i2c->slave != NULL)
ret = i2c->slave->read(i2c->slave->data);
- IDBR = ret;
- ICR |= ICR_TB; /* allow next byte */
+ writel(ret, _IDBR(i2c));
+ writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c)); /* allow next byte */
}
}
static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
{
- unsigned int byte = IDBR;
+ unsigned int byte = readl(_IDBR(i2c));
if (i2c->slave != NULL)
i2c->slave->write(i2c->slave->data, byte);
- ICR |= ICR_TB;
+ writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
}
static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
@@ -403,13 +419,13 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
* start condition... if this happens, we'd better back off
* and stop holding the poor thing up
*/
- ICR &= ~(ICR_START|ICR_STOP);
- ICR |= ICR_TB;
+ writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c));
+ writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
timeout = 0x10000;
while (1) {
- if ((IBMR & 2) == 2)
+ if ((readl(_IBMR(i2c)) & 2) == 2)
break;
timeout--;
@@ -420,7 +436,7 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
}
}
- ICR &= ~ICR_SCLE;
+ writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
}
static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
@@ -447,14 +463,14 @@ static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
if (isr & ISR_BED) {
/* what should we do here? */
} else {
- IDBR = 0;
- ICR |= ICR_TB;
+ writel(0, _IDBR(i2c));
+ writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
}
}
static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
{
- ICR |= ICR_TB | ICR_ACKNAK;
+ writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c));
}
static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
@@ -466,13 +482,13 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
* start condition... if this happens, we'd better back off
* and stop holding the poor thing up
*/
- ICR &= ~(ICR_START|ICR_STOP);
- ICR |= ICR_TB | ICR_ACKNAK;
+ writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c));
+ writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c));
timeout = 0x10000;
while (1) {
- if ((IBMR & 2) == 2)
+ if ((readl(_IBMR(i2c)) & 2) == 2)
break;
timeout--;
@@ -483,7 +499,7 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
}
}
- ICR &= ~ICR_SCLE;
+ writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
}
static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
@@ -514,13 +530,13 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
/*
* Step 1: target slave address into IDBR
*/
- IDBR = i2c_pxa_addr_byte(i2c->msg);
+ writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c));
/*
* Step 2: initiate the write.
*/
- icr = ICR & ~(ICR_STOP | ICR_ALDIE);
- ICR = icr | ICR_START | ICR_TB;
+ icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE);
+ writel(icr | ICR_START | ICR_TB, _ICR(i2c));
}
/*
@@ -594,7 +610,7 @@ static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret)
static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
{
- u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
+ u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
again:
/*
@@ -645,7 +661,7 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
/*
* Write mode. Write the next data byte.
*/
- IDBR = i2c->msg->buf[i2c->msg_ptr++];
+ writel(i2c->msg->buf[i2c->msg_ptr++], _IDBR(i2c));
icr |= ICR_ALDIE | ICR_TB;
@@ -675,7 +691,7 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
/*
* Write the next address.
*/
- IDBR = i2c_pxa_addr_byte(i2c->msg);
+ writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c));
/*
* And trigger a repeated start, and send the byte.
@@ -696,18 +712,18 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
i2c->icrlog[i2c->irqlogidx-1] = icr;
- ICR = icr;
+ writel(icr, _ICR(i2c));
show_state(i2c);
}
static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
{
- u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
+ u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
/*
* Read the byte.
*/
- i2c->msg->buf[i2c->msg_ptr++] = IDBR;
+ i2c->msg->buf[i2c->msg_ptr++] = readl(_IDBR(i2c));
if (i2c->msg_ptr < i2c->msg->len) {
/*
@@ -724,17 +740,17 @@ static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
i2c->icrlog[i2c->irqlogidx-1] = icr;
- ICR = icr;
+ writel(icr, _ICR(i2c));
}
static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
{
struct pxa_i2c *i2c = dev_id;
- u32 isr = ISR;
+ u32 isr = readl(_ISR(i2c));
if (i2c_debug > 2 && 0) {
dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n",
- __func__, isr, ICR, IBMR);
+ __func__, isr, readl(_ICR(i2c)), readl(_IBMR(i2c)));
decode_ISR(isr);
}
@@ -746,7 +762,7 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
/*
* Always clear all pending IRQs.
*/
- ISR = isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED);
+ writel(isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED), _ISR(i2c));
if (isr & ISR_SAD)
i2c_pxa_slave_start(i2c, isr);
@@ -779,7 +795,7 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num
/* If the I2C controller is disabled we need to reset it (probably due
to a suspend/resume destroying state). We do this here as we can then
avoid worrying about resuming the controller before its users. */
- if (!(ICR & ICR_IUE))
+ if (!(readl(_ICR(i2c)) & ICR_IUE))
i2c_pxa_reset(i2c);
for (i = adap->retries; i >= 0; i--) {
@@ -810,28 +826,53 @@ static const struct i2c_algorithm i2c_pxa_algorithm = {
static struct pxa_i2c i2c_pxa = {
.lock = SPIN_LOCK_UNLOCKED,
- .wait = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait),
.adap = {
.owner = THIS_MODULE,
.algo = &i2c_pxa_algorithm,
- .name = "pxa2xx-i2c",
+ .name = "pxa2xx-i2c.0",
.retries = 5,
},
};
+#define res_len(r) ((r)->end - (r)->start + 1)
static int i2c_pxa_probe(struct platform_device *dev)
{
struct pxa_i2c *i2c = &i2c_pxa;
+ struct resource *res;
#ifdef CONFIG_I2C_PXA_SLAVE
struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
#endif
int ret;
+ int irq;
-#ifdef CONFIG_PXA27x
- pxa_gpio_mode(GPIO117_I2CSCL_MD);
- pxa_gpio_mode(GPIO118_I2CSDA_MD);
- udelay(100);
-#endif
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(dev, 0);
+ if (res == NULL || irq < 0)
+ return -ENODEV;
+
+ if (!request_mem_region(res->start, res_len(res), res->name))
+ return -ENOMEM;
+
+ i2c = kmalloc(sizeof(struct pxa_i2c), GFP_KERNEL);
+ if (!i2c) {
+ ret = -ENOMEM;
+ goto emalloc;
+ }
+
+ memcpy(i2c, &i2c_pxa, sizeof(struct pxa_i2c));
+ init_waitqueue_head(&i2c->wait);
+ i2c->adap.name[strlen(i2c->adap.name) - 1] = '0' + dev->id % 10;
+
+ i2c->reg_base = ioremap(res->start, res_len(res));
+ if (!i2c->reg_base) {
+ ret = -EIO;
+ goto eremap;
+ }
+
+ i2c->iobase = res->start;
+ i2c->iosize = res_len(res);
+
+ i2c->irq = irq;
i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
@@ -842,11 +883,28 @@ static int i2c_pxa_probe(struct platform_device *dev)
}
#endif
- pxa_set_cken(CKEN14_I2C, 1);
- ret = request_irq(IRQ_I2C, i2c_pxa_handler, IRQF_DISABLED,
- "pxa2xx-i2c", i2c);
+ switch (dev->id) {
+ case 0:
+#ifdef CONFIG_PXA27x
+ pxa_gpio_mode(GPIO117_I2CSCL_MD);
+ pxa_gpio_mode(GPIO118_I2CSDA_MD);
+#endif
+ pxa_set_cken(CKEN14_I2C, 1);
+ break;
+#ifdef CONFIG_PXA27x
+ case 1:
+ local_irq_disable();
+ PCFR |= PCFR_PI2CEN;
+ local_irq_enable();
+ pxa_set_cken(CKEN15_PWRI2C, 1);
+#endif
+ }
+
+ ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
+ i2c->adap.name, i2c);
if (ret)
- goto out;
+ goto ereqirq;
+
i2c_pxa_reset(i2c);
@@ -856,7 +914,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
ret = i2c_add_adapter(&i2c->adap);
if (ret < 0) {
printk(KERN_INFO "I2C: Failed to add bus\n");
- goto err_irq;
+ goto eadapt;
}
platform_set_drvdata(dev, i2c);
@@ -870,9 +928,25 @@ static int i2c_pxa_probe(struct platform_device *dev)
#endif
return 0;
- err_irq:
- free_irq(IRQ_I2C, i2c);
- out:
+eadapt:
+ free_irq(irq, i2c);
+ereqirq:
+ switch (dev->id) {
+ case 0:
+ pxa_set_cken(CKEN14_I2C, 0);
+ break;
+#ifdef CONFIG_PXA27x
+ case 1:
+ pxa_set_cken(CKEN15_PWRI2C, 0);
+ local_irq_disable();
+ PCFR &= ~PCFR_PI2CEN;
+ local_irq_enable();
+#endif
+ }
+eremap:
+ kfree(i2c);
+emalloc:
+ release_mem_region(res->start, res_len(res));
return ret;
}
@@ -883,8 +957,21 @@ static int i2c_pxa_remove(struct platform_device *dev)
platform_set_drvdata(dev, NULL);
i2c_del_adapter(&i2c->adap);
- free_irq(IRQ_I2C, i2c);
- pxa_set_cken(CKEN14_I2C, 0);
+ free_irq(i2c->irq, i2c);
+ switch (dev->id) {
+ case 0:
+ pxa_set_cken(CKEN14_I2C, 0);
+ break;
+#ifdef CONFIG_PXA27x
+ case 1:
+ pxa_set_cken(CKEN15_PWRI2C, 0);
+ local_irq_disable();
+ PCFR &= ~PCFR_PI2CEN;
+ local_irq_enable();
+#endif
+ }
+ release_mem_region(i2c->iobase, i2c->iosize);
+ kfree(i2c);
return 0;
}
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 6adf8649764..49234e32fd1 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -800,6 +800,14 @@ config BLK_DEV_IDEDMA_PMAC
to transfer data to and from memory. Saying Y is safe and improves
performance.
+config BLK_DEV_IDE_CELLEB
+ bool "Toshiba's Cell Reference Set IDE support"
+ depends on PPC_CELLEB
+ help
+ This driver provides support for the built-in IDE controller on
+ Toshiba Cell Reference Board.
+ If unsure, say Y.
+
config BLK_DEV_IDE_SWARM
tristate "IDE for Sibyte evaluation boards"
depends on SIBYTE_SB1xxx_SOC
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index d9f029e8ff7..28feedfbd21 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -37,6 +37,7 @@ ide-core-$(CONFIG_BLK_DEV_Q40IDE) += legacy/q40ide.o
# built-in only drivers from ppc/
ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o
ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o
+ide-core-$(CONFIG_BLK_DEV_IDE_CELLEB) += ppc/scc_pata.o
# built-in only drivers from h8300/
ide-core-$(CONFIG_H8300) += h8300/ide-h8300.o
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 8a1c27f2869..40e5c66b81c 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -307,26 +307,24 @@ static int icside_set_speed(ide_drive_t *drive, u8 xfer_mode)
return on;
}
-static int icside_dma_host_off(ide_drive_t *drive)
+static void icside_dma_host_off(ide_drive_t *drive)
{
- return 0;
}
-static int icside_dma_off_quietly(ide_drive_t *drive)
+static void icside_dma_off_quietly(ide_drive_t *drive)
{
drive->using_dma = 0;
- return icside_dma_host_off(drive);
}
-static int icside_dma_host_on(ide_drive_t *drive)
+static void icside_dma_host_on(ide_drive_t *drive)
{
- return 0;
}
static int icside_dma_on(ide_drive_t *drive)
{
drive->using_dma = 1;
- return icside_dma_host_on(drive);
+
+ return 0;
}
static int icside_dma_check(ide_drive_t *drive)
@@ -365,10 +363,7 @@ static int icside_dma_check(ide_drive_t *drive)
out:
on = icside_set_speed(drive, xfer_mode);
- if (on)
- return icside_dma_on(drive);
- else
- return icside_dma_off_quietly(drive);
+ return on ? 0 : -1;
}
static int icside_dma_end(ide_drive_t *drive)
@@ -497,9 +492,9 @@ static void icside_dma_init(ide_hwif_t *hwif)
hwif->autodma = autodma;
hwif->ide_dma_check = icside_dma_check;
- hwif->ide_dma_host_off = icside_dma_host_off;
- hwif->ide_dma_off_quietly = icside_dma_off_quietly;
- hwif->ide_dma_host_on = icside_dma_host_on;
+ hwif->dma_host_off = icside_dma_host_off;
+ hwif->dma_off_quietly = icside_dma_off_quietly;
+ hwif->dma_host_on = icside_dma_host_on;
hwif->ide_dma_on = icside_dma_on;
hwif->dma_setup = icside_dma_setup;
hwif->dma_exec_cmd = icside_dma_exec_cmd;
@@ -556,7 +551,7 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e
* Ensure we're using MMIO
*/
default_hwif_mmiops(hwif);
- hwif->mmio = 2;
+ hwif->mmio = 1;
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
hwif->hw.io_ports[i] = port;
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
index 3058217767d..9c6c49fdd2b 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/arm/rapide.c
@@ -46,7 +46,7 @@ rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int
hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
hwif->hw.irq = hwif->irq = irq;
- hwif->mmio = 2;
+ hwif->mmio = 1;
default_hwif_mmiops(hwif);
return hwif;
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index 5797e0b5a13..6b2d152351b 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -682,9 +682,12 @@ static void cris_ide_input_data (ide_drive_t *drive, void *, unsigned int);
static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int);
static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int);
static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int);
-static int cris_dma_off (ide_drive_t *drive);
static int cris_dma_on (ide_drive_t *drive);
+static void cris_dma_off(ide_drive_t *drive)
+{
+}
+
static void tune_cris_ide(ide_drive_t *drive, u8 pio)
{
int setup, strobe, hold;
@@ -795,7 +798,7 @@ init_e100_ide (void)
0, 0, cris_ide_ack_intr,
ide_default_irq(0));
ide_register_hw(&hw, &hwif);
- hwif->mmio = 2;
+ hwif->mmio = 1;
hwif->chipset = ide_etrax100;
hwif->tuneproc = &tune_cris_ide;
hwif->speedproc = &speed_cris_ide;
@@ -814,13 +817,16 @@ init_e100_ide (void)
hwif->OUTBSYNC = &cris_ide_outbsync;
hwif->INB = &cris_ide_inb;
hwif->INW = &cris_ide_inw;
- hwif->ide_dma_host_off = &cris_dma_off;
- hwif->ide_dma_host_on = &cris_dma_on;
- hwif->ide_dma_off_quietly = &cris_dma_off;
+ hwif->dma_host_off = &cris_dma_off;
+ hwif->dma_host_on = &cris_dma_on;
+ hwif->dma_off_quietly = &cris_dma_off;
hwif->udma_four = 0;
hwif->ultra_mask = cris_ultra_mask;
hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
hwif->swdma_mask = 0x07; /* Singleword DMA 0-2 */
+ hwif->autodma = 1;
+ hwif->drives[0].autodma = 1;
+ hwif->drives[1].autodma = 1;
}
/* Reset pulse */
@@ -835,11 +841,6 @@ init_e100_ide (void)
cris_ide_set_speed(TYPE_UDMA, ATA_UDMA2_CYC, ATA_UDMA2_DVS, 0);
}
-static int cris_dma_off (ide_drive_t *drive)
-{
- return 0;
-}
-
static int cris_dma_on (ide_drive_t *drive)
{
return 0;
@@ -1045,17 +1046,10 @@ static ide_startstop_t cris_dma_intr (ide_drive_t *drive)
static int cris_dma_check(ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
- struct hd_driveid* id = drive->id;
-
- if (id && (id->capability & 1)) {
- if (ide_use_dma(drive)) {
- if (cris_config_drive_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
- }
+ if (ide_use_dma(drive) && cris_config_drive_for_dma(drive))
+ return 0;
- return hwif->ide_dma_off_quietly(drive);
+ return -1;
}
static int cris_dma_end(ide_drive_t *drive)
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
index 608ca871744..88750a30033 100644
--- a/drivers/ide/h8300/ide-h8300.c
+++ b/drivers/ide/h8300/ide-h8300.c
@@ -76,13 +76,11 @@ static inline void hwif_setup(ide_hwif_t *hwif)
{
default_hwif_iops(hwif);
- hwif->mmio = 2;
+ hwif->mmio = 1;
hwif->OUTW = mm_outw;
hwif->OUTSW = mm_outsw;
hwif->INW = mm_inw;
hwif->INSW = mm_insw;
- hwif->OUTL = NULL;
- hwif->INL = NULL;
hwif->OUTSL = NULL;
hwif->INSL = NULL;
}
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 5969cec58dc..45a928c058c 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -687,15 +687,8 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 sta
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
struct request *rq = HWGROUP(drive)->rq;
- ide_hwif_t *hwif = HWIF(drive);
int stat, err, sense_key;
- /* We may have bogus DMA interrupts in PIO state here */
- if (HWIF(drive)->dma_status && hwif->atapi_irq_bogon) {
- stat = hwif->INB(hwif->dma_status);
- /* Should we force the bit as well ? */
- hwif->OUTB(stat, hwif->dma_status);
- }
/* Check for errors. */
stat = HWIF(drive)->INB(IDE_STATUS_REG);
if (stat_ret)
@@ -930,6 +923,10 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
+ /* waiting for CDB interrupt, not DMA yet. */
+ if (info->dma)
+ drive->waiting_for_dma = 0;
+
/* packet command */
ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry);
return ide_started;
@@ -972,6 +969,10 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
/* Check for errors. */
if (cdrom_decode_status(drive, DRQ_STAT, NULL))
return ide_stopped;
+
+ /* Ok, next interrupt will be DMA interrupt. */
+ if (info->dma)
+ drive->waiting_for_dma = 1;
} else {
/* Otherwise, we must wait for DRQ to get set. */
if (ide_wait_stat(&startstop, drive, DRQ_STAT,
@@ -1103,7 +1104,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
if (dma) {
info->dma = 0;
if ((dma_error = HWIF(drive)->ide_dma_end(drive)))
- __ide_dma_off(drive);
+ ide_dma_off(drive);
}
if (cdrom_decode_status(drive, 0, &stat))
@@ -1699,7 +1700,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
if (dma) {
if (dma_error) {
printk(KERN_ERR "ide-cd: dma error\n");
- __ide_dma_off(drive);
+ ide_dma_off(drive);
return ide_error(drive, "dma error", stat);
}
@@ -1825,7 +1826,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
info->dma = 0;
if ((dma_error = HWIF(drive)->ide_dma_end(drive))) {
printk(KERN_ERR "ide-cd: write dma error\n");
- __ide_dma_off(drive);
+ ide_dma_off(drive);
}
}
@@ -3254,14 +3255,6 @@ int ide_cdrom_setup (ide_drive_t *drive)
if (drive->autotune == IDE_TUNE_DEFAULT ||
drive->autotune == IDE_TUNE_AUTO)
drive->dsc_overlap = (drive->next != drive);
-#if 0
- drive->dsc_overlap = (HWIF(drive)->no_dsc) ? 0 : 1;
- if (HWIF(drive)->no_dsc) {
- printk(KERN_INFO "ide-cd: %s: disabling DSC overlap\n",
- drive->name);
- drive->dsc_overlap = 0;
- }
-#endif
if (ide_cdrom_register(drive, nslots)) {
printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
@@ -3360,21 +3353,16 @@ static int idecd_open(struct inode * inode, struct file * file)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct cdrom_info *info;
- ide_drive_t *drive;
int rc = -ENOMEM;
if (!(info = ide_cd_get(disk)))
return -ENXIO;
- drive = info->drive;
-
- drive->usage++;
-
if (!info->buffer)
- info->buffer = kmalloc(SECTOR_BUFFER_SIZE,
- GFP_KERNEL|__GFP_REPEAT);
- if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file)))
- drive->usage--;
+ info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT);
+
+ if (info->buffer)
+ rc = cdrom_open(&info->devinfo, inode, file);
if (rc < 0)
ide_cd_put(info);
@@ -3386,10 +3374,8 @@ static int idecd_release(struct inode * inode, struct file * file)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct cdrom_info *info = ide_cd_g(disk);
- ide_drive_t *drive = info->drive;
cdrom_release (&info->devinfo, file);
- drive->usage--;
ide_cd_put(info);
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 0a05a377d66..e2cea1889c4 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -77,6 +77,7 @@ struct ide_disk_obj {
ide_driver_t *driver;
struct gendisk *disk;
struct kref kref;
+ unsigned int openers; /* protected by BKL for now */
};
static DEFINE_MUTEX(idedisk_ref_mutex);
@@ -1081,8 +1082,9 @@ static int idedisk_open(struct inode *inode, struct file *filp)
drive = idkp->drive;
- drive->usage++;
- if (drive->removable && drive->usage == 1) {
+ idkp->openers++;
+
+ if (drive->removable && idkp->openers == 1) {
ide_task_t args;
memset(&args, 0, sizeof(ide_task_t));
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
@@ -1106,9 +1108,10 @@ static int idedisk_release(struct inode *inode, struct file *filp)
struct ide_disk_obj *idkp = ide_disk_g(disk);
ide_drive_t *drive = idkp->drive;
- if (drive->usage == 1)
+ if (idkp->openers == 1)
ide_cacheflush_p(drive);
- if (drive->removable && drive->usage == 1) {
+
+ if (drive->removable && idkp->openers == 1) {
ide_task_t args;
memset(&args, 0, sizeof(ide_task_t));
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK;
@@ -1117,7 +1120,8 @@ static int idedisk_release(struct inode *inode, struct file *filp)
if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
drive->doorlocking = 0;
}
- drive->usage--;
+
+ idkp->openers--;
ide_disk_put(idkp);
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 56efed6742d..08e7cd043bc 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -348,15 +348,14 @@ EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
static int config_drive_for_dma (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = HWIF(drive);
- if ((id->capability & 1) && hwif->autodma) {
+ if ((id->capability & 1) && drive->hwif->autodma) {
/*
* Enable DMA on any drive that has
* UltraDMA (mode 0/1/2/3/4/5/6) enabled
*/
if ((id->field_valid & 4) && ((id->dma_ultra >> 8) & 0x7f))
- return hwif->ide_dma_on(drive);
+ return 0;
/*
* Enable DMA on any drive that has mode2 DMA
* (multi or single) enabled
@@ -364,14 +363,14 @@ static int config_drive_for_dma (ide_drive_t *drive)
if (id->field_valid & 2) /* regular DMA */
if ((id->dma_mword & 0x404) == 0x404 ||
(id->dma_1word & 0x404) == 0x404)
- return hwif->ide_dma_on(drive);
+ return 0;
/* Consult the list of known "good" drives */
if (__ide_dma_good_drive(drive))
- return hwif->ide_dma_on(drive);
+ return 0;
}
-// if (hwif->tuneproc != NULL) hwif->tuneproc(drive, 255);
- return hwif->ide_dma_off_quietly(drive);
+
+ return -1;
}
/**
@@ -415,72 +414,68 @@ static int dma_timer_expiry (ide_drive_t *drive)
}
/**
- * __ide_dma_host_off - Generic DMA kill
+ * ide_dma_host_off - Generic DMA kill
* @drive: drive to control
*
* Perform the generic IDE controller DMA off operation. This
* works for most IDE bus mastering controllers
*/
-int __ide_dma_host_off (ide_drive_t *drive)
+void ide_dma_host_off(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
u8 unit = (drive->select.b.unit & 0x01);
u8 dma_stat = hwif->INB(hwif->dma_status);
hwif->OUTB((dma_stat & ~(1<<(5+unit))), hwif->dma_status);
- return 0;
}
-EXPORT_SYMBOL(__ide_dma_host_off);
+EXPORT_SYMBOL(ide_dma_host_off);
/**
- * __ide_dma_host_off_quietly - Generic DMA kill
+ * ide_dma_off_quietly - Generic DMA kill
* @drive: drive to control
*
* Turn off the current DMA on this IDE controller.
*/
-int __ide_dma_off_quietly (ide_drive_t *drive)
+void ide_dma_off_quietly(ide_drive_t *drive)
{
drive->using_dma = 0;
ide_toggle_bounce(drive, 0);
- if (HWIF(drive)->ide_dma_host_off(drive))
- return 1;
-
- return 0;
+ drive->hwif->dma_host_off(drive);
}
-EXPORT_SYMBOL(__ide_dma_off_quietly);
+EXPORT_SYMBOL(ide_dma_off_quietly);
#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
/**
- * __ide_dma_off - disable DMA on a device
+ * ide_dma_off - disable DMA on a device
* @drive: drive to disable DMA on
*
* Disable IDE DMA for a device on this IDE controller.
* Inform the user that DMA has been disabled.
*/
-int __ide_dma_off (ide_drive_t *drive)
+void ide_dma_off(ide_drive_t *drive)
{
printk(KERN_INFO "%s: DMA disabled\n", drive->name);
- return HWIF(drive)->ide_dma_off_quietly(drive);
+ drive->hwif->dma_off_quietly(drive);
}
-EXPORT_SYMBOL(__ide_dma_off);
+EXPORT_SYMBOL(ide_dma_off);
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
/**
- * __ide_dma_host_on - Enable DMA on a host
+ * ide_dma_host_on - Enable DMA on a host
* @drive: drive to enable for DMA
*
* Enable DMA on an IDE controller following generic bus mastering
* IDE controller behaviour
*/
-
-int __ide_dma_host_on (ide_drive_t *drive)
+
+void ide_dma_host_on(ide_drive_t *drive)
{
if (drive->using_dma) {
ide_hwif_t *hwif = HWIF(drive);
@@ -488,12 +483,10 @@ int __ide_dma_host_on (ide_drive_t *drive)
u8 dma_stat = hwif->INB(hwif->dma_status);
hwif->OUTB((dma_stat|(1<<(5+unit))), hwif->dma_status);
- return 0;
}
- return 1;
}
-EXPORT_SYMBOL(__ide_dma_host_on);
+EXPORT_SYMBOL(ide_dma_host_on);
/**
* __ide_dma_on - Enable DMA on a device
@@ -511,8 +504,7 @@ int __ide_dma_on (ide_drive_t *drive)
drive->using_dma = 1;
ide_toggle_bounce(drive, 1);
- if (HWIF(drive)->ide_dma_host_on(drive))
- return 1;
+ drive->hwif->dma_host_on(drive);
return 0;
}
@@ -565,7 +557,10 @@ int ide_dma_setup(ide_drive_t *drive)
}
/* PRD table */
- hwif->OUTL(hwif->dmatable_dma, hwif->dma_prdtable);
+ if (hwif->mmio)
+ writel(hwif->dmatable_dma, (void __iomem *)hwif->dma_prdtable);
+ else
+ outl(hwif->dmatable_dma, hwif->dma_prdtable);
/* specify r/w */
hwif->OUTB(reading, hwif->dma_command);
@@ -680,6 +675,9 @@ int ide_use_dma(ide_drive_t *drive)
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = drive->hwif;
+ if ((id->capability & 1) == 0 || drive->autodma == 0)
+ return 0;
+
/* consult the list of known "bad" drives */
if (__ide_dma_bad_drive(drive))
return 0;
@@ -753,12 +751,37 @@ void ide_dma_verbose(ide_drive_t *drive)
return;
bug_dma_off:
printk(", BUG DMA OFF");
- hwif->ide_dma_off_quietly(drive);
+ hwif->dma_off_quietly(drive);
return;
}
EXPORT_SYMBOL(ide_dma_verbose);
+int ide_set_dma(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ int rc;
+
+ rc = hwif->ide_dma_check(drive);
+
+ switch(rc) {
+ case -1: /* DMA needs to be disabled */
+ hwif->dma_off_quietly(drive);
+ return 0;
+ case 0: /* DMA needs to be enabled */
+ return hwif->ide_dma_on(drive);
+ case 1: /* DMA setting cannot be changed */
+ break;
+ default:
+ BUG();
+ break;
+ }
+
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(ide_set_dma);
+
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
int __ide_dma_lostirq (ide_drive_t *drive)
{
@@ -809,7 +832,7 @@ int ide_release_dma(ide_hwif_t *hwif)
{
ide_release_dma_engine(hwif);
- if (hwif->mmio == 2)
+ if (hwif->mmio)
return 1;
else
return ide_release_iomio_dma(hwif);
@@ -878,9 +901,9 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
{
- if (hwif->mmio == 2)
+ if (hwif->mmio)
return ide_mapped_mmio_dma(hwif, base,ports);
- BUG_ON(hwif->mmio == 1);
+
return ide_iomio_dma(hwif, base, ports);
}
@@ -908,14 +931,14 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p
if (!(hwif->dma_prdtable))
hwif->dma_prdtable = (hwif->dma_base + 4);
- if (!hwif->ide_dma_off_quietly)
- hwif->ide_dma_off_quietly = &__ide_dma_off_quietly;
- if (!hwif->ide_dma_host_off)
- hwif->ide_dma_host_off = &__ide_dma_host_off;
+ if (!hwif->dma_off_quietly)
+ hwif->dma_off_quietly = &ide_dma_off_quietly;
+ if (!hwif->dma_host_off)
+ hwif->dma_host_off = &ide_dma_host_off;
if (!hwif->ide_dma_on)
hwif->ide_dma_on = &__ide_dma_on;
- if (!hwif->ide_dma_host_on)
- hwif->ide_dma_host_on = &__ide_dma_host_on;
+ if (!hwif->dma_host_on)
+ hwif->dma_host_on = &ide_dma_host_on;
if (!hwif->ide_dma_check)
hwif->ide_dma_check = &__ide_dma_check;
if (!hwif->dma_setup)
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index d33717c8afd..57cd21c5b2c 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -279,6 +279,7 @@ typedef struct ide_floppy_obj {
ide_driver_t *driver;
struct gendisk *disk;
struct kref kref;
+ unsigned int openers; /* protected by BKL for now */
/* Current packet command */
idefloppy_pc_t *pc;
@@ -866,7 +867,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
printk(KERN_ERR "ide-floppy: The floppy wants to issue "
"more interrupts in DMA mode\n");
- (void)__ide_dma_off(drive);
+ ide_dma_off(drive);
return ide_do_reset(drive);
}
@@ -1096,9 +1097,9 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
pc->current_position = pc->buffer;
bcount.all = min(pc->request_transfer, 63 * 1024);
- if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
- (void)__ide_dma_off(drive);
- }
+ if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags))
+ ide_dma_off(drive);
+
feature.all = 0;
if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
@@ -1433,7 +1434,8 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
drive->bios_cyl = 0;
drive->bios_head = drive->bios_sect = 0;
- floppy->blocks = floppy->bs_factor = 0;
+ floppy->blocks = 0;
+ floppy->bs_factor = 1;
set_capacity(floppy->disk, 0);
idefloppy_create_read_capacity_cmd(&pc);
@@ -1949,9 +1951,9 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
drive = floppy->drive;
- drive->usage++;
+ floppy->openers++;
- if (drive->usage == 1) {
+ if (floppy->openers == 1) {
clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
/* Just in case */
@@ -1969,13 +1971,11 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
** capacity of the drive or begin the format - Sam
*/
) {
- drive->usage--;
ret = -EIO;
goto out_put_floppy;
}
if (floppy->wp && (filp->f_mode & 2)) {
- drive->usage--;
ret = -EROFS;
goto out_put_floppy;
}
@@ -1987,13 +1987,13 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
}
check_disk_change(inode->i_bdev);
} else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) {
- drive->usage--;
ret = -EBUSY;
goto out_put_floppy;
}
return 0;
out_put_floppy:
+ floppy->openers--;
ide_floppy_put(floppy);
return ret;
}
@@ -2007,7 +2007,7 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
debug_log(KERN_INFO "Reached idefloppy_release\n");
- if (drive->usage == 1) {
+ if (floppy->openers == 1) {
/* IOMEGA Clik! drives do not support lock/unlock commands */
if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
idefloppy_create_prevent_cmd(&pc, 0);
@@ -2016,7 +2016,8 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
}
- drive->usage--;
+
+ floppy->openers--;
ide_floppy_put(floppy);
@@ -2050,7 +2051,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
prevent = 0;
/* fall through */
case CDROM_LOCKDOOR:
- if (drive->usage > 1)
+ if (floppy->openers > 1)
return -EBUSY;
/* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
@@ -2072,7 +2073,7 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
if (!(file->f_mode & 2))
return -EPERM;
- if (drive->usage > 1) {
+ if (floppy->openers > 1) {
/* Don't format if someone is using the disk */
clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 2614f41b507..c193553f6fe 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -226,7 +226,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
break;
if (drive->hwif->ide_dma_check == NULL)
break;
- drive->hwif->ide_dma_check(drive);
+ ide_set_dma(drive);
break;
}
pm->pm_step = ide_pm_state_completed;
@@ -1351,7 +1351,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
*/
drive->retry_pio++;
drive->state = DMA_PIO_RETRY;
- (void) hwif->ide_dma_off_quietly(drive);
+ hwif->dma_off_quietly(drive);
/*
* un-busy drive etc (hwgroup->busy is cleared on return) and
@@ -1646,6 +1646,17 @@ irqreturn_t ide_intr (int irq, void *dev_id)
del_timer(&hwgroup->timer);
spin_unlock(&ide_lock);
+ /* Some controllers might set DMA INTR no matter DMA or PIO;
+ * bmdma status might need to be cleared even for
+ * PIO interrupts to prevent spurious/lost irq.
+ */
+ if (hwif->ide_dma_clear_irq && !(drive->waiting_for_dma))
+ /* ide_dma_end() needs bmdma status for error checking.
+ * So, skip clearing bmdma status here and leave it
+ * to ide_dma_end() if this is dma interrupt.
+ */
+ hwif->ide_dma_clear_irq(drive);
+
if (drive->unmask)
local_irq_enable_in_hardirq();
/* service this interrupt, may set handler for next interrupt */
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index badde633177..c67b3b1e6f4 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -49,11 +49,6 @@ static void ide_insw (unsigned long port, void *addr, u32 count)
insw(port, addr, count);
}
-static u32 ide_inl (unsigned long port)
-{
- return (u32) inl(port);
-}
-
static void ide_insl (unsigned long port, void *addr, u32 count)
{
insl(port, addr, count);
@@ -79,11 +74,6 @@ static void ide_outsw (unsigned long port, void *addr, u32 count)
outsw(port, addr, count);
}
-static void ide_outl (u32 val, unsigned long port)
-{
- outl(val, port);
-}
-
static void ide_outsl (unsigned long port, void *addr, u32 count)
{
outsl(port, addr, count);
@@ -94,12 +84,10 @@ void default_hwif_iops (ide_hwif_t *hwif)
hwif->OUTB = ide_outb;
hwif->OUTBSYNC = ide_outbsync;
hwif->OUTW = ide_outw;
- hwif->OUTL = ide_outl;
hwif->OUTSW = ide_outsw;
hwif->OUTSL = ide_outsl;
hwif->INB = ide_inb;
hwif->INW = ide_inw;
- hwif->INL = ide_inl;
hwif->INSW = ide_insw;
hwif->INSL = ide_insl;
}
@@ -123,11 +111,6 @@ static void ide_mm_insw (unsigned long port, void *addr, u32 count)
__ide_mm_insw((void __iomem *) port, addr, count);
}
-static u32 ide_mm_inl (unsigned long port)
-{
- return (u32) readl((void __iomem *) port);
-}
-
static void ide_mm_insl (unsigned long port, void *addr, u32 count)
{
__ide_mm_insl((void __iomem *) port, addr, count);
@@ -153,11 +136,6 @@ static void ide_mm_outsw (unsigned long port, void *addr, u32 count)
__ide_mm_outsw((void __iomem *) port, addr, count);
}
-static void ide_mm_outl (u32 value, unsigned long port)
-{
- writel(value, (void __iomem *) port);
-}
-
static void ide_mm_outsl (unsigned long port, void *addr, u32 count)
{
__ide_mm_outsl((void __iomem *) port, addr, count);
@@ -170,12 +148,10 @@ void default_hwif_mmiops (ide_hwif_t *hwif)
this one is controller specific! */
hwif->OUTBSYNC = ide_mm_outbsync;
hwif->OUTW = ide_mm_outw;
- hwif->OUTL = ide_mm_outl;
hwif->OUTSW = ide_mm_outsw;
hwif->OUTSL = ide_mm_outsl;
hwif->INB = ide_mm_inb;
hwif->INW = ide_mm_inw;
- hwif->INL = ide_mm_inl;
hwif->INSW = ide_mm_insw;
hwif->INSL = ide_mm_insl;
}
@@ -777,7 +753,7 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed)
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->ide_dma_check) /* check if host supports DMA */
- hwif->ide_dma_host_off(drive);
+ hwif->dma_host_off(drive);
#endif
/*
@@ -854,9 +830,9 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed)
#ifdef CONFIG_BLK_DEV_IDEDMA
if (speed >= XFER_SW_DMA_0)
- hwif->ide_dma_host_on(drive);
+ hwif->dma_host_on(drive);
else if (hwif->ide_dma_check) /* check if host supports DMA */
- hwif->ide_dma_off_quietly(drive);
+ hwif->dma_off_quietly(drive);
#endif
switch(speed) {
@@ -1066,12 +1042,12 @@ static void check_dma_crc(ide_drive_t *drive)
{
#ifdef CONFIG_BLK_DEV_IDEDMA
if (drive->crc_count) {
- (void) HWIF(drive)->ide_dma_off_quietly(drive);
+ drive->hwif->dma_off_quietly(drive);
ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive));
if (drive->current_speed >= XFER_SW_DMA_0)
(void) HWIF(drive)->ide_dma_on(drive);
} else
- (void)__ide_dma_off(drive);
+ ide_dma_off(drive);
#endif
}
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 8237d89eec6..8afce4ceea3 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -205,6 +205,21 @@ int ide_dma_enable (ide_drive_t *drive)
EXPORT_SYMBOL(ide_dma_enable);
+int ide_use_fast_pio(ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+
+ if ((id->capability & 1) && drive->autodma)
+ return 1;
+
+ if ((id->capability & 8) || (id->field_valid & 2))
+ return 1;
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(ide_use_fast_pio);
+
/*
* Standard (generic) timings for PIO modes, from ATA2 specification.
* These timings are for access to the IDE data port register *only*.
@@ -349,7 +364,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p
int use_iordy = 0;
struct hd_driveid* id = drive->id;
int overridden = 0;
- int blacklisted = 0;
if (mode_wanted != 255) {
pio_mode = mode_wanted;
@@ -357,7 +371,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p
pio_mode = 0;
} else if ((pio_mode = ide_scan_pio_blacklist(id->model)) != -1) {
overridden = 1;
- blacklisted = 1;
use_iordy = (pio_mode > 2);
} else {
pio_mode = id->tPIO;
@@ -409,7 +422,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode, ide_p
d->cycle_time = cycle_time ? cycle_time : ide_pio_timings[pio_mode].cycle_time;
d->use_iordy = use_iordy;
d->overridden = overridden;
- d->blacklisted = blacklisted;
}
return pio_mode;
}
@@ -462,8 +474,6 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
return -1;
}
-EXPORT_SYMBOL_GPL(ide_set_xfer_rate);
-
static void ide_dump_opcode(ide_drive_t *drive)
{
struct request *rq;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 176bbc850d6..8afbd6cb94b 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -853,11 +853,11 @@ static void probe_hwif(ide_hwif_t *hwif)
* things, if not checked and cleared.
* PARANOIA!!!
*/
- hwif->ide_dma_off_quietly(drive);
+ hwif->dma_off_quietly(drive);
#ifdef CONFIG_IDEDMA_ONLYDISK
if (drive->media == ide_disk)
#endif
- hwif->ide_dma_check(drive);
+ ide_set_dma(drive);
}
}
}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index c6eec0413a6..4e59239fef7 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1970,7 +1970,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
printk(KERN_ERR "ide-tape: The tape wants to issue more "
"interrupts in DMA mode\n");
printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
- (void)__ide_dma_off(drive);
+ ide_dma_off(drive);
return ide_do_reset(drive);
}
/* Get the number of bytes to transfer on this interrupt. */
@@ -2176,7 +2176,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
printk(KERN_WARNING "ide-tape: DMA disabled, "
"reverting to PIO\n");
- (void)__ide_dma_off(drive);
+ ide_dma_off(drive);
}
if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
dma_ok = !hwif->dma_setup(drive);
@@ -4792,15 +4792,10 @@ static int idetape_open(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ide_tape_obj *tape;
- ide_drive_t *drive;
if (!(tape = ide_tape_get(disk)))
return -ENXIO;
- drive = tape->drive;
-
- drive->usage++;
-
return 0;
}
@@ -4808,9 +4803,6 @@ static int idetape_release(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ide_tape_obj *tape = ide_tape_g(disk);
- ide_drive_t *drive = tape->drive;
-
- drive->usage--;
ide_tape_put(tape);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index c750f6ce770..b3c0818c5c6 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -389,9 +389,8 @@ int ide_hwif_request_regions(ide_hwif_t *hwif)
unsigned long addr;
unsigned int i;
- if (hwif->mmio == 2)
+ if (hwif->mmio)
return 0;
- BUG_ON(hwif->mmio == 1);
addr = hwif->io_ports[IDE_CONTROL_OFFSET];
if (addr && !hwif_request_region(hwif, addr, 1))
goto control_region_busy;
@@ -438,7 +437,7 @@ void ide_hwif_release_regions(ide_hwif_t *hwif)
{
u32 i = 0;
- if (hwif->mmio == 2)
+ if (hwif->mmio)
return;
if (hwif->io_ports[IDE_CONTROL_OFFSET])
release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
@@ -507,23 +506,22 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->ide_dma_end = tmp_hwif->ide_dma_end;
hwif->ide_dma_check = tmp_hwif->ide_dma_check;
hwif->ide_dma_on = tmp_hwif->ide_dma_on;
- hwif->ide_dma_off_quietly = tmp_hwif->ide_dma_off_quietly;
+ hwif->dma_off_quietly = tmp_hwif->dma_off_quietly;
hwif->ide_dma_test_irq = tmp_hwif->ide_dma_test_irq;
- hwif->ide_dma_host_on = tmp_hwif->ide_dma_host_on;
- hwif->ide_dma_host_off = tmp_hwif->ide_dma_host_off;
+ hwif->ide_dma_clear_irq = tmp_hwif->ide_dma_clear_irq;
+ hwif->dma_host_on = tmp_hwif->dma_host_on;
+ hwif->dma_host_off = tmp_hwif->dma_host_off;
hwif->ide_dma_lostirq = tmp_hwif->ide_dma_lostirq;
hwif->ide_dma_timeout = tmp_hwif->ide_dma_timeout;
hwif->OUTB = tmp_hwif->OUTB;
hwif->OUTBSYNC = tmp_hwif->OUTBSYNC;
hwif->OUTW = tmp_hwif->OUTW;
- hwif->OUTL = tmp_hwif->OUTL;
hwif->OUTSW = tmp_hwif->OUTSW;
hwif->OUTSL = tmp_hwif->OUTSL;
hwif->INB = tmp_hwif->INB;
hwif->INW = tmp_hwif->INW;
- hwif->INL = tmp_hwif->INL;
hwif->INSW = tmp_hwif->INSW;
hwif->INSL = tmp_hwif->INSL;
@@ -551,7 +549,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->extra_ports = tmp_hwif->extra_ports;
hwif->autodma = tmp_hwif->autodma;
hwif->udma_four = tmp_hwif->udma_four;
- hwif->no_dsc = tmp_hwif->no_dsc;
hwif->hwif_data = tmp_hwif->hwif_data;
}
@@ -1138,12 +1135,11 @@ static int set_using_dma (ide_drive_t *drive, int arg)
if (HWIF(drive)->ide_dma_check == NULL)
return -EPERM;
if (arg) {
- if (HWIF(drive)->ide_dma_check(drive)) return -EIO;
- if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
- } else {
- if (__ide_dma_off(drive))
+ if (ide_set_dma(drive))
return -EIO;
- }
+ if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
+ } else
+ ide_dma_off(drive);
return 0;
#else
return -EPERM;
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
index 0391a312287..1ed224a01f7 100644
--- a/drivers/ide/legacy/buddha.c
+++ b/drivers/ide/legacy/buddha.c
@@ -215,7 +215,7 @@ fail_base2:
index = ide_register_hw(&hw, &hwif);
if (index != -1) {
- hwif->mmio = 2;
+ hwif->mmio = 1;
printk("ide%d: ", index);
switch(type) {
case BOARD_BUDDHA:
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
index 64d42619ab0..dcfadbbf55d 100644
--- a/drivers/ide/legacy/gayle.c
+++ b/drivers/ide/legacy/gayle.c
@@ -167,7 +167,7 @@ found:
index = ide_register_hw(&hw, &hwif);
if (index != -1) {
- hwif->mmio = 2;
+ hwif->mmio = 1;
switch (i) {
case 0:
printk("ide%d: Gayle IDE interface (A%d style)\n", index,
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
index c48e87e512d..19ccd006f20 100644
--- a/drivers/ide/legacy/ht6560b.c
+++ b/drivers/ide/legacy/ht6560b.c
@@ -143,16 +143,16 @@ static void ht6560b_selectproc (ide_drive_t *drive)
current_timing = timing;
if (drive->media != ide_disk || !drive->present)
select |= HT_PREFETCH_MODE;
- (void) HWIF(drive)->INB(HT_CONFIG_PORT);
- (void) HWIF(drive)->INB(HT_CONFIG_PORT);
- (void) HWIF(drive)->INB(HT_CONFIG_PORT);
- (void) HWIF(drive)->INB(HT_CONFIG_PORT);
- HWIF(drive)->OUTB(select, HT_CONFIG_PORT);
+ (void)inb(HT_CONFIG_PORT);
+ (void)inb(HT_CONFIG_PORT);
+ (void)inb(HT_CONFIG_PORT);
+ (void)inb(HT_CONFIG_PORT);
+ outb(select, HT_CONFIG_PORT);
/*
* Set timing for this drive:
*/
- HWIF(drive)->OUTB(timing, IDE_SELECT_REG);
- (void) HWIF(drive)->INB(IDE_STATUS_REG);
+ outb(timing, IDE_SELECT_REG);
+ (void)inb(IDE_STATUS_REG);
#ifdef DEBUG
printk("ht6560b: %s: select=%#x timing=%#x\n",
drive->name, select, timing);
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index b1730d7e414..4c0079ad52a 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -141,7 +141,7 @@ void macide_init(void)
}
if (index != -1) {
- hwif->mmio = 2;
+ hwif->mmio = 1;
if (macintosh_config->ide_type == MAC_IDE_QUADRA)
printk(KERN_INFO "ide%d: Macintosh Quadra IDE interface\n", index);
else if (macintosh_config->ide_type == MAC_IDE_PB)
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index 434a94faa3b..74f08124eab 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -145,7 +145,7 @@ void q40ide_init(void)
index = ide_register_hw(&hw, &hwif);
// **FIXME**
if (index != -1)
- hwif->mmio = 2;
+ hwif->mmio = 1;
}
}
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index c7854ea57b5..0a59d5ef159 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -181,12 +181,6 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
{
int mem_sttime;
int mem_stcfg;
- unsigned long mode;
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
- if (ide_use_dma(drive))
- mode = ide_dma_speed(drive, 0);
-#endif
mem_sttime = 0;
mem_stcfg = au_readl(MEM_STCFG2);
@@ -195,7 +189,7 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
auide_tune_drive(drive, speed - XFER_PIO_0);
return 0;
}
-
+
switch(speed) {
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
case XFER_MW_DMA_2:
@@ -207,7 +201,6 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
mem_stcfg &= ~TOECS_MASK;
mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS;
- mode = XFER_MW_DMA_2;
break;
case XFER_MW_DMA_1:
mem_sttime = SBC_IDE_TIMING(MDMA1);
@@ -218,7 +211,6 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
mem_stcfg &= ~TOECS_MASK;
mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS;
- mode = XFER_MW_DMA_1;
break;
case XFER_MW_DMA_0:
mem_sttime = SBC_IDE_TIMING(MDMA0);
@@ -229,14 +221,13 @@ static int auide_tune_chipset (ide_drive_t *drive, u8 speed)
mem_stcfg &= ~TOECS_MASK;
mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS;
- mode = XFER_MW_DMA_0;
break;
#endif
default:
return 1;
}
-
- if (ide_config_drive_speed(drive, mode))
+
+ if (ide_config_drive_speed(drive, speed))
return 1;
au_writel(mem_sttime,MEM_STTIME2);
@@ -423,9 +414,9 @@ static int auide_dma_check(ide_drive_t *drive)
speed = ide_find_best_mode(drive, XFER_PIO | XFER_MWDMA);
if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
- return HWIF(drive)->ide_dma_on(drive);
+ return 0;
- return HWIF(drive)->ide_dma_off_quietly(drive);
+ return -1;
}
static int auide_dma_test_irq(ide_drive_t *drive)
@@ -447,27 +438,24 @@ static int auide_dma_test_irq(ide_drive_t *drive)
return 0;
}
-static int auide_dma_host_on(ide_drive_t *drive)
+static void auide_dma_host_on(ide_drive_t *drive)
{
- return 0;
}
static int auide_dma_on(ide_drive_t *drive)
{
drive->using_dma = 1;
- return auide_dma_host_on(drive);
-}
+ return 0;
+}
-static int auide_dma_host_off(ide_drive_t *drive)
+static void auide_dma_host_off(ide_drive_t *drive)
{
- return 0;
}
-static int auide_dma_off_quietly(ide_drive_t *drive)
+static void auide_dma_off_quietly(ide_drive_t *drive)
{
drive->using_dma = 0;
- return auide_dma_host_off(drive);
}
static int auide_dma_lostirq(ide_drive_t *drive)
@@ -717,7 +705,8 @@ static int au_ide_probe(struct device *dev)
/* hold should be on in all cases */
hwif->hold = 1;
- hwif->mmio = 2;
+
+ hwif->mmio = 1;
/* If the user has selected DDMA assisted copies,
then set up a few local I/O function entry points
@@ -732,7 +721,7 @@ static int au_ide_probe(struct device *dev)
hwif->speedproc = &auide_tune_chipset;
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
- hwif->ide_dma_off_quietly = &auide_dma_off_quietly;
+ hwif->dma_off_quietly = &auide_dma_off_quietly;
hwif->ide_dma_timeout = &auide_dma_timeout;
hwif->ide_dma_check = &auide_dma_check;
@@ -741,8 +730,8 @@ static int au_ide_probe(struct device *dev)
hwif->ide_dma_end = &auide_dma_end;
hwif->dma_setup = &auide_dma_setup;
hwif->ide_dma_test_irq = &auide_dma_test_irq;
- hwif->ide_dma_host_off = &auide_dma_host_off;
- hwif->ide_dma_host_on = &auide_dma_host_on;
+ hwif->dma_host_off = &auide_dma_host_off;
+ hwif->dma_host_on = &auide_dma_host_on;
hwif->ide_dma_lostirq = &auide_dma_lostirq;
hwif->ide_dma_on = &auide_dma_on;
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
index 09c9e7936b0..81fa06851b2 100644
--- a/drivers/ide/mips/swarm.c
+++ b/drivers/ide/mips/swarm.c
@@ -115,7 +115,7 @@ static int __devinit swarm_ide_probe(struct device *dev)
/* Setup MMIO ops. */
default_hwif_mmiops(hwif);
/* Prevent resource map manipulation. */
- hwif->mmio = 2;
+ hwif->mmio = 1;
hwif->noprobe = 0;
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index d261bfbad22..990eafe5ea1 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -94,9 +94,9 @@ static u8 aec62xx_ratemask (ide_drive_t *drive)
switch(hwif->pci_dev->device) {
case PCI_DEVICE_ID_ARTOP_ATP865:
case PCI_DEVICE_ID_ARTOP_ATP865R:
- mode = (hwif->INB(((hwif->channel) ?
- hwif->mate->dma_status :
- hwif->dma_status)) & 0x10) ? 4 : 3;
+ mode = (inb(hwif->channel ?
+ hwif->mate->dma_status :
+ hwif->dma_status) & 0x10) ? 4 : 3;
break;
case PCI_DEVICE_ID_ARTOP_ATP860:
case PCI_DEVICE_ID_ARTOP_ATP860R:
@@ -209,25 +209,13 @@ static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio)
static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
- if ((id->capability & 1) && drive->autodma) {
-
- if (ide_use_dma(drive)) {
- if (config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
-
- goto fast_ata_pio;
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive))
aec62xx_tune_drive(drive, 5);
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
+
+ return -1;
}
static int aec62xx_irq_timeout (ide_drive_t *drive)
@@ -286,10 +274,8 @@ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
hwif->tuneproc = &aec62xx_tune_drive;
hwif->speedproc = &aec62xx_tune_chipset;
- if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+ if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
hwif->serialized = hwif->channel;
- hwif->no_dsc = 1;
- }
if (hwif->mate)
hwif->mate->serialized = hwif->serialized;
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 68df77ec502..4debd18d52f 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -507,17 +507,15 @@ static int config_chipset_for_dma (ide_drive_t *drive)
*
* Configure a drive for DMA operation. If DMA is not possible we
* drop the drive into PIO mode instead.
- *
- * FIXME: exactly what are we trying to return here
*/
-
+
static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct hd_driveid *id = drive->id;
if ((m5229_revision<=0x20) && (drive->media!=ide_disk))
- return hwif->ide_dma_off_quietly(drive);
+ goto no_dma_set;
drive->init_speed = 0;
@@ -552,9 +550,10 @@ try_dma_modes:
ata_pio:
hwif->tuneproc(drive, 255);
no_dma_set:
- return hwif->ide_dma_off_quietly(drive);
+ return -1;
}
- return hwif->ide_dma_on(drive);
+
+ return 0;
}
/**
@@ -852,8 +851,8 @@ static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
{
if (m5229_revision < 0x20)
return;
- if (!(hwif->channel))
- hwif->OUTB(hwif->INB(dmabase+2) & 0x60, dmabase+2);
+ if (!hwif->channel)
+ outb(inb(dmabase + 2) & 0x60, dmabase + 2);
ide_setup_dma(hwif, dmabase, 8);
}
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index a4336995a41..7989bdd842a 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -304,8 +304,9 @@ static int amd74xx_ide_dma_check(ide_drive_t *drive)
amd_set_drive(drive, speed);
if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
- return HWIF(drive)->ide_dma_on(drive);
- return HWIF(drive)->ide_dma_off_quietly(drive);
+ return 0;
+
+ return -1;
}
/*
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 982ac31fa99..2d48af32e3f 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -101,7 +101,7 @@ static u8 atiixp_dma_2_pio(u8 xfer_rate) {
}
}
-static int atiixp_ide_dma_host_on(ide_drive_t *drive)
+static void atiixp_dma_host_on(ide_drive_t *drive)
{
struct pci_dev *dev = drive->hwif->pci_dev;
unsigned long flags;
@@ -118,10 +118,10 @@ static int atiixp_ide_dma_host_on(ide_drive_t *drive)
spin_unlock_irqrestore(&atiixp_lock, flags);
- return __ide_dma_host_on(drive);
+ ide_dma_host_on(drive);
}
-static int atiixp_ide_dma_host_off(ide_drive_t *drive)
+static void atiixp_dma_host_off(ide_drive_t *drive)
{
struct pci_dev *dev = drive->hwif->pci_dev;
unsigned long flags;
@@ -135,7 +135,7 @@ static int atiixp_ide_dma_host_off(ide_drive_t *drive)
spin_unlock_irqrestore(&atiixp_lock, flags);
- return __ide_dma_host_off(drive);
+ ide_dma_host_off(drive);
}
/**
@@ -235,11 +235,8 @@ static int atiixp_config_drive_for_dma(ide_drive_t *drive)
{
u8 speed = ide_dma_speed(drive, atiixp_ratemask(drive));
- /* If no DMA speed was available then disable DMA and use PIO. */
- if (!speed) {
- u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
- speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
- }
+ if (!speed)
+ return 0;
(void) atiixp_speedproc(drive, speed);
return ide_dma_enable(drive);
@@ -255,30 +252,20 @@ static int atiixp_config_drive_for_dma(ide_drive_t *drive)
static int atiixp_dma_check(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
u8 tspeed, speed;
drive->init_speed = 0;
- if ((id->capability & 1) && drive->autodma) {
-
- if (ide_use_dma(drive)) {
- if (atiixp_config_drive_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
-
- goto fast_ata_pio;
+ if (ide_use_dma(drive) && atiixp_config_drive_for_dma(drive))
+ return 0;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive)) {
tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
- hwif->speedproc(drive, speed);
- return hwif->ide_dma_off_quietly(drive);
+ atiixp_speedproc(drive, speed);
}
- /* IORDY not supported */
- return 0;
+
+ return -1;
}
/**
@@ -318,8 +305,8 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
else
hwif->udma_four = 0;
- hwif->ide_dma_host_on = &atiixp_ide_dma_host_on;
- hwif->ide_dma_host_off = &atiixp_ide_dma_host_off;
+ hwif->dma_host_on = &atiixp_dma_host_on;
+ hwif->dma_host_off = &atiixp_dma_host_off;
hwif->ide_dma_check = &atiixp_dma_check;
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index aee947e8fc3..49df27513da 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -466,36 +466,21 @@ static int config_chipset_for_dma (ide_drive_t *drive)
if (!speed)
return 0;
- if(ide_set_xfer_rate(drive, speed))
- return 0;
-
- if (!drive->init_speed)
- drive->init_speed = speed;
+ if (cmd64x_tune_chipset(drive, speed))
+ return 0;
return ide_dma_enable(drive);
}
static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
- if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) {
-
- if (ide_use_dma(drive)) {
- if (config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
-
- goto fast_ata_pio;
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive))
config_chipset_for_pio(drive, 1);
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
+
+ return -1;
}
static int cmd64x_alt_dma_status (struct pci_dev *dev)
@@ -518,13 +503,13 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive)
drive->waiting_for_dma = 0;
/* read DMA command state */
- dma_cmd = hwif->INB(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_command);
/* stop DMA */
- hwif->OUTB((dma_cmd & ~1), hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_command);
/* get DMA status */
- dma_stat = hwif->INB(hwif->dma_status);
+ dma_stat = inb(hwif->dma_status);
/* clear the INTR & ERROR bits */
- hwif->OUTB(dma_stat|6, hwif->dma_status);
+ outb(dma_stat | 6, hwif->dma_status);
if (cmd64x_alt_dma_status(dev)) {
u8 dma_intr = 0;
u8 dma_mask = (hwif->channel) ? ARTTIM23_INTR_CH1 :
@@ -546,7 +531,7 @@ static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
struct pci_dev *dev = hwif->pci_dev;
u8 dma_alt_stat = 0, mask = (hwif->channel) ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
- u8 dma_stat = hwif->INB(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_status);
(void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat);
#ifdef DEBUG
@@ -576,13 +561,13 @@ static int cmd646_1_ide_dma_end (ide_drive_t *drive)
drive->waiting_for_dma = 0;
/* get DMA status */
- dma_stat = hwif->INB(hwif->dma_status);
+ dma_stat = inb(hwif->dma_status);
/* read DMA command state */
- dma_cmd = hwif->INB(hwif->dma_command);
+ dma_cmd = inb(hwif->dma_command);
/* stop DMA */
- hwif->OUTB((dma_cmd & ~1), hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_command);
/* clear the INTR & ERROR bits */
- hwif->OUTB(dma_stat|6, hwif->dma_status);
+ outb(dma_stat | 6, hwif->dma_status);
/* and free any DMA resources */
ide_destroy_dmatable(drive);
/* verify good DMA status */
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index ba6786aabf3..400859a839f 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -132,12 +132,11 @@ static void cs5520_tune_drive(ide_drive_t *drive, u8 pio)
static int cs5520_config_drive_xfer_rate(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
-
/* Tune the drive for PIO modes up to PIO 4 */
cs5520_tune_drive(drive, 4);
+
/* Then tell the core to use DMA operations */
- return hwif->ide_dma_on(drive);
+ return 0;
}
/*
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index 9bf5fdfc5b1..b2d7c132ef4 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -81,8 +81,8 @@ static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autot
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
if (!cs5530_set_xfer_mode(drive, modes[pio])) {
- format = (hwif->INL(basereg+4) >> 31) & 1;
- hwif->OUTL(cs5530_pio_timings[format][pio],
+ format = (inl(basereg + 4) >> 31) & 1;
+ outl(cs5530_pio_timings[format][pio],
basereg+(drive->select.b.unit<<3));
}
}
@@ -103,16 +103,13 @@ static int cs5530_config_dma (ide_drive_t *drive)
int unit = drive->select.b.unit;
ide_drive_t *mate = &hwif->drives[unit^1];
struct hd_driveid *id = drive->id;
- unsigned int reg, timings;
+ unsigned int reg, timings = 0;
unsigned long basereg;
/*
* Default to DMA-off in case we run into trouble here.
*/
- hwif->ide_dma_off_quietly(drive);
- /* turn off DMA while we fiddle */
- hwif->ide_dma_host_off(drive);
- /* clear DMA_capable bit */
+ hwif->dma_off_quietly(drive);
/*
* The CS5530 specifies that two drives sharing a cable cannot
@@ -182,30 +179,24 @@ static int cs5530_config_dma (ide_drive_t *drive)
case XFER_MW_DMA_1: timings = 0x00012121; break;
case XFER_MW_DMA_2: timings = 0x00002020; break;
default:
- printk(KERN_ERR "%s: cs5530_config_dma: huh? mode=%02x\n",
- drive->name, mode);
- return 1; /* failure */
+ BUG();
+ break;
}
basereg = CS5530_BASEREG(hwif);
- reg = hwif->INL(basereg+4); /* get drive0 config register */
+ reg = inl(basereg + 4); /* get drive0 config register */
timings |= reg & 0x80000000; /* preserve PIO format bit */
if (unit == 0) { /* are we configuring drive0? */
- hwif->OUTL(timings, basereg+4); /* write drive0 config register */
+ outl(timings, basereg + 4); /* write drive0 config register */
} else {
if (timings & 0x00100000)
reg |= 0x00100000; /* enable UDMA timings for both drives */
else
reg &= ~0x00100000; /* disable UDMA timings for both drives */
- hwif->OUTL(reg, basereg+4); /* write drive0 config register */
- hwif->OUTL(timings, basereg+12); /* write drive1 config register */
+ outl(reg, basereg + 4); /* write drive0 config register */
+ outl(timings, basereg + 12); /* write drive1 config register */
}
- (void) hwif->ide_dma_host_on(drive);
- /* set DMA_capable bit */
- /*
- * Finally, turn DMA on in software, and exit.
- */
- return hwif->ide_dma_on(drive); /* success */
+ return 0; /* success */
}
/**
@@ -321,17 +312,17 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
hwif->tuneproc = &cs5530_tuneproc;
basereg = CS5530_BASEREG(hwif);
- d0_timings = hwif->INL(basereg+0);
+ d0_timings = inl(basereg + 0);
if (CS5530_BAD_PIO(d0_timings)) {
/* PIO timings not initialized? */
- hwif->OUTL(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0);
+ outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0);
if (!hwif->drives[0].autotune)
hwif->drives[0].autotune = 1;
/* needs autotuning later */
}
- if (CS5530_BAD_PIO(hwif->INL(basereg+8))) {
- /* PIO timings not initialized? */
- hwif->OUTL(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8);
+ if (CS5530_BAD_PIO(inl(basereg + 8))) {
+ /* PIO timings not initialized? */
+ outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8);
if (!hwif->drives[1].autotune)
hwif->drives[1].autotune = 1;
/* needs autotuning later */
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 5c5aec28e67..45f43efbf92 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -195,28 +195,19 @@ static int cs5535_config_drive_for_dma(ide_drive_t *drive)
static int cs5535_dma_check(ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
- struct hd_driveid *id = drive->id;
u8 speed;
drive->init_speed = 0;
- if ((id->capability & 1) && drive->autodma) {
- if (ide_use_dma(drive)) {
- if (cs5535_config_drive_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
-
- goto fast_ata_pio;
+ if (ide_use_dma(drive) && cs5535_config_drive_for_dma(drive))
+ return 0;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive)) {
speed = ide_get_best_pio_mode(drive, 255, 4, NULL);
cs5535_set_drive(drive, speed);
- return hwif->ide_dma_off_quietly(drive);
}
- /* IORDY not supported */
- return 0;
+
+ return -1;
}
static u8 __devinit cs5535_cable_detect(struct pci_dev *dev)
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index 9eafcbf444f..103b9db9785 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -197,8 +197,8 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
#if CY82C693_DEBUG_LOGS
/* for debug let's show the previous values */
- HWIF(drive)->OUTB(index, CY82_INDEX_PORT);
- data = HWIF(drive)->INB(CY82_DATA_PORT);
+ outb(index, CY82_INDEX_PORT);
+ data = inb(CY82_DATA_PORT);
printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
drive->name, HWIF(drive)->channel, drive->select.b.unit,
@@ -207,8 +207,8 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
data = (u8)mode|(u8)(single<<2);
- HWIF(drive)->OUTB(index, CY82_INDEX_PORT);
- HWIF(drive)->OUTB(data, CY82_DATA_PORT);
+ outb(index, CY82_INDEX_PORT);
+ outb(data, CY82_DATA_PORT);
#if CY82C693_DEBUG_INFO
printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n",
@@ -227,8 +227,8 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
*/
data = BUSMASTER_TIMEOUT;
- HWIF(drive)->OUTB(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
- HWIF(drive)->OUTB(data, CY82_DATA_PORT);
+ outb(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
+ outb(data, CY82_DATA_PORT);
#if CY82C693_DEBUG_INFO
printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n",
@@ -478,21 +478,18 @@ static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
}
}
-static ide_pci_device_t cy82c693_chipsets[] __devinitdata = {
- { /* 0 */
- .name = "CY82C693",
- .init_chipset = init_chipset_cy82c693,
- .init_iops = init_iops_cy82c693,
- .init_hwif = init_hwif_cy82c693,
- .channels = 1,
- .autodma = AUTODMA,
- .bootable = ON_BOARD,
- }
+static ide_pci_device_t cy82c693_chipset __devinitdata = {
+ .name = "CY82C693",
+ .init_chipset = init_chipset_cy82c693,
+ .init_iops = init_iops_cy82c693,
+ .init_hwif = init_hwif_cy82c693,
+ .channels = 1,
+ .autodma = AUTODMA,
+ .bootable = ON_BOARD,
};
static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &cy82c693_chipsets[id->driver_data];
struct pci_dev *dev2;
int ret = -ENODEV;
@@ -501,7 +498,7 @@ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_dev
if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
PCI_FUNC(dev->devfn) == 1) {
dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
- ret = ide_setup_pci_devices(dev, dev2, d);
+ ret = ide_setup_pci_devices(dev, dev2, &cy82c693_chipset);
/* We leak pci refs here but thats ok - we can't be unloaded */
}
return ret;
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index ce7b08f08a0..924eaa3a570 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -48,19 +48,6 @@ static u8 hpt34x_ratemask (ide_drive_t *drive)
return 1;
}
-static void hpt34x_clear_chipset (ide_drive_t *drive)
-{
- struct pci_dev *dev = HWIF(drive)->pci_dev;
- u32 reg1 = 0, tmp1 = 0, reg2 = 0, tmp2 = 0;
-
- pci_read_config_dword(dev, 0x44, &reg1);
- pci_read_config_dword(dev, 0x48, &reg2);
- tmp1 = ((0x00 << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
- tmp2 = (reg2 & ~(0x11 << drive->dn));
- pci_write_config_dword(dev, 0x44, tmp1);
- pci_write_config_dword(dev, 0x48, tmp2);
-}
-
static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
{
struct pci_dev *dev = HWIF(drive)->pci_dev;
@@ -81,7 +68,7 @@ static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
pci_read_config_dword(dev, 0x44, &reg1);
pci_read_config_dword(dev, 0x48, &reg2);
tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
- tmp2 = ((hi_speed << drive->dn) | reg2);
+ tmp2 = ((hi_speed << drive->dn) | (reg2 & ~(0x11 << drive->dn)));
pci_write_config_dword(dev, 0x44, tmp1);
pci_write_config_dword(dev, 0x48, tmp2);
@@ -99,7 +86,6 @@ static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
static void hpt34x_tune_drive (ide_drive_t *drive, u8 pio)
{
pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
- hpt34x_clear_chipset(drive);
(void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio));
}
@@ -117,38 +103,25 @@ static int config_chipset_for_dma (ide_drive_t *drive)
if (!(speed))
return 0;
- hpt34x_clear_chipset(drive);
(void) hpt34x_tune_chipset(drive, speed);
return ide_dma_enable(drive);
}
static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
drive->init_speed = 0;
- if (id && (id->capability & 1) && drive->autodma) {
-
- if (ide_use_dma(drive)) {
- if (config_chipset_for_dma(drive))
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
#ifndef CONFIG_HPT34X_AUTODMA
- return hwif->ide_dma_off_quietly(drive);
+ return -1;
#else
- return hwif->ide_dma_on(drive);
+ return 0;
#endif
- }
-
- goto fast_ata_pio;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive))
hpt34x_tune_drive(drive, 255);
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
+
+ return -1;
}
/*
@@ -209,7 +182,6 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif)
hwif->tuneproc = &hpt34x_tune_drive;
hwif->speedproc = &hpt34x_tune_chipset;
- hwif->no_dsc = 1;
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 05be8fadda7..60ecdc258c7 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -736,24 +736,15 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
static int hpt366_config_drive_xfer_rate(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
drive->init_speed = 0;
- if ((id->capability & 1) && drive->autodma) {
- if (ide_use_dma(drive) && config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
-
- goto fast_ata_pio;
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive))
hpt3xx_tune_drive(drive, 255);
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
+
+ return -1;
}
/*
@@ -841,7 +832,7 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
return 0;
}
- dma_stat = hwif->INB(hwif->dma_status);
+ dma_stat = inb(hwif->dma_status);
/* return 1 if INTR asserted */
if (dma_stat & 4)
return 1;
@@ -1391,9 +1382,6 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
u8 dma_new = 0, dma_old = 0;
unsigned long flags;
- if (!dmabase)
- return;
-
dma_old = hwif->INB(dmabase + 2);
local_irq_save(flags);
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index 63248b6909f..424f00bb160 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -244,17 +244,15 @@ static int config_chipset_for_dma (ide_drive_t *drive)
static int it8213_config_drive_for_dma (ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
+ u8 pio;
- if (ide_use_dma(drive)) {
- if (config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- hwif->speedproc(drive, XFER_PIO_0
- + ide_get_best_pio_mode(drive, 255, 4, NULL));
+ pio = ide_get_best_pio_mode(drive, 255, 4, NULL);
+ it8213_tune_chipset(drive, XFER_PIO_0 + pio);
- return hwif->ide_dma_off_quietly(drive);
+ return -1;
}
/**
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index e9bad185968..a132767f7d9 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -520,14 +520,12 @@ static int config_chipset_for_dma (ide_drive_t *drive)
static int it821x_config_drive_for_dma (ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- if (ide_use_dma(drive)) {
- if (config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
config_it821x_chipset_for_pio(drive, 1);
- return hwif->ide_dma_off_quietly(drive);
+
+ return -1;
}
/**
@@ -608,11 +606,11 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
printk(".\n");
/* Now the core code will have wrongly decided no DMA
so we need to fix this */
- hwif->ide_dma_off_quietly(drive);
+ hwif->dma_off_quietly(drive);
#ifdef CONFIG_IDEDMA_ONLYDISK
if (drive->media == ide_disk)
#endif
- hwif->ide_dma_check(drive);
+ ide_set_dma(drive);
} else {
/* Non RAID volume. Fixups to stop the core code
doing unsupported things */
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index f07bbbed177..53f25500c22 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -147,7 +147,9 @@ static int config_chipset_for_dma (ide_drive_t *drive)
{
u8 speed = ide_dma_speed(drive, jmicron_ratemask(drive));
- config_jmicron_chipset_for_pio(drive, !speed);
+ if (!speed)
+ return 0;
+
jmicron_tune_chipset(drive, speed);
return ide_dma_enable(drive);
}
@@ -162,14 +164,12 @@ static int config_chipset_for_dma (ide_drive_t *drive)
static int jmicron_config_drive_for_dma (ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- if (ide_use_dma(drive)) {
- if (config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
config_jmicron_chipset_for_pio(drive, 1);
- return hwif->ide_dma_off_quietly(drive);
+
+ return -1;
}
/**
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index 8aaea4ea554..b310c4f5107 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -166,10 +166,10 @@ static int ns87415_ide_dma_end (ide_drive_t *drive)
/* get dma command mode */
dma_cmd = hwif->INB(hwif->dma_command);
/* stop DMA */
- hwif->OUTB(dma_cmd & ~1, hwif->dma_command);
+ outb(dma_cmd & ~1, hwif->dma_command);
/* from ERRATA: clear the INTR & ERROR bits */
dma_cmd = hwif->INB(hwif->dma_command);
- hwif->OUTB(dma_cmd|6, hwif->dma_command);
+ outb(dma_cmd | 6, hwif->dma_command);
/* and free any DMA resources */
ide_destroy_dmatable(drive);
/* verify good DMA status */
@@ -190,7 +190,8 @@ static int ns87415_ide_dma_setup(ide_drive_t *drive)
static int ns87415_ide_dma_check (ide_drive_t *drive)
{
if (drive->media != ide_disk)
- return HWIF(drive)->ide_dma_off_quietly(drive);
+ return -1;
+
return __ide_dma_check(drive);
}
@@ -243,9 +244,9 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
* to SELECT_DRIVE() properly during first probe_hwif().
*/
timeout = 10000;
- hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
udelay(10);
- hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ outb(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
do {
udelay(50);
stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
@@ -263,7 +264,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
if (!hwif->dma_base)
return;
- hwif->OUTB(0x60, hwif->dma_status);
+ outb(0x60, hwif->dma_status);
hwif->dma_setup = &ns87415_ide_dma_setup;
hwif->ide_dma_check = &ns87415_ide_dma_check;
hwif->ide_dma_end = &ns87415_ide_dma_end;
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index 22bbf613f94..9ca60dd2185 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -176,34 +176,35 @@ static int cmpt_clk(int time, int bus_speed)
return ((time*bus_speed+999)/1000);
}
-static void write_reg(ide_hwif_t *hwif, u8 value, int reg)
/* Write value to register reg, base of register
* is at reg_base (0x1f0 primary, 0x170 secondary,
* if not changed by PCI configuration).
* This is from setupvic.exe program.
*/
+static void write_reg(u8 value, int reg)
{
- hwif->INW(reg_base+1);
- hwif->INW(reg_base+1);
- hwif->OUTB(3, reg_base+2);
- hwif->OUTB(value, reg_base+reg);
- hwif->OUTB(0x83, reg_base+2);
+ inw(reg_base + 1);
+ inw(reg_base + 1);
+ outb(3, reg_base + 2);
+ outb(value, reg_base + reg);
+ outb(0x83, reg_base + 2);
}
-static u8 read_reg(ide_hwif_t *hwif, int reg)
/* Read value from register reg, base of register
* is at reg_base (0x1f0 primary, 0x170 secondary,
* if not changed by PCI configuration).
* This is from setupvic.exe program.
*/
+static u8 read_reg(int reg)
{
u8 ret = 0;
- hwif->INW(reg_base+1);
- hwif->INW(reg_base+1);
- hwif->OUTB(3, reg_base+2);
- ret = hwif->INB(reg_base+reg);
- hwif->OUTB(0x83, reg_base+2);
+ inw(reg_base + 1);
+ inw(reg_base + 1);
+ outb(3, reg_base + 2);
+ ret = inb(reg_base + reg);
+ outb(0x83, reg_base + 2);
+
return ret;
}
@@ -286,39 +287,39 @@ static void opti621_tune_drive (ide_drive_t *drive, u8 pio)
reg_base = hwif->io_ports[IDE_DATA_OFFSET];
/* allow Register-B */
- hwif->OUTB(0xc0, reg_base+CNTRL_REG);
+ outb(0xc0, reg_base + CNTRL_REG);
/* hmm, setupvic.exe does this ;-) */
- hwif->OUTB(0xff, reg_base+5);
+ outb(0xff, reg_base + 5);
/* if reads 0xff, adapter not exist? */
- (void) hwif->INB(reg_base+CNTRL_REG);
+ (void)inb(reg_base + CNTRL_REG);
/* if reads 0xc0, no interface exist? */
- read_reg(hwif, CNTRL_REG);
+ read_reg(CNTRL_REG);
/* read version, probably 0 */
- read_reg(hwif, STRAP_REG);
+ read_reg(STRAP_REG);
/* program primary drive */
- /* select Index-0 for Register-A */
- write_reg(hwif, 0, MISC_REG);
- /* set read cycle timings */
- write_reg(hwif, cycle1, READ_REG);
- /* set write cycle timings */
- write_reg(hwif, cycle1, WRITE_REG);
+ /* select Index-0 for Register-A */
+ write_reg(0, MISC_REG);
+ /* set read cycle timings */
+ write_reg(cycle1, READ_REG);
+ /* set write cycle timings */
+ write_reg(cycle1, WRITE_REG);
/* program secondary drive */
- /* select Index-1 for Register-B */
- write_reg(hwif, 1, MISC_REG);
- /* set read cycle timings */
- write_reg(hwif, cycle2, READ_REG);
- /* set write cycle timings */
- write_reg(hwif, cycle2, WRITE_REG);
+ /* select Index-1 for Register-B */
+ write_reg(1, MISC_REG);
+ /* set read cycle timings */
+ write_reg(cycle2, READ_REG);
+ /* set write cycle timings */
+ write_reg(cycle2, WRITE_REG);
/* use Register-A for drive 0 */
/* use Register-B for drive 1 */
- write_reg(hwif, 0x85, CNTRL_REG);
+ write_reg(0x85, CNTRL_REG);
/* set address setup, DRDY timings, */
/* and read prefetch for both drives */
- write_reg(hwif, misc, MISC_REG);
+ write_reg(misc, MISC_REG);
spin_unlock_irqrestore(&ide_lock, flags);
}
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 236a03144a2..6ceb25bc5a7 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -101,8 +101,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
{
u8 value;
- hwif->OUTB(index, hwif->dma_vendor1);
- value = hwif->INB(hwif->dma_vendor3);
+ outb(index, hwif->dma_vendor1);
+ value = inb(hwif->dma_vendor3);
DBG("index[%02X] value[%02X]\n", index, value);
return value;
@@ -115,8 +115,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
*/
static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value)
{
- hwif->OUTB(index, hwif->dma_vendor1);
- hwif->OUTB(value, hwif->dma_vendor3);
+ outb(index, hwif->dma_vendor1);
+ outb(value, hwif->dma_vendor3);
DBG("index[%02X] value[%02X]\n", index, value);
}
@@ -281,25 +281,15 @@ static int config_chipset_for_dma(ide_drive_t *drive)
static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
drive->init_speed = 0;
- if ((id->capability & 1) && drive->autodma) {
-
- if (ide_use_dma(drive) && config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- goto fast_ata_pio;
+ if (ide_use_fast_pio(drive))
+ pdcnew_tune_drive(drive, 255);
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
- hwif->tuneproc(drive, 255);
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
+ return -1;
}
static int pdcnew_quirkproc(ide_drive_t *drive)
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 730e8d1ec2f..a7a639fe1ea 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -2,6 +2,7 @@
* linux/drivers/ide/pci/pdc202xx_old.c Version 0.36 Sept 11, 2002
*
* Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2006-2007 MontaVista Software, Inc.
*
* Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this
* compiled into the kernel if you have more than one card installed.
@@ -216,21 +217,10 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
}
-/* 0 1 2 3 4 5 6 7 8
- * 960, 480, 390, 300, 240, 180, 120, 90, 60
- * 180, 150, 120, 90, 60
- * DMA_Speed
- * 180, 120, 90, 90, 90, 60, 30
- * 11, 5, 4, 3, 2, 1, 0
- */
-static void config_chipset_for_pio (ide_drive_t *drive, u8 pio)
+static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio)
{
- u8 speed = 0;
-
- if (pio == 5) pio = 4;
- speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL);
-
- pdc202xx_tune_chipset(drive, speed);
+ pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+ pdc202xx_tune_chipset(drive, XFER_PIO_0 + pio);
}
static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
@@ -250,17 +240,17 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
{
unsigned long clock_reg = hwif->dma_master + 0x11;
- u8 clock = hwif->INB(clock_reg);
+ u8 clock = inb(clock_reg);
- hwif->OUTB(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
+ outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
}
static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
{
unsigned long clock_reg = hwif->dma_master + 0x11;
- u8 clock = hwif->INB(clock_reg);
+ u8 clock = inb(clock_reg);
- hwif->OUTB(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
+ outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
}
static int config_chipset_for_dma (ide_drive_t *drive)
@@ -332,27 +322,15 @@ chipset_is_set:
static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
drive->init_speed = 0;
- if (id && (id->capability & 1) && drive->autodma) {
-
- if (ide_use_dma(drive)) {
- if (config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- goto fast_ata_pio;
+ if (ide_use_fast_pio(drive))
+ pdc202xx_tune_drive(drive, 255);
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
- hwif->tuneproc(drive, 5);
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
+ return -1;
}
static int pdc202xx_quirkproc (ide_drive_t *drive)
@@ -375,14 +353,14 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
unsigned long high_16 = hwif->dma_master;
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
u32 word_count = 0;
- u8 clock = hwif->INB(high_16 + 0x11);
+ u8 clock = inb(high_16 + 0x11);
- hwif->OUTB(clock|(hwif->channel ? 0x08 : 0x02), high_16+0x11);
+ outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11);
word_count = (rq->nr_sectors << 8);
word_count = (rq_data_dir(rq) == READ) ?
word_count | 0x05000000 :
word_count | 0x06000000;
- hwif->OUTL(word_count, atapi_reg);
+ outl(word_count, atapi_reg);
}
ide_dma_start(drive);
}
@@ -395,9 +373,9 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
u8 clock = 0;
- hwif->OUTL(0, atapi_reg); /* zero out extra */
- clock = hwif->INB(high_16 + 0x11);
- hwif->OUTB(clock & ~(hwif->channel ? 0x08:0x02), high_16+0x11);
+ outl(0, atapi_reg); /* zero out extra */
+ clock = inb(high_16 + 0x11);
+ outb(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11);
}
if (drive->current_speed > XFER_UDMA_2)
pdc_old_disable_66MHz_clock(drive->hwif);
@@ -408,8 +386,8 @@ static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long high_16 = hwif->dma_master;
- u8 dma_stat = hwif->INB(hwif->dma_status);
- u8 sc1d = hwif->INB((high_16 + 0x001d));
+ u8 dma_stat = inb(hwif->dma_status);
+ u8 sc1d = inb(high_16 + 0x001d);
if (hwif->channel) {
/* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */
@@ -445,11 +423,11 @@ static int pdc202xx_ide_dma_timeout(ide_drive_t *drive)
static void pdc202xx_reset_host (ide_hwif_t *hwif)
{
unsigned long high_16 = hwif->dma_master;
- u8 udma_speed_flag = hwif->INB(high_16|0x001f);
+ u8 udma_speed_flag = inb(high_16 | 0x001f);
- hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f));
+ outb(udma_speed_flag | 0x10, high_16 | 0x001f);
mdelay(100);
- hwif->OUTB((udma_speed_flag & ~0x10), (high_16|0x001f));
+ outb(udma_speed_flag & ~0x10, high_16 | 0x001f);
mdelay(2000); /* 2 seconds ?! */
printk(KERN_WARNING "PDC202XX: %s channel reset.\n",
@@ -463,7 +441,7 @@ static void pdc202xx_reset (ide_drive_t *drive)
pdc202xx_reset_host(hwif);
pdc202xx_reset_host(mate);
- hwif->tuneproc(drive, 5);
+ pdc202xx_tune_drive(drive, 255);
}
static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
@@ -490,7 +468,7 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
hwif->rqsize = 256;
hwif->autodma = 0;
- hwif->tuneproc = &config_chipset_for_pio;
+ hwif->tuneproc = &pdc202xx_tune_drive;
hwif->quirkproc = &pdc202xx_quirkproc;
if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246)
@@ -537,9 +515,9 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
return;
}
- udma_speed_flag = hwif->INB((dmabase|0x1f));
- primary_mode = hwif->INB((dmabase|0x1a));
- secondary_mode = hwif->INB((dmabase|0x1b));
+ udma_speed_flag = inb(dmabase | 0x1f);
+ primary_mode = inb(dmabase | 0x1a);
+ secondary_mode = inb(dmabase | 0x1b);
printk(KERN_INFO "%s: (U)DMA Burst Bit %sABLED " \
"Primary %s Mode " \
"Secondary %s Mode.\n", hwif->cds->name,
@@ -552,30 +530,10 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
printk(KERN_INFO "%s: FORCING BURST BIT 0x%02x->0x%02x ",
hwif->cds->name, udma_speed_flag,
(udma_speed_flag|1));
- hwif->OUTB(udma_speed_flag|1,(dmabase|0x1f));
- printk("%sACTIVE\n",
- (hwif->INB(dmabase|0x1f)&1) ? "":"IN");
+ outb(udma_speed_flag | 1, dmabase | 0x1f);
+ printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN");
}
#endif /* CONFIG_PDC202XX_BURST */
-#ifdef CONFIG_PDC202XX_MASTER
- if (!(primary_mode & 1)) {
- printk(KERN_INFO "%s: FORCING PRIMARY MODE BIT "
- "0x%02x -> 0x%02x ", hwif->cds->name,
- primary_mode, (primary_mode|1));
- hwif->OUTB(primary_mode|1, (dmabase|0x1a));
- printk("%s\n",
- (hwif->INB((dmabase|0x1a)) & 1) ? "MASTER" : "PCI");
- }
-
- if (!(secondary_mode & 1)) {
- printk(KERN_INFO "%s: FORCING SECONDARY MODE BIT "
- "0x%02x -> 0x%02x ", hwif->cds->name,
- secondary_mode, (secondary_mode|1));
- hwif->OUTB(secondary_mode|1, (dmabase|0x1b));
- printk("%s\n",
- (hwif->INB((dmabase|0x1b)) & 1) ? "MASTER" : "PCI");
- }
-#endif /* CONFIG_PDC202XX_MASTER */
ide_setup_dma(hwif, dmabase, 8);
}
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 52cfc2ac22c..569822f4cf5 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -369,7 +369,7 @@ static int piix_config_drive_for_dma (ide_drive_t *drive)
* If no DMA speed was available or the chipset has DMA bugs
* then disable DMA and use PIO
*/
- if (!speed || no_piix_dma)
+ if (!speed)
return 0;
(void) piix_tune_chipset(drive, speed);
@@ -386,41 +386,28 @@ static int piix_config_drive_for_dma (ide_drive_t *drive)
static int piix_config_drive_xfer_rate (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
drive->init_speed = 0;
- if ((id->capability & 1) && drive->autodma) {
-
- if (ide_use_dma(drive) && piix_config_drive_for_dma(drive))
- return hwif->ide_dma_on(drive);
-
- goto fast_ata_pio;
+ if (ide_use_dma(drive) && piix_config_drive_for_dma(drive))
+ return 0;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive))
/* Find best PIO mode. */
- (void) hwif->speedproc(drive, XFER_PIO_0 +
- ide_get_best_pio_mode(drive, 255, 4, NULL));
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
+ piix_tune_chipset(drive, XFER_PIO_0 +
+ ide_get_best_pio_mode(drive, 255, 4, NULL));
+
+ return -1;
}
/**
- * init_chipset_piix - set up the PIIX chipset
- * @dev: PCI device to set up
- * @name: Name of the device
+ * piix_is_ichx - check if ICHx
+ * @dev: PCI device to check
*
- * Initialize the PCI device as required. For the PIIX this turns
- * out to be nice and simple
+ * returns 1 if ICHx, 0 otherwise.
*/
-
-static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name)
+static int piix_is_ichx(struct pci_dev *dev)
{
- switch(dev->device) {
+ switch (dev->device) {
case PCI_DEVICE_ID_INTEL_82801EB_1:
case PCI_DEVICE_ID_INTEL_82801AA_1:
case PCI_DEVICE_ID_INTEL_82801AB_1:
@@ -438,19 +425,61 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char
case PCI_DEVICE_ID_INTEL_ICH7_21:
case PCI_DEVICE_ID_INTEL_ESB2_18:
case PCI_DEVICE_ID_INTEL_ICH8_6:
- {
- unsigned int extra = 0;
- pci_read_config_dword(dev, 0x54, &extra);
- pci_write_config_dword(dev, 0x54, extra|0x400);
- }
- default:
- break;
+ return 1;
}
return 0;
}
/**
+ * init_chipset_piix - set up the PIIX chipset
+ * @dev: PCI device to set up
+ * @name: Name of the device
+ *
+ * Initialize the PCI device as required. For the PIIX this turns
+ * out to be nice and simple
+ */
+
+static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name)
+{
+ if (piix_is_ichx(dev)) {
+ unsigned int extra = 0;
+ pci_read_config_dword(dev, 0x54, &extra);
+ pci_write_config_dword(dev, 0x54, extra|0x400);
+ }
+
+ return 0;
+}
+
+/**
+ * piix_dma_clear_irq - clear BMDMA status
+ * @drive: IDE drive to clear
+ *
+ * Called from ide_intr() for PIO interrupts
+ * to clear BMDMA status as needed by ICHx
+ */
+static void piix_dma_clear_irq(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ u8 dma_stat;
+
+ /* clear the INTR & ERROR bits */
+ dma_stat = hwif->INB(hwif->dma_status);
+ /* Should we force the bit as well ? */
+ hwif->OUTB(dma_stat, hwif->dma_status);
+}
+
+static int __devinit piix_cable_detect(ide_hwif_t *hwif)
+{
+ struct pci_dev *dev = hwif->pci_dev;
+ u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
+
+ pci_read_config_byte(dev, 0x54, &reg54h);
+
+ return (reg54h & mask) ? 1 : 0;
+}
+
+/**
* init_hwif_piix - fill in the hwif for the PIIX
* @hwif: IDE interface
*
@@ -460,9 +489,6 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char
static void __devinit init_hwif_piix(ide_hwif_t *hwif)
{
- u8 reg54h = 0, reg55h = 0, ata66 = 0;
- u8 mask = hwif->channel ? 0xc0 : 0x30;
-
#ifndef CONFIG_IA64
if (!hwif->irq)
hwif->irq = hwif->channel ? 15 : 14;
@@ -472,10 +498,6 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
/* This is a painful system best to let it self tune for now */
return;
}
- /* ESB2 appears to generate spurious DMA interrupts in PIO mode
- when in native mode */
- if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_ESB2_18)
- hwif->atapi_irq_bogon = 1;
hwif->autodma = 0;
hwif->tuneproc = &piix_tune_drive;
@@ -486,15 +508,16 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
if (!hwif->dma_base)
return;
+ /* ICHx need to clear the bmdma status for all interrupts */
+ if (piix_is_ichx(hwif->pci_dev))
+ hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
+
hwif->atapi_dma = 1;
hwif->ultra_mask = 0x3f;
hwif->mwdma_mask = 0x06;
hwif->swdma_mask = 0x04;
switch(hwif->pci_dev->device) {
- case PCI_DEVICE_ID_INTEL_82371MX:
- hwif->mwdma_mask = 0x80;
- hwif->swdma_mask = 0x80;
case PCI_DEVICE_ID_INTEL_82371FB_0:
case PCI_DEVICE_ID_INTEL_82371FB_1:
case PCI_DEVICE_ID_INTEL_82371SB_1:
@@ -507,14 +530,14 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
hwif->ultra_mask = 0x07;
break;
default:
- pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
- pci_read_config_byte(hwif->pci_dev, 0x55, &reg55h);
- ata66 = (reg54h & mask) ? 1 : 0;
+ if (!hwif->udma_four)
+ hwif->udma_four = piix_cable_detect(hwif);
break;
}
- if (!(hwif->udma_four))
- hwif->udma_four = ata66;
+ if (no_piix_dma)
+ hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
+
hwif->ide_dma_check = &piix_config_drive_xfer_rate;
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 8d762d323f8..b5ae0c50e21 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -161,7 +161,7 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
/*
* Default to DMA-off in case we run into trouble here.
*/
- hwif->ide_dma_off_quietly(drive); /* turn off DMA while we fiddle */
+ hwif->dma_off_quietly(drive); /* turn off DMA while we fiddle */
outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */
/*
@@ -241,10 +241,7 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */
- /*
- * Finally, turn DMA on in software, and exit.
- */
- return hwif->ide_dma_on(drive); /* success */
+ return 0; /* success */
}
/*
@@ -442,10 +439,10 @@ static int sc1200_resume (struct pci_dev *dev)
ide_drive_t *drive = &(hwif->drives[d]);
if (drive->present && !__ide_dma_bad_drive(drive)) {
int was_using_dma = drive->using_dma;
- hwif->ide_dma_off_quietly(drive);
+ hwif->dma_off_quietly(drive);
sc1200_config_dma(drive);
if (!was_using_dma && drive->using_dma) {
- hwif->ide_dma_off_quietly(drive);
+ hwif->dma_off_quietly(drive);
}
}
}
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index ea9a28a4585..dbcd37a0c65 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -160,7 +160,7 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
(dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
if (!drive->init_speed) {
- u8 dma_stat = hwif->INB(hwif->dma_status);
+ u8 dma_stat = inb(hwif->dma_status);
dma_pio:
if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
@@ -315,35 +315,15 @@ static int config_chipset_for_dma (ide_drive_t *drive)
static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
drive->init_speed = 0;
- if ((id->capability & 1) && drive->autodma) {
-
- if (ide_use_dma(drive)) {
- if (config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
-
- goto fast_ata_pio;
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive))
config_chipset_for_pio(drive);
- // hwif->tuneproc(drive, 5);
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
-}
-
-/* This can go soon */
-static int svwks_ide_dma_end (ide_drive_t *drive)
-{
- return __ide_dma_end(drive);
+ return -1;
}
static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const char *name)
@@ -537,35 +517,20 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
}
hwif->ide_dma_check = &svwks_config_drive_xfer_rate;
- if (hwif->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE)
- hwif->ide_dma_end = &svwks_ide_dma_end;
- else if (!(hwif->udma_four))
- hwif->udma_four = ata66_svwks(hwif);
+ if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
+ if (!hwif->udma_four)
+ hwif->udma_four = ata66_svwks(hwif);
+ }
if (!noautodma)
hwif->autodma = 1;
- dma_stat = hwif->INB(hwif->dma_status);
+ dma_stat = inb(hwif->dma_status);
hwif->drives[0].autodma = (dma_stat & 0x20);
hwif->drives[1].autodma = (dma_stat & 0x40);
hwif->drives[0].autotune = (!(dma_stat & 0x20));
hwif->drives[1].autotune = (!(dma_stat & 0x40));
}
-/*
- * We allow the BM-DMA driver to only work on enabled interfaces.
- */
-static void __devinit init_dma_svwks (ide_hwif_t *hwif, unsigned long dmabase)
-{
- struct pci_dev *dev = hwif->pci_dev;
-
- if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
- (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) &&
- (!(PCI_FUNC(dev->devfn) & 1)) && (hwif->channel))
- return;
-
- ide_setup_dma(hwif, dmabase, 8);
-}
-
static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d)
{
return ide_setup_pci_device(dev, d);
@@ -600,7 +565,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
.init_setup = init_setup_svwks,
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .init_dma = init_dma_svwks,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
@@ -609,7 +573,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
.init_setup = init_setup_csb6,
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .init_dma = init_dma_svwks,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
@@ -618,7 +581,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
.init_setup = init_setup_csb6,
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .init_dma = init_dma_svwks,
.channels = 1, /* 2 */
.autodma = AUTODMA,
.bootable = ON_BOARD,
@@ -627,7 +589,6 @@ static ide_pci_device_t serverworks_chipsets[] __devinitdata = {
.init_setup = init_setup_svwks,
.init_chipset = init_chipset_svwks,
.init_hwif = init_hwif_svwks,
- .init_dma = init_dma_svwks,
.channels = 1, /* 2 */
.autodma = AUTODMA,
.bootable = ON_BOARD,
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index b0bf0180927..fd09b295a69 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -110,24 +110,24 @@ sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
static void
sgiioc4_maskproc(ide_drive_t * drive, int mask)
{
- ide_hwif_t *hwif = HWIF(drive);
- hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
- IDE_CONTROL_REG);
+ writeb(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
+ (void __iomem *)IDE_CONTROL_REG);
}
static int
sgiioc4_checkirq(ide_hwif_t * hwif)
{
- u8 intr_reg =
- hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4);
+ unsigned long intr_addr =
+ hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4;
- if (intr_reg & 0x03)
+ if ((u8)readl((void __iomem *)intr_addr) & 0x03)
return 1;
return 0;
}
+static u8 sgiioc4_INB(unsigned long);
static int
sgiioc4_clearirq(ide_drive_t * drive)
@@ -138,21 +138,21 @@ sgiioc4_clearirq(ide_drive_t * drive)
hwif->io_ports[IDE_IRQ_OFFSET] + (IOC4_INTR_REG << 2);
/* Code to check for PCI error conditions */
- intr_reg = hwif->INL(other_ir);
+ intr_reg = readl((void __iomem *)other_ir);
if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
/*
- * Using hwif->INB to read the IDE_STATUS_REG has a side effect
+ * Using sgiioc4_INB to read the IDE_STATUS_REG has a side effect
* of clearing the interrupt. The first read should clear it
* if it is set. The second read should return a "clear" status
* if it got cleared. If not, then spin for a bit trying to
* clear it.
*/
- u8 stat = hwif->INB(IDE_STATUS_REG);
+ u8 stat = sgiioc4_INB(IDE_STATUS_REG);
int count = 0;
- stat = hwif->INB(IDE_STATUS_REG);
+ stat = sgiioc4_INB(IDE_STATUS_REG);
while ((stat & 0x80) && (count++ < 100)) {
udelay(1);
- stat = hwif->INB(IDE_STATUS_REG);
+ stat = sgiioc4_INB(IDE_STATUS_REG);
}
if (intr_reg & 0x02) {
@@ -161,9 +161,9 @@ sgiioc4_clearirq(ide_drive_t * drive)
pci_stat_cmd_reg;
pci_err_addr_low =
- hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET]);
+ readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]);
pci_err_addr_high =
- hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + 4);
+ readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4));
pci_read_config_dword(hwif->pci_dev, PCI_COMMAND,
&pci_stat_cmd_reg);
printk(KERN_ERR
@@ -180,9 +180,9 @@ sgiioc4_clearirq(ide_drive_t * drive)
}
/* Clear the Interrupt, Error bits on the IOC4 */
- hwif->OUTL(0x03, other_ir);
+ writel(0x03, (void __iomem *)other_ir);
- intr_reg = hwif->INL(other_ir);
+ intr_reg = readl((void __iomem *)other_ir);
}
return intr_reg & 3;
@@ -191,23 +191,25 @@ sgiioc4_clearirq(ide_drive_t * drive)
static void sgiioc4_ide_dma_start(ide_drive_t * drive)
{
ide_hwif_t *hwif = HWIF(drive);
- unsigned int reg = hwif->INL(hwif->dma_base + IOC4_DMA_CTRL * 4);
+ unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4;
+ unsigned int reg = readl((void __iomem *)ioc4_dma_addr);
unsigned int temp_reg = reg | IOC4_S_DMA_START;
- hwif->OUTL(temp_reg, hwif->dma_base + IOC4_DMA_CTRL * 4);
+ writel(temp_reg, (void __iomem *)ioc4_dma_addr);
}
static u32
sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
{
+ unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
u32 ioc4_dma;
int count;
count = 0;
- ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+ ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
while ((ioc4_dma & IOC4_S_DMA_STOP) && (count++ < 200)) {
udelay(1);
- ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+ ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
}
return ioc4_dma;
}
@@ -218,11 +220,11 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
{
u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0;
ide_hwif_t *hwif = HWIF(drive);
- u64 dma_base = hwif->dma_base;
+ unsigned long dma_base = hwif->dma_base;
int dma_stat = 0;
unsigned long *ending_dma = ide_get_hwifdata(hwif);
- hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+ writel(IOC4_S_DMA_STOP, (void __iomem *)(dma_base + IOC4_DMA_CTRL * 4));
ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
@@ -254,8 +256,8 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
dma_stat = 1;
}
- bc_dev = hwif->INL(dma_base + IOC4_BC_DEV * 4);
- bc_mem = hwif->INL(dma_base + IOC4_BC_MEM * 4);
+ bc_dev = readl((void __iomem *)(dma_base + IOC4_BC_DEV * 4));
+ bc_mem = readl((void __iomem *)(dma_base + IOC4_BC_MEM * 4));
if ((bc_dev & 0x01FF) || (bc_mem & 0x1FF)) {
if (bc_dev > bc_mem + 8) {
@@ -273,34 +275,29 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
}
static int
-sgiioc4_ide_dma_check(ide_drive_t * drive)
+sgiioc4_ide_dma_on(ide_drive_t * drive)
{
- if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) {
- printk(KERN_INFO
- "Couldnot set %s in Multimode-2 DMA mode | "
- "Drive %s using PIO instead\n",
- drive->name, drive->name);
- drive->using_dma = 0;
- } else
- drive->using_dma = 1;
+ drive->using_dma = 1;
return 0;
}
-static int
-sgiioc4_ide_dma_on(ide_drive_t * drive)
+static void sgiioc4_dma_off_quietly(ide_drive_t *drive)
{
- drive->using_dma = 1;
+ drive->using_dma = 0;
- return HWIF(drive)->ide_dma_host_on(drive);
+ drive->hwif->dma_host_off(drive);
}
-static int
-sgiioc4_ide_dma_off_quietly(ide_drive_t * drive)
+static int sgiioc4_ide_dma_check(ide_drive_t *drive)
{
- drive->using_dma = 0;
-
- return HWIF(drive)->ide_dma_host_off(drive);
+ /* FIXME: check for available DMA modes */
+ if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) {
+ printk(KERN_WARNING "%s: couldn't set MWDMA2 mode, "
+ "using PIO instead\n", drive->name);
+ return -1;
+ } else
+ return 0;
}
/* returns 1 if dma irq issued, 0 otherwise */
@@ -310,21 +307,13 @@ sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
return sgiioc4_checkirq(HWIF(drive));
}
-static int
-sgiioc4_ide_dma_host_on(ide_drive_t * drive)
+static void sgiioc4_dma_host_on(ide_drive_t * drive)
{
- if (drive->using_dma)
- return 0;
-
- return 1;
}
-static int
-sgiioc4_ide_dma_host_off(ide_drive_t * drive)
+static void sgiioc4_dma_host_off(ide_drive_t * drive)
{
sgiioc4_clearirq(drive);
-
- return 0;
}
static int
@@ -436,16 +425,17 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
{
u32 ioc4_dma;
ide_hwif_t *hwif = HWIF(drive);
- u64 dma_base = hwif->dma_base;
+ unsigned long dma_base = hwif->dma_base;
+ unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
u32 dma_addr, ending_dma_addr;
- ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+ ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
if (ioc4_dma & IOC4_S_DMA_ACTIVE) {
printk(KERN_WARNING
"%s(%s):Warning!! DMA from previous transfer was still active\n",
__FUNCTION__, drive->name);
- hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+ writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
if (ioc4_dma & IOC4_S_DMA_STOP)
@@ -454,13 +444,13 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
__FUNCTION__, drive->name);
}
- ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
+ ioc4_dma = readl((void __iomem *)ioc4_dma_addr);
if (ioc4_dma & IOC4_S_DMA_ERROR) {
printk(KERN_WARNING
"%s(%s) : Warning!! - DMA Error during Previous"
" transfer | status 0x%x\n",
__FUNCTION__, drive->name, ioc4_dma);
- hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
+ writel(IOC4_S_DMA_STOP, (void __iomem *)ioc4_dma_addr);
ioc4_dma = sgiioc4_ide_dma_stop(hwif, dma_base);
if (ioc4_dma & IOC4_S_DMA_STOP)
@@ -471,14 +461,14 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
/* Address of the Scatter Gather List */
dma_addr = cpu_to_le32(hwif->dmatable_dma);
- hwif->OUTL(dma_addr, dma_base + IOC4_DMA_PTR_L * 4);
+ writel(dma_addr, (void __iomem *)(dma_base + IOC4_DMA_PTR_L * 4));
/* Address of the Ending DMA */
memset(ide_get_hwifdata(hwif), 0, IOC4_IDE_CACHELINE_SIZE);
ending_dma_addr = cpu_to_le32(hwif->dma_status);
- hwif->OUTL(ending_dma_addr, dma_base + IOC4_DMA_END_ADDR * 4);
+ writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4));
- hwif->OUTL(dma_direction, dma_base + IOC4_DMA_CTRL * 4);
+ writel(dma_direction, (void __iomem *)ioc4_dma_addr);
drive->waiting_for_dma = 1;
}
@@ -590,7 +580,7 @@ static int sgiioc4_ide_dma_setup(ide_drive_t *drive)
static void __devinit
ide_init_sgiioc4(ide_hwif_t * hwif)
{
- hwif->mmio = 2;
+ hwif->mmio = 1;
hwif->autodma = 1;
hwif->atapi_dma = 1;
hwif->ultra_mask = 0x0; /* Disable Ultra DMA */
@@ -613,10 +603,10 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
hwif->ide_dma_end = &sgiioc4_ide_dma_end;
hwif->ide_dma_check = &sgiioc4_ide_dma_check;
hwif->ide_dma_on = &sgiioc4_ide_dma_on;
- hwif->ide_dma_off_quietly = &sgiioc4_ide_dma_off_quietly;
+ hwif->dma_off_quietly = &sgiioc4_dma_off_quietly;
hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
- hwif->ide_dma_host_on = &sgiioc4_ide_dma_host_on;
- hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off;
+ hwif->dma_host_on = &sgiioc4_dma_host_on;
+ hwif->dma_host_off = &sgiioc4_dma_host_off;
hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
hwif->ide_dma_timeout = &__ide_dma_timeout;
@@ -688,7 +678,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
default_hwif_mmiops(hwif);
/* Initializing chipset IRQ Registers */
- hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4);
+ writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
ide_init_sgiioc4(hwif);
@@ -729,8 +719,7 @@ out:
return ret;
}
-static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
- {
+static ide_pci_device_t sgiioc4_chipset __devinitdata = {
/* Channel 0 */
.name = "SGIIOC4",
.init_hwif = ide_init_sgiioc4,
@@ -739,7 +728,6 @@ static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
.autodma = AUTODMA,
/* SGI IOC4 doesn't have enablebits. */
.bootable = ON_BOARD,
- }
};
int
@@ -751,8 +739,7 @@ ioc4_ide_attach_one(struct ioc4_driver_data *idd)
if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
return 0;
- return pci_init_sgiioc4(idd->idd_pdev,
- &sgiioc4_chipsets[idd->idd_pci_id->driver_data]);
+ return pci_init_sgiioc4(idd->idd_pdev, &sgiioc4_chipset);
}
static struct ioc4_submodule ioc4_ide_submodule = {
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 4ff89c7d990..7b4c189a9d9 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -1,8 +1,9 @@
/*
- * linux/drivers/ide/pci/siimage.c Version 1.07 Nov 30, 2003
+ * linux/drivers/ide/pci/siimage.c Version 1.11 Jan 27, 2007
*
* Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2003 Red Hat <alan@redhat.com>
+ * Copyright (C) 2007 MontaVista Software, Inc.
*
* May be copied or modified under the terms of the GNU General Public License
*
@@ -205,41 +206,39 @@ static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted)
unsigned long tfaddr = siimage_selreg(hwif, 0x02);
/* cheat for now and use the docs */
- switch(mode_wanted) {
- case 4:
- speedp = 0x10c1;
- speedt = 0x10c1;
- break;
- case 3:
- speedp = 0x10C3;
- speedt = 0x10C3;
- break;
- case 2:
- speedp = 0x1104;
- speedt = 0x1281;
- break;
- case 1:
- speedp = 0x2283;
- speedt = 0x1281;
- break;
- case 0:
- default:
- speedp = 0x328A;
- speedt = 0x328A;
- break;
+ switch (mode_wanted) {
+ case 4:
+ speedp = 0x10c1;
+ speedt = 0x10c1;
+ break;
+ case 3:
+ speedp = 0x10c3;
+ speedt = 0x10c3;
+ break;
+ case 2:
+ speedp = 0x1104;
+ speedt = 0x1281;
+ break;
+ case 1:
+ speedp = 0x2283;
+ speedt = 0x2283;
+ break;
+ case 0:
+ default:
+ speedp = 0x328a;
+ speedt = 0x328a;
+ break;
}
- if (hwif->mmio)
- {
- hwif->OUTW(speedt, addr);
- hwif->OUTW(speedp, tfaddr);
+
+ if (hwif->mmio) {
+ hwif->OUTW(speedp, addr);
+ hwif->OUTW(speedt, tfaddr);
/* Now set up IORDY */
if(mode_wanted == 3 || mode_wanted == 4)
hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2);
else
hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2);
- }
- else
- {
+ } else {
pci_write_config_word(hwif->pci_dev, addr, speedp);
pci_write_config_word(hwif->pci_dev, tfaddr, speedt);
pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp);
@@ -397,12 +396,9 @@ static int config_chipset_for_dma (ide_drive_t *drive)
if (!speed)
return 0;
- if (ide_set_xfer_rate(drive, speed))
+ if (siimage_tune_chipset(drive, speed))
return 0;
- if (!drive->init_speed)
- drive->init_speed = speed;
-
return ide_dma_enable(drive);
}
@@ -418,25 +414,13 @@ static int config_chipset_for_dma (ide_drive_t *drive)
static int siimage_config_drive_for_dma (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
- if ((id->capability & 1) != 0 && drive->autodma) {
-
- if (ide_use_dma(drive)) {
- if (config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
-
- goto fast_ata_pio;
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive))
config_chipset_for_pio(drive, 1);
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
+
+ return -1;
}
/* returns 1 if dma irq issued, 0 otherwise */
@@ -472,11 +456,11 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
unsigned long addr = siimage_selreg(hwif, 0x1);
if (SATA_ERROR_REG) {
- u32 ext_stat = hwif->INL(base + 0x10);
+ u32 ext_stat = readl((void __iomem *)(base + 0x10));
u8 watchdog = 0;
if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
- u32 sata_error = hwif->INL(SATA_ERROR_REG);
- hwif->OUTL(sata_error, SATA_ERROR_REG);
+ u32 sata_error = readl((void __iomem *)SATA_ERROR_REG);
+ writel(sata_error, (void __iomem *)SATA_ERROR_REG);
watchdog = (sata_error & 0x00680000) ? 1 : 0;
printk(KERN_WARNING "%s: sata_error = 0x%08x, "
"watchdog = %d, %s\n",
@@ -493,11 +477,11 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
}
/* return 1 if INTR asserted */
- if ((hwif->INB(hwif->dma_status) & 0x04) == 0x04)
+ if ((readb((void __iomem *)hwif->dma_status) & 0x04) == 0x04)
return 1;
/* return 1 if Device INTR asserted */
- if ((hwif->INB(addr) & 8) == 8)
+ if ((readb((void __iomem *)addr) & 8) == 8)
return 0; //return 1;
return 0;
@@ -519,9 +503,9 @@ static int siimage_busproc (ide_drive_t * drive, int state)
u32 stat_config = 0;
unsigned long addr = siimage_selreg(hwif, 0);
- if (hwif->mmio) {
- stat_config = hwif->INL(addr);
- } else
+ if (hwif->mmio)
+ stat_config = readl((void __iomem *)addr);
+ else
pci_read_config_dword(hwif->pci_dev, addr, &stat_config);
switch (state) {
@@ -557,9 +541,10 @@ static int siimage_reset_poll (ide_drive_t *drive)
if (SATA_STATUS_REG) {
ide_hwif_t *hwif = HWIF(drive);
- if ((hwif->INL(SATA_STATUS_REG) & 0x03) != 0x03) {
+ /* SATA_STATUS_REG is valid only when in MMIO mode */
+ if ((readl((void __iomem *)SATA_STATUS_REG) & 0x03) != 0x03) {
printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
- hwif->name, hwif->INL(SATA_STATUS_REG));
+ hwif->name, readl((void __iomem *)SATA_STATUS_REG));
HWGROUP(drive)->polling = 0;
return ide_started;
}
@@ -619,7 +604,8 @@ static void siimage_reset (ide_drive_t *drive)
}
if (SATA_STATUS_REG) {
- u32 sata_stat = hwif->INL(SATA_STATUS_REG);
+ /* SATA_STATUS_REG is valid only when in MMIO mode */
+ u32 sata_stat = readl((void __iomem *)SATA_STATUS_REG);
printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n",
hwif->name, sata_stat, __FUNCTION__);
if (!(sata_stat)) {
@@ -898,7 +884,8 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
base = (unsigned long) addr;
hwif->dma_base = base + (ch ? 0x08 : 0x00);
- hwif->mmio = 2;
+
+ hwif->mmio = 1;
}
static int is_dev_seagate_sata(ide_drive_t *drive)
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 1afff659ab5..2ba0669f36a 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -667,67 +667,20 @@ static int config_chipset_for_dma (ide_drive_t *drive)
return ide_dma_enable(drive);
}
-static int sis5513_config_drive_xfer_rate (ide_drive_t *drive)
+static int sis5513_config_xfer_rate(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
+ config_art_rwp_pio(drive, 5);
drive->init_speed = 0;
- if (id && (id->capability & 1) && drive->autodma) {
-
- if (ide_use_dma(drive)) {
- if (config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
-
- goto fast_ata_pio;
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive))
sis5513_tune_drive(drive, 5);
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
-}
-
-/* initiates/aborts (U)DMA read/write operations on a drive. */
-static int sis5513_config_xfer_rate (ide_drive_t *drive)
-{
- config_drive_art_rwp(drive);
- config_art_rwp_pio(drive, 5);
- return sis5513_config_drive_xfer_rate(drive);
-}
-
-/*
- Future simpler config_xfer_rate :
- When ide_find_best_mode is made bad-drive aware
- - remove config_drive_xfer_rate and config_chipset_for_dma,
- - replace config_xfer_rate with the following
-
-static int sis5513_config_xfer_rate (ide_drive_t *drive)
-{
- u16 w80 = HWIF(drive)->udma_four;
- u16 speed;
-
- config_drive_art_rwp(drive);
- config_art_rwp_pio(drive, 5);
-
- speed = ide_find_best_mode(drive,
- XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
- (chipset_family >= ATA_33 ? XFER_UDMA : 0) |
- (w80 && chipset_family >= ATA_66 ? XFER_UDMA_66 : 0) |
- (w80 && chipset_family >= ATA_100a ? XFER_UDMA_100 : 0) |
- (w80 && chipset_family >= ATA_133a ? XFER_UDMA_133 : 0));
-
- sis5513_tune_chipset(drive, speed);
- if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
- return HWIF(drive)->ide_dma_on(drive);
- return HWIF(drive)->ide_dma_off_quietly(drive);
+ return -1;
}
-*/
/* Chip detection and general config */
static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name)
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 170a2619905..3a8a76fc78c 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -161,14 +161,14 @@ static int sl82c105_check_drive (ide_drive_t *drive)
if (id->field_valid & 2) {
if ((id->dma_mword & hwif->mwdma_mask) ||
(id->dma_1word & hwif->swdma_mask))
- return hwif->ide_dma_on(drive);
+ return 0;
}
- if (__ide_dma_good_drive(drive))
- return hwif->ide_dma_on(drive);
+ if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)
+ return 0;
} while (0);
- return hwif->ide_dma_off_quietly(drive);
+ return -1;
}
/*
@@ -215,7 +215,7 @@ static int sl82c105_ide_dma_lost_irq(ide_drive_t *drive)
* Was DMA enabled? If so, disable it - we're resetting the
* host. The IDE layer will be handling the drive for us.
*/
- val = hwif->INB(dma_base);
+ val = inb(dma_base);
if (val & 1) {
outb(val & ~1, dma_base);
printk("sl82c105: DMA was enabled\n");
@@ -259,28 +259,22 @@ static int sl82c105_ide_dma_on (ide_drive_t *drive)
{
DBG(("sl82c105_ide_dma_on(drive:%s)\n", drive->name));
- if (config_for_dma(drive)) {
- config_for_pio(drive, 4, 0, 0);
- return HWIF(drive)->ide_dma_off_quietly(drive);
- }
+ if (config_for_dma(drive))
+ return 1;
printk(KERN_INFO "%s: DMA enabled\n", drive->name);
return __ide_dma_on(drive);
}
-static int sl82c105_ide_dma_off_quietly (ide_drive_t *drive)
+static void sl82c105_dma_off_quietly(ide_drive_t *drive)
{
u8 speed = XFER_PIO_0;
- int rc;
-
- DBG(("sl82c105_ide_dma_off_quietly(drive:%s)\n", drive->name));
- rc = __ide_dma_off_quietly(drive);
+ DBG(("sl82c105_dma_off_quietly(drive:%s)\n", drive->name));
+
+ ide_dma_off_quietly(drive);
if (drive->pio_speed)
speed = drive->pio_speed - XFER_PIO_0;
config_for_pio(drive, speed, 0, 1);
- drive->current_speed = drive->pio_speed;
-
- return rc;
}
/*
@@ -401,11 +395,9 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
/*
* Initialise the chip
*/
-
static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
{
unsigned int rev;
- u8 dma_state;
DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
@@ -431,7 +423,6 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
if (!hwif->dma_base)
return;
- dma_state = hwif->INB(hwif->dma_base + 2) & ~0x60;
rev = sl82c105_bridge_revision(hwif->pci_dev);
if (rev <= 5) {
/*
@@ -441,15 +432,12 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n",
hwif->name, rev);
} else {
- dma_state |= 0x60;
-
hwif->atapi_dma = 1;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
+ hwif->mwdma_mask = 0x04;
hwif->ide_dma_check = &sl82c105_check_drive;
hwif->ide_dma_on = &sl82c105_ide_dma_on;
- hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly;
+ hwif->dma_off_quietly = &sl82c105_dma_off_quietly;
hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq;
hwif->dma_start = &sl82c105_ide_dma_start;
hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout;
@@ -462,7 +450,6 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
if (hwif->mate)
hwif->serialized = hwif->mate->serialized = 1;
}
- hwif->OUTB(dma_state, hwif->dma_base + 2);
}
static ide_pci_device_t sl82c105_chipset __devinitdata = {
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index 2663ddbd9b6..ae7eb58d961 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -179,26 +179,16 @@ static int slc90e66_config_drive_for_dma (ide_drive_t *drive)
static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
drive->init_speed = 0;
- if ((id->capability & 1) && drive->autodma) {
-
- if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive))
- return hwif->ide_dma_on(drive);
+ if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive))
+ return 0;
- goto fast_ata_pio;
+ if (ide_use_fast_pio(drive))
+ (void)slc90e66_tune_chipset(drive, XFER_PIO_0 +
+ ide_get_best_pio_mode(drive, 255, 4, NULL));
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
- (void) hwif->speedproc(drive, XFER_PIO_0 +
- ide_get_best_pio_mode(drive, 255, 4, NULL));
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
+ return -1;
}
static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index 2ad72bbda34..0b6d81d6ce4 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -45,7 +45,7 @@ static int tc86c001_tune_chipset(ide_drive_t *drive, u8 speed)
scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
scr |= mode;
- hwif->OUTW(scr, scr_port);
+ outw(scr, scr_port);
return ide_config_drive_speed(drive, speed);
}
@@ -89,15 +89,15 @@ static int tc86c001_timer_expiry(ide_drive_t *drive)
"attempting recovery...\n", drive->name);
/* Stop DMA */
- hwif->OUTB(dma_cmd & ~0x01, hwif->dma_command);
+ outb(dma_cmd & ~0x01, hwif->dma_command);
/* Setup the dummy DMA transfer */
- hwif->OUTW(0, sc_base + 0x0a); /* Sector Count */
- hwif->OUTW(0, twcr_port); /* Transfer Word Count 1 or 2 */
+ outw(0, sc_base + 0x0a); /* Sector Count */
+ outw(0, twcr_port); /* Transfer Word Count 1 or 2 */
/* Start the dummy DMA transfer */
- hwif->OUTB(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
- hwif->OUTB(0x01, hwif->dma_command); /* set START_STOPBM */
+ outb(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
+ outb(0x01, hwif->dma_command); /* set START_STOPBM */
/*
* If an interrupt was pending, it should come thru shortly.
@@ -128,8 +128,8 @@ static void tc86c001_dma_start(ide_drive_t *drive)
* the appropriate system control registers for DMA to work
* with LBA48 and ATAPI devices...
*/
- hwif->OUTW(nsectors, sc_base + 0x0a); /* Sector Count */
- hwif->OUTW(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
+ outw(nsectors, sc_base + 0x0a); /* Sector Count */
+ outw(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
/* Install our timeout expiry hook, saving the current handler... */
ide_set_hwifdata(hwif, hwgroup->expiry);
@@ -168,7 +168,7 @@ static int tc86c001_busproc(ide_drive_t *drive, int state)
}
/* System Control 1 Register bit 11 (ATA Hard Reset) write */
- hwif->OUTW(scr1, sc_base + 0x00);
+ outw(scr1, sc_base + 0x00);
return 0;
}
@@ -185,23 +185,13 @@ static int config_chipset_for_dma(ide_drive_t *drive)
static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
- if ((id->capability & 1) && drive->autodma) {
-
- if (ide_use_dma(drive) && config_chipset_for_dma(drive))
- return hwif->ide_dma_on(drive);
-
- goto fast_ata_pio;
+ if (ide_use_dma(drive) && config_chipset_for_dma(drive))
+ return 0;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive))
tc86c001_tune_drive(drive, 255);
- return hwif->ide_dma_off_quietly(drive);
- }
- /* IORDY not supported */
- return 0;
+
+ return -1;
}
static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
@@ -210,13 +200,13 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
u16 scr1 = hwif->INW(sc_base + 0x00);;
/* System Control 1 Register bit 15 (Soft Reset) set */
- hwif->OUTW(scr1 | 0x8000, sc_base + 0x00);
+ outw(scr1 | 0x8000, sc_base + 0x00);
/* System Control 1 Register bit 14 (FIFO Reset) set */
- hwif->OUTW(scr1 | 0x4000, sc_base + 0x00);
+ outw(scr1 | 0x4000, sc_base + 0x00);
/* System Control 1 Register: reset clear */
- hwif->OUTW(scr1 & ~0xc000, sc_base + 0x00);
+ outw(scr1 & ~0xc000, sc_base + 0x00);
/* Store the system control register base for convenience... */
hwif->config_data = sc_base;
@@ -234,7 +224,7 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
* Sector Count Control Register bits 0 and 1 set:
* software sets Sector Count Register for master and slave device
*/
- hwif->OUTW(0x0003, sc_base + 0x0c);
+ outw(0x0003, sc_base + 0x0c);
/* Sector Count Register limit */
hwif->rqsize = 0xffff;
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index b13cce1fd1a..5e06179c346 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -104,29 +104,21 @@ static int triflex_config_drive_for_dma(ide_drive_t *drive)
{
int speed = ide_dma_speed(drive, 0); /* No ultra speeds */
- if (!speed) {
- u8 pspeed = ide_get_best_pio_mode(drive, 255, 4, NULL);
- speed = XFER_PIO_0 + pspeed;
- }
-
+ if (!speed)
+ return 0;
+
(void) triflex_tune_chipset(drive, speed);
return ide_dma_enable(drive);
}
static int triflex_config_drive_xfer_rate(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
- if ((id->capability & 1) && drive->autodma) {
- if (ide_use_dma(drive)) {
- if (triflex_config_drive_for_dma(drive))
- return hwif->ide_dma_on(drive);
- }
- }
+ if (ide_use_dma(drive) && triflex_config_drive_for_dma(drive))
+ return 0;
+
+ triflex_tune_drive(drive, 255);
- hwif->tuneproc(drive, 255);
- return hwif->ide_dma_off_quietly(drive);
+ return -1;
}
static void __devinit init_hwif_triflex(ide_hwif_t *hwif)
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index 174b88c4780..cbb1b11119a 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -157,16 +157,16 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
if (reg != hwif->select_data) {
hwif->select_data = reg;
/* set PIO/DMA */
- hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1);
- hwif->OUTW(reg & 0xff, hwif->config_data);
+ outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
+ outw(reg & 0xff, hwif->config_data);
}
/* enable IRQ if not probing */
if (drive->present) {
- reg = hwif->INW(hwif->config_data + 3);
+ reg = inw(hwif->config_data + 3);
reg &= 0x13;
reg &= ~(1 << hwif->channel);
- hwif->OUTW(reg, hwif->config_data+3);
+ outw(reg, hwif->config_data + 3);
}
local_irq_restore(flags);
@@ -177,15 +177,12 @@ static void trm290_selectproc (ide_drive_t *drive)
trm290_prepare_drive(drive, drive->using_dma);
}
-#ifdef CONFIG_BLK_DEV_IDEDMA
static void trm290_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
{
- ide_hwif_t *hwif = HWIF(drive);
-
BUG_ON(HWGROUP(drive)->handler != NULL); /* paranoia check */
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
/* issue cmd to drive */
- hwif->OUTB(command, IDE_COMMAND_REG);
+ outb(command, IDE_COMMAND_REG);
}
static int trm290_ide_dma_setup(ide_drive_t *drive)
@@ -211,10 +208,10 @@ static int trm290_ide_dma_setup(ide_drive_t *drive)
}
/* select DMA xfer */
trm290_prepare_drive(drive, 1);
- hwif->OUTL(hwif->dmatable_dma|rw, hwif->dma_command);
+ outl(hwif->dmatable_dma | rw, hwif->dma_command);
drive->waiting_for_dma = 1;
/* start DMA */
- hwif->OUTW((count * 2) - 1, hwif->dma_status);
+ outw((count * 2) - 1, hwif->dma_status);
return 0;
}
@@ -230,7 +227,7 @@ static int trm290_ide_dma_end (ide_drive_t *drive)
drive->waiting_for_dma = 0;
/* purge DMA mappings */
ide_destroy_dmatable(drive);
- status = hwif->INW(hwif->dma_status);
+ status = inw(hwif->dma_status);
return (status != 0x00ff);
}
@@ -239,10 +236,9 @@ static int trm290_ide_dma_test_irq (ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
u16 status = 0;
- status = hwif->INW(hwif->dma_status);
+ status = inw(hwif->dma_status);
return (status == 0x00ff);
}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
/*
* Invoked from ide-dma.c at boot time.
@@ -269,15 +265,15 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
local_irq_save(flags);
/* put config reg into first byte of hwif->select_data */
- hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1);
+ outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
/* select PIO as default */
hwif->select_data = 0x21;
- hwif->OUTB(hwif->select_data, hwif->config_data);
+ outb(hwif->select_data, hwif->config_data);
/* get IRQ info */
- reg = hwif->INB(hwif->config_data+3);
+ reg = inb(hwif->config_data + 3);
/* mask IRQs for both ports */
reg = (reg & 0x10) | 0x03;
- hwif->OUTB(reg, hwif->config_data+3);
+ outb(reg, hwif->config_data + 3);
local_irq_restore(flags);
if ((reg & 0x10))
@@ -289,13 +285,11 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
-#ifdef CONFIG_BLK_DEV_IDEDMA
hwif->dma_setup = &trm290_ide_dma_setup;
hwif->dma_exec_cmd = &trm290_ide_dma_exec_cmd;
hwif->dma_start = &trm290_ide_dma_start;
hwif->ide_dma_end = &trm290_ide_dma_end;
hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
hwif->selectproc = &trm290_selectproc;
hwif->autodma = 0; /* play it safe for now */
@@ -312,16 +306,16 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
static u16 next_offset = 0;
u8 old_mask;
- hwif->OUTB(0x54|(hwif->channel<<3), hwif->config_data+1);
- old = hwif->INW(hwif->config_data);
+ outb(0x54 | (hwif->channel << 3), hwif->config_data + 1);
+ old = inw(hwif->config_data);
old &= ~1;
- old_mask = hwif->INB(old+2);
+ old_mask = inb(old + 2);
if (old != compat && old_mask == 0xff) {
/* leave lower 10 bits untouched */
compat += (next_offset += 0x400);
hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2;
- hwif->OUTW(compat|1, hwif->config_data);
- new = hwif->INW(hwif->config_data);
+ outw(compat | 1, hwif->config_data);
+ new = inw(hwif->config_data);
printk(KERN_INFO "%s: control basereg workaround: "
"old=0x%04x, new=0x%04x\n",
hwif->name, old, new & ~1);
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 6fb6e50b823..a508550c409 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -240,8 +240,9 @@ static int via82cxxx_ide_dma_check (ide_drive_t *drive)
via_set_drive(drive, speed);
if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
- return hwif->ide_dma_on(drive);
- return hwif->ide_dma_off_quietly(drive);
+ return 0;
+
+ return -1;
}
static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index d8ea23710bf..395d35253d5 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1237,7 +1237,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->OUTBSYNC = pmac_outbsync;
/* Tell common code _not_ to mess with resources */
- hwif->mmio = 2;
+ hwif->mmio = 1;
hwif->hwif_data = pmif;
pmac_ide_init_hwif_ports(&hwif->hw, pmif->regbase, 0, &hwif->irq);
memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
@@ -1979,16 +1979,12 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
return 1;
}
-static int
-pmac_ide_dma_host_off (ide_drive_t *drive)
+static void pmac_ide_dma_host_off(ide_drive_t *drive)
{
- return 0;
}
-static int
-pmac_ide_dma_host_on (ide_drive_t *drive)
+static int pmac_ide_dma_host_on(ide_drive_t *drive)
{
- return 0;
}
static int
@@ -2034,7 +2030,7 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
return;
}
- hwif->ide_dma_off_quietly = &__ide_dma_off_quietly;
+ hwif->dma_off_quietly = &ide_dma_off_quietly;
hwif->ide_dma_on = &__ide_dma_on;
hwif->ide_dma_check = &pmac_ide_dma_check;
hwif->dma_setup = &pmac_ide_dma_setup;
@@ -2042,8 +2038,8 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->dma_start = &pmac_ide_dma_start;
hwif->ide_dma_end = &pmac_ide_dma_end;
hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
- hwif->ide_dma_host_off = &pmac_ide_dma_host_off;
- hwif->ide_dma_host_on = &pmac_ide_dma_host_on;
+ hwif->dma_host_off = &pmac_ide_dma_host_off;
+ hwif->dma_host_on = &pmac_ide_dma_host_on;
hwif->ide_dma_timeout = &__ide_dma_timeout;
hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq;
diff --git a/drivers/ide/ppc/scc_pata.c b/drivers/ide/ppc/scc_pata.c
new file mode 100644
index 00000000000..de64b022478
--- /dev/null
+++ b/drivers/ide/ppc/scc_pata.c
@@ -0,0 +1,831 @@
+/*
+ * Support for IDE interfaces on Celleb platform
+ *
+ * (C) Copyright 2006 TOSHIBA CORPORATION
+ *
+ * This code is based on drivers/ide/pci/siimage.c:
+ * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2003 Red Hat <alan@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA 0x01b4
+
+#define SCC_PATA_NAME "scc IDE"
+
+#define TDVHSEL_MASTER 0x00000001
+#define TDVHSEL_SLAVE 0x00000004
+
+#define MODE_JCUSFEN 0x00000080
+
+#define CCKCTRL_ATARESET 0x00040000
+#define CCKCTRL_BUFCNT 0x00020000
+#define CCKCTRL_CRST 0x00010000
+#define CCKCTRL_OCLKEN 0x00000100
+#define CCKCTRL_ATACLKOEN 0x00000002
+#define CCKCTRL_LCLKEN 0x00000001
+
+#define QCHCD_IOS_SS 0x00000001
+
+#define QCHSD_STPDIAG 0x00020000
+
+#define INTMASK_MSK 0xD1000012
+#define INTSTS_SERROR 0x80000000
+#define INTSTS_PRERR 0x40000000
+#define INTSTS_RERR 0x10000000
+#define INTSTS_ICERR 0x01000000
+#define INTSTS_BMSINT 0x00000010
+#define INTSTS_BMHE 0x00000008
+#define INTSTS_IOIRQS 0x00000004
+#define INTSTS_INTRQ 0x00000002
+#define INTSTS_ACTEINT 0x00000001
+
+#define ECMODE_VALUE 0x01
+
+static struct scc_ports {
+ unsigned long ctl, dma;
+ unsigned char hwif_id; /* for removing hwif from system */
+} scc_ports[MAX_HWIFS];
+
+/* PIO transfer mode table */
+/* JCHST */
+static unsigned long JCHSTtbl[2][7] = {
+ {0x0E, 0x05, 0x02, 0x03, 0x02, 0x00, 0x00}, /* 100MHz */
+ {0x13, 0x07, 0x04, 0x04, 0x03, 0x00, 0x00} /* 133MHz */
+};
+
+/* JCHHT */
+static unsigned long JCHHTtbl[2][7] = {
+ {0x0E, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00}, /* 100MHz */
+ {0x13, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00} /* 133MHz */
+};
+
+/* JCHCT */
+static unsigned long JCHCTtbl[2][7] = {
+ {0x1D, 0x1D, 0x1C, 0x0B, 0x06, 0x00, 0x00}, /* 100MHz */
+ {0x27, 0x26, 0x26, 0x0E, 0x09, 0x00, 0x00} /* 133MHz */
+};
+
+
+/* DMA transfer mode table */
+/* JCHDCTM/JCHDCTS */
+static unsigned long JCHDCTxtbl[2][7] = {
+ {0x0A, 0x06, 0x04, 0x03, 0x01, 0x00, 0x00}, /* 100MHz */
+ {0x0E, 0x09, 0x06, 0x04, 0x02, 0x01, 0x00} /* 133MHz */
+};
+
+/* JCSTWTM/JCSTWTS */
+static unsigned long JCSTWTxtbl[2][7] = {
+ {0x06, 0x04, 0x03, 0x02, 0x02, 0x02, 0x00}, /* 100MHz */
+ {0x09, 0x06, 0x04, 0x02, 0x02, 0x02, 0x02} /* 133MHz */
+};
+
+/* JCTSS */
+static unsigned long JCTSStbl[2][7] = {
+ {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00}, /* 100MHz */
+ {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05} /* 133MHz */
+};
+
+/* JCENVT */
+static unsigned long JCENVTtbl[2][7] = {
+ {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00}, /* 100MHz */
+ {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02} /* 133MHz */
+};
+
+/* JCACTSELS/JCACTSELM */
+static unsigned long JCACTSELtbl[2][7] = {
+ {0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00}, /* 100MHz */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} /* 133MHz */
+};
+
+
+static u8 scc_ide_inb(unsigned long port)
+{
+ u32 data = in_be32((void*)port);
+ return (u8)data;
+}
+
+static u16 scc_ide_inw(unsigned long port)
+{
+ u32 data = in_be32((void*)port);
+ return (u16)data;
+}
+
+static void scc_ide_insw(unsigned long port, void *addr, u32 count)
+{
+ u16 *ptr = (u16 *)addr;
+ while (count--) {
+ *ptr++ = le16_to_cpu(in_be32((void*)port));
+ }
+}
+
+static void scc_ide_insl(unsigned long port, void *addr, u32 count)
+{
+ u16 *ptr = (u16 *)addr;
+ while (count--) {
+ *ptr++ = le16_to_cpu(in_be32((void*)port));
+ *ptr++ = le16_to_cpu(in_be32((void*)port));
+ }
+}
+
+static void scc_ide_outb(u8 addr, unsigned long port)
+{
+ out_be32((void*)port, addr);
+}
+
+static void scc_ide_outw(u16 addr, unsigned long port)
+{
+ out_be32((void*)port, addr);
+}
+
+static void
+scc_ide_outbsync(ide_drive_t * drive, u8 addr, unsigned long port)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+
+ out_be32((void*)port, addr);
+ __asm__ __volatile__("eieio":::"memory");
+ in_be32((void*)(hwif->dma_base + 0x01c));
+ __asm__ __volatile__("eieio":::"memory");
+}
+
+static void
+scc_ide_outsw(unsigned long port, void *addr, u32 count)
+{
+ u16 *ptr = (u16 *)addr;
+ while (count--) {
+ out_be32((void*)port, cpu_to_le16(*ptr++));
+ }
+}
+
+static void
+scc_ide_outsl(unsigned long port, void *addr, u32 count)
+{
+ u16 *ptr = (u16 *)addr;
+ while (count--) {
+ out_be32((void*)port, cpu_to_le16(*ptr++));
+ out_be32((void*)port, cpu_to_le16(*ptr++));
+ }
+}
+
+/**
+ * scc_ratemask - Compute available modes
+ * @drive: IDE drive
+ *
+ * Compute the available speeds for the devices on the interface.
+ * Enforce UDMA33 as a limit if there is no 80pin cable present.
+ */
+
+static u8 scc_ratemask(ide_drive_t *drive)
+{
+ u8 mode = 4;
+
+ if (!eighty_ninty_three(drive))
+ mode = min(mode, (u8)1);
+ return mode;
+}
+
+/**
+ * scc_tuneproc - tune a drive PIO mode
+ * @drive: drive to tune
+ * @mode_wanted: the target operating mode
+ *
+ * Load the timing settings for this device mode into the
+ * controller.
+ */
+
+static void scc_tuneproc(ide_drive_t *drive, byte mode_wanted)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ struct scc_ports *ports = ide_get_hwifdata(hwif);
+ unsigned long ctl_base = ports->ctl;
+ unsigned long cckctrl_port = ctl_base + 0xff0;
+ unsigned long piosht_port = ctl_base + 0x000;
+ unsigned long pioct_port = ctl_base + 0x004;
+ unsigned long reg;
+ unsigned char speed = XFER_PIO_0;
+ int offset;
+
+ mode_wanted = ide_get_best_pio_mode(drive, mode_wanted, 4, NULL);
+ switch (mode_wanted) {
+ case 4:
+ speed = XFER_PIO_4;
+ break;
+ case 3:
+ speed = XFER_PIO_3;
+ break;
+ case 2:
+ speed = XFER_PIO_2;
+ break;
+ case 1:
+ speed = XFER_PIO_1;
+ break;
+ case 0:
+ default:
+ speed = XFER_PIO_0;
+ break;
+ }
+
+ reg = in_be32((void __iomem *)cckctrl_port);
+ if (reg & CCKCTRL_ATACLKOEN) {
+ offset = 1; /* 133MHz */
+ } else {
+ offset = 0; /* 100MHz */
+ }
+ reg = JCHSTtbl[offset][mode_wanted] << 16 | JCHHTtbl[offset][mode_wanted];
+ out_be32((void __iomem *)piosht_port, reg);
+ reg = JCHCTtbl[offset][mode_wanted];
+ out_be32((void __iomem *)pioct_port, reg);
+
+ ide_config_drive_speed(drive, speed);
+}
+
+/**
+ * scc_tune_chipset - tune a drive DMA mode
+ * @drive: Drive to set up
+ * @xferspeed: speed we want to achieve
+ *
+ * Load the timing settings for this device mode into the
+ * controller.
+ */
+
+static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ u8 speed = ide_rate_filter(scc_ratemask(drive), xferspeed);
+ struct scc_ports *ports = ide_get_hwifdata(hwif);
+ unsigned long ctl_base = ports->ctl;
+ unsigned long cckctrl_port = ctl_base + 0xff0;
+ unsigned long mdmact_port = ctl_base + 0x008;
+ unsigned long mcrcst_port = ctl_base + 0x00c;
+ unsigned long sdmact_port = ctl_base + 0x010;
+ unsigned long scrcst_port = ctl_base + 0x014;
+ unsigned long udenvt_port = ctl_base + 0x018;
+ unsigned long tdvhsel_port = ctl_base + 0x020;
+ int is_slave = (&hwif->drives[1] == drive);
+ int offset, idx;
+ unsigned long reg;
+ unsigned long jcactsel;
+
+ reg = in_be32((void __iomem *)cckctrl_port);
+ if (reg & CCKCTRL_ATACLKOEN) {
+ offset = 1; /* 133MHz */
+ } else {
+ offset = 0; /* 100MHz */
+ }
+
+ switch (speed) {
+ case XFER_UDMA_6:
+ idx = 6;
+ break;
+ case XFER_UDMA_5:
+ idx = 5;
+ break;
+ case XFER_UDMA_4:
+ idx = 4;
+ break;
+ case XFER_UDMA_3:
+ idx = 3;
+ break;
+ case XFER_UDMA_2:
+ idx = 2;
+ break;
+ case XFER_UDMA_1:
+ idx = 1;
+ break;
+ case XFER_UDMA_0:
+ idx = 0;
+ break;
+ default:
+ return 1;
+ }
+
+ jcactsel = JCACTSELtbl[offset][idx];
+ if (is_slave) {
+ out_be32((void __iomem *)sdmact_port, JCHDCTxtbl[offset][idx]);
+ out_be32((void __iomem *)scrcst_port, JCSTWTxtbl[offset][idx]);
+ jcactsel = jcactsel << 2;
+ out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_SLAVE) | jcactsel);
+ } else {
+ out_be32((void __iomem *)mdmact_port, JCHDCTxtbl[offset][idx]);
+ out_be32((void __iomem *)mcrcst_port, JCSTWTxtbl[offset][idx]);
+ out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_MASTER) | jcactsel);
+ }
+ reg = JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx];
+ out_be32((void __iomem *)udenvt_port, reg);
+
+ return ide_config_drive_speed(drive, speed);
+}
+
+/**
+ * scc_config_chipset_for_dma - configure for DMA
+ * @drive: drive to configure
+ *
+ * Called by scc_config_drive_for_dma().
+ */
+
+static int scc_config_chipset_for_dma(ide_drive_t *drive)
+{
+ u8 speed = ide_dma_speed(drive, scc_ratemask(drive));
+
+ if (!speed)
+ return 0;
+
+ if (scc_tune_chipset(drive, speed))
+ return 0;
+
+ return ide_dma_enable(drive);
+}
+
+/**
+ * scc_configure_drive_for_dma - set up for DMA transfers
+ * @drive: drive we are going to set up
+ *
+ * Set up the drive for DMA, tune the controller and drive as
+ * required.
+ * If the drive isn't suitable for DMA or we hit other problems
+ * then we will drop down to PIO and set up PIO appropriately.
+ * (return 1)
+ */
+
+static int scc_config_drive_for_dma(ide_drive_t *drive)
+{
+ if (ide_use_dma(drive) && scc_config_chipset_for_dma(drive))
+ return 0;
+
+ if (ide_use_fast_pio(drive))
+ scc_tuneproc(drive, 4);
+
+ return -1;
+}
+
+/**
+ * scc_ide_dma_setup - begin a DMA phase
+ * @drive: target device
+ *
+ * Build an IDE DMA PRD (IDE speak for scatter gather table)
+ * and then set up the DMA transfer registers.
+ *
+ * Returns 0 on success. If a PIO fallback is required then 1
+ * is returned.
+ */
+
+static int scc_dma_setup(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = HWGROUP(drive)->rq;
+ unsigned int reading;
+ u8 dma_stat;
+
+ if (rq_data_dir(rq))
+ reading = 0;
+ else
+ reading = 1 << 3;
+
+ /* fall back to pio! */
+ if (!ide_build_dmatable(drive, rq)) {
+ ide_map_sg(drive, rq);
+ return 1;
+ }
+
+ /* PRD table */
+ out_be32((void __iomem *)hwif->dma_prdtable, hwif->dmatable_dma);
+
+ /* specify r/w */
+ out_be32((void __iomem *)hwif->dma_command, reading);
+
+ /* read dma_status for INTR & ERROR flags */
+ dma_stat = in_be32((void __iomem *)hwif->dma_status);
+
+ /* clear INTR & ERROR flags */
+ out_be32((void __iomem *)hwif->dma_status, dma_stat|6);
+ drive->waiting_for_dma = 1;
+ return 0;
+}
+
+
+/**
+ * scc_ide_dma_end - Stop DMA
+ * @drive: IDE drive
+ *
+ * Check and clear INT Status register.
+ * Then call __ide_dma_end().
+ */
+
+static int scc_ide_dma_end(ide_drive_t * drive)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ unsigned long intsts_port = hwif->dma_base + 0x014;
+ u32 reg;
+
+ while (1) {
+ reg = in_be32((void __iomem *)intsts_port);
+
+ if (reg & INTSTS_SERROR) {
+ printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME);
+ out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT);
+
+ out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ continue;
+ }
+
+ if (reg & INTSTS_PRERR) {
+ u32 maea0, maec0;
+ unsigned long ctl_base = hwif->config_data;
+
+ maea0 = in_be32((void __iomem *)(ctl_base + 0xF50));
+ maec0 = in_be32((void __iomem *)(ctl_base + 0xF54));
+
+ printk(KERN_WARNING "%s: PRERR [addr:%x cmd:%x]\n", SCC_PATA_NAME, maea0, maec0);
+
+ out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT);
+
+ out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ continue;
+ }
+
+ if (reg & INTSTS_RERR) {
+ printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME);
+ out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT);
+
+ out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+ continue;
+ }
+
+ if (reg & INTSTS_ICERR) {
+ out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+
+ printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME);
+ out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT);
+ continue;
+ }
+
+ if (reg & INTSTS_BMSINT) {
+ printk(KERN_WARNING "%s: Internal Bus Error\n", SCC_PATA_NAME);
+ out_be32((void __iomem *)intsts_port, INTSTS_BMSINT);
+
+ ide_do_reset(drive);
+ continue;
+ }
+
+ if (reg & INTSTS_BMHE) {
+ out_be32((void __iomem *)intsts_port, INTSTS_BMHE);
+ continue;
+ }
+
+ if (reg & INTSTS_ACTEINT) {
+ out_be32((void __iomem *)intsts_port, INTSTS_ACTEINT);
+ continue;
+ }
+
+ if (reg & INTSTS_IOIRQS) {
+ out_be32((void __iomem *)intsts_port, INTSTS_IOIRQS);
+ continue;
+ }
+ break;
+ }
+
+ return __ide_dma_end(drive);
+}
+
+/**
+ * setup_mmio_scc - map CTRL/BMID region
+ * @dev: PCI device we are configuring
+ * @name: device name
+ *
+ */
+
+static int setup_mmio_scc (struct pci_dev *dev, const char *name)
+{
+ unsigned long ctl_base = pci_resource_start(dev, 0);
+ unsigned long dma_base = pci_resource_start(dev, 1);
+ unsigned long ctl_size = pci_resource_len(dev, 0);
+ unsigned long dma_size = pci_resource_len(dev, 1);
+ void *ctl_addr;
+ void *dma_addr;
+ int i;
+
+ for (i = 0; i < MAX_HWIFS; i++) {
+ if (scc_ports[i].ctl == 0)
+ break;
+ }
+ if (i >= MAX_HWIFS)
+ return -ENOMEM;
+
+ if (!request_mem_region(ctl_base, ctl_size, name)) {
+ printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
+ goto fail_0;
+ }
+
+ if (!request_mem_region(dma_base, dma_size, name)) {
+ printk(KERN_WARNING "%s: IDE controller MMIO ports not available.\n", SCC_PATA_NAME);
+ goto fail_1;
+ }
+
+ if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL)
+ goto fail_2;
+
+ if ((dma_addr = ioremap(dma_base, dma_size)) == NULL)
+ goto fail_3;
+
+ pci_set_master(dev);
+ scc_ports[i].ctl = (unsigned long)ctl_addr;
+ scc_ports[i].dma = (unsigned long)dma_addr;
+ pci_set_drvdata(dev, (void *) &scc_ports[i]);
+
+ return 1;
+
+ fail_3:
+ iounmap(ctl_addr);
+ fail_2:
+ release_mem_region(dma_base, dma_size);
+ fail_1:
+ release_mem_region(ctl_base, ctl_size);
+ fail_0:
+ return -ENOMEM;
+}
+
+/**
+ * init_setup_scc - set up an SCC PATA Controller
+ * @dev: PCI device
+ * @d: IDE PCI device
+ *
+ * Perform the initial set up for this device.
+ */
+
+static int __devinit init_setup_scc(struct pci_dev *dev, ide_pci_device_t *d)
+{
+ unsigned long ctl_base;
+ unsigned long dma_base;
+ unsigned long cckctrl_port;
+ unsigned long intmask_port;
+ unsigned long mode_port;
+ unsigned long ecmode_port;
+ unsigned long dma_status_port;
+ u32 reg = 0;
+ struct scc_ports *ports;
+ int rc;
+
+ rc = setup_mmio_scc(dev, d->name);
+ if (rc < 0) {
+ return rc;
+ }
+
+ ports = pci_get_drvdata(dev);
+ ctl_base = ports->ctl;
+ dma_base = ports->dma;
+ cckctrl_port = ctl_base + 0xff0;
+ intmask_port = dma_base + 0x010;
+ mode_port = ctl_base + 0x024;
+ ecmode_port = ctl_base + 0xf00;
+ dma_status_port = dma_base + 0x004;
+
+ /* controller initialization */
+ reg = 0;
+ out_be32((void*)cckctrl_port, reg);
+ reg |= CCKCTRL_ATACLKOEN;
+ out_be32((void*)cckctrl_port, reg);
+ reg |= CCKCTRL_LCLKEN | CCKCTRL_OCLKEN;
+ out_be32((void*)cckctrl_port, reg);
+ reg |= CCKCTRL_CRST;
+ out_be32((void*)cckctrl_port, reg);
+
+ for (;;) {
+ reg = in_be32((void*)cckctrl_port);
+ if (reg & CCKCTRL_CRST)
+ break;
+ udelay(5000);
+ }
+
+ reg |= CCKCTRL_ATARESET;
+ out_be32((void*)cckctrl_port, reg);
+
+ out_be32((void*)ecmode_port, ECMODE_VALUE);
+ out_be32((void*)mode_port, MODE_JCUSFEN);
+ out_be32((void*)intmask_port, INTMASK_MSK);
+
+ return ide_setup_pci_device(dev, d);
+}
+
+/**
+ * init_mmio_iops_scc - set up the iops for MMIO
+ * @hwif: interface to set up
+ *
+ */
+
+static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
+{
+ struct pci_dev *dev = hwif->pci_dev;
+ struct scc_ports *ports = pci_get_drvdata(dev);
+ unsigned long dma_base = ports->dma;
+
+ ide_set_hwifdata(hwif, ports);
+
+ hwif->INB = scc_ide_inb;
+ hwif->INW = scc_ide_inw;
+ hwif->INSW = scc_ide_insw;
+ hwif->INSL = scc_ide_insl;
+ hwif->OUTB = scc_ide_outb;
+ hwif->OUTBSYNC = scc_ide_outbsync;
+ hwif->OUTW = scc_ide_outw;
+ hwif->OUTSW = scc_ide_outsw;
+ hwif->OUTSL = scc_ide_outsl;
+
+ hwif->io_ports[IDE_DATA_OFFSET] = dma_base + 0x20;
+ hwif->io_ports[IDE_ERROR_OFFSET] = dma_base + 0x24;
+ hwif->io_ports[IDE_NSECTOR_OFFSET] = dma_base + 0x28;
+ hwif->io_ports[IDE_SECTOR_OFFSET] = dma_base + 0x2c;
+ hwif->io_ports[IDE_LCYL_OFFSET] = dma_base + 0x30;
+ hwif->io_ports[IDE_HCYL_OFFSET] = dma_base + 0x34;
+ hwif->io_ports[IDE_SELECT_OFFSET] = dma_base + 0x38;
+ hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c;
+ hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40;
+
+ hwif->irq = hwif->pci_dev->irq;
+ hwif->dma_base = dma_base;
+ hwif->config_data = ports->ctl;
+ hwif->mmio = 1;
+}
+
+/**
+ * init_iops_scc - set up iops
+ * @hwif: interface to set up
+ *
+ * Do the basic setup for the SCC hardware interface
+ * and then do the MMIO setup.
+ */
+
+static void __devinit init_iops_scc(ide_hwif_t *hwif)
+{
+ struct pci_dev *dev = hwif->pci_dev;
+ hwif->hwif_data = NULL;
+ if (pci_get_drvdata(dev) == NULL)
+ return;
+ init_mmio_iops_scc(hwif);
+}
+
+/**
+ * init_hwif_scc - set up hwif
+ * @hwif: interface to set up
+ *
+ * We do the basic set up of the interface structure. The SCC
+ * requires several custom handlers so we override the default
+ * ide DMA handlers appropriately.
+ */
+
+static void __devinit init_hwif_scc(ide_hwif_t *hwif)
+{
+ struct scc_ports *ports = ide_get_hwifdata(hwif);
+
+ ports->hwif_id = hwif->index;
+
+ hwif->dma_command = hwif->dma_base;
+ hwif->dma_status = hwif->dma_base + 0x04;
+ hwif->dma_prdtable = hwif->dma_base + 0x08;
+
+ /* PTERADD */
+ out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
+
+ hwif->dma_setup = scc_dma_setup;
+ hwif->ide_dma_end = scc_ide_dma_end;
+ hwif->speedproc = scc_tune_chipset;
+ hwif->tuneproc = scc_tuneproc;
+ hwif->ide_dma_check = scc_config_drive_for_dma;
+
+ hwif->drives[0].autotune = IDE_TUNE_AUTO;
+ hwif->drives[1].autotune = IDE_TUNE_AUTO;
+
+ if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN) {
+ hwif->ultra_mask = 0x7f; /* 133MHz */
+ } else {
+ hwif->ultra_mask = 0x3f; /* 100MHz */
+ }
+ hwif->mwdma_mask = 0x00;
+ hwif->swdma_mask = 0x00;
+ hwif->atapi_dma = 1;
+
+ /* we support 80c cable only. */
+ hwif->udma_four = 1;
+
+ hwif->autodma = 0;
+ if (!noautodma)
+ hwif->autodma = 1;
+ hwif->drives[0].autodma = hwif->autodma;
+ hwif->drives[1].autodma = hwif->autodma;
+}
+
+#define DECLARE_SCC_DEV(name_str) \
+ { \
+ .name = name_str, \
+ .init_setup = init_setup_scc, \
+ .init_iops = init_iops_scc, \
+ .init_hwif = init_hwif_scc, \
+ .channels = 1, \
+ .autodma = AUTODMA, \
+ .bootable = ON_BOARD, \
+ }
+
+static ide_pci_device_t scc_chipsets[] __devinitdata = {
+ /* 0 */ DECLARE_SCC_DEV("sccIDE"),
+};
+
+/**
+ * scc_init_one - pci layer discovery entry
+ * @dev: PCI device
+ * @id: ident table entry
+ *
+ * Called by the PCI code when it finds an SCC PATA controller.
+ * We then use the IDE PCI generic helper to do most of the work.
+ */
+
+static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ ide_pci_device_t *d = &scc_chipsets[id->driver_data];
+ return d->init_setup(dev, d);
+}
+
+/**
+ * scc_remove - pci layer remove entry
+ * @dev: PCI device
+ *
+ * Called by the PCI code when it removes an SCC PATA controller.
+ */
+
+static void __devexit scc_remove(struct pci_dev *dev)
+{
+ struct scc_ports *ports = pci_get_drvdata(dev);
+ ide_hwif_t *hwif = &ide_hwifs[ports->hwif_id];
+ unsigned long ctl_base = pci_resource_start(dev, 0);
+ unsigned long dma_base = pci_resource_start(dev, 1);
+ unsigned long ctl_size = pci_resource_len(dev, 0);
+ unsigned long dma_size = pci_resource_len(dev, 1);
+
+ if (hwif->dmatable_cpu) {
+ pci_free_consistent(hwif->pci_dev,
+ PRD_ENTRIES * PRD_BYTES,
+ hwif->dmatable_cpu,
+ hwif->dmatable_dma);
+ hwif->dmatable_cpu = NULL;
+ }
+
+ ide_unregister(hwif->index);
+
+ hwif->chipset = ide_unknown;
+ iounmap((void*)ports->dma);
+ iounmap((void*)ports->ctl);
+ release_mem_region(dma_base, dma_size);
+ release_mem_region(ctl_base, ctl_size);
+ memset(ports, 0, sizeof(*ports));
+}
+
+static struct pci_device_id scc_pci_tbl[] = {
+ { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { 0, },
+};
+MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
+
+static struct pci_driver driver = {
+ .name = "SCC IDE",
+ .id_table = scc_pci_tbl,
+ .probe = scc_init_one,
+ .remove = scc_remove,
+};
+
+static int scc_ide_init(void)
+{
+ return ide_pci_register_driver(&driver);
+}
+
+module_init(scc_ide_init);
+/* -- No exit code?
+static void scc_ide_exit(void)
+{
+ ide_pci_unregister_driver(&driver);
+}
+module_exit(scc_ide_exit);
+ */
+
+
+MODULE_DESCRIPTION("PCI driver module for Toshiba SCC IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h
index 8f207508ed1..46878fef136 100644
--- a/drivers/ieee1394/ieee1394-ioctl.h
+++ b/drivers/ieee1394/ieee1394-ioctl.h
@@ -100,5 +100,7 @@
_IO ('#', 0x28)
#define RAW1394_IOC_ISO_RECV_FLUSH \
_IO ('#', 0x29)
+#define RAW1394_IOC_GET_CYCLE_TIMER \
+ _IOR ('#', 0x30, struct raw1394_cycle_timer)
#endif /* __IEEE1394_IOCTL_H */
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 1521e57e124..d791d08c743 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -33,7 +33,10 @@
#include <linux/skbuff.h>
#include <linux/suspend.h>
#include <linux/kthread.h>
+#include <linux/preempt.h>
+#include <linux/time.h>
+#include <asm/system.h>
#include <asm/byteorder.h>
#include "ieee1394_types.h"
@@ -186,6 +189,45 @@ int hpsb_reset_bus(struct hpsb_host *host, int type)
}
}
+/**
+ * hpsb_read_cycle_timer - read cycle timer register and system time
+ * @host: host whose isochronous cycle timer register is read
+ * @cycle_timer: address of bitfield to return the register contents
+ * @local_time: address to return the system time
+ *
+ * The format of * @cycle_timer, is described in OHCI 1.1 clause 5.13. This
+ * format is also read from non-OHCI controllers. * @local_time contains the
+ * system time in microseconds since the Epoch, read at the moment when the
+ * cycle timer was read.
+ *
+ * Return value: 0 for success or error number otherwise.
+ */
+int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
+ u64 *local_time)
+{
+ int ctr;
+ struct timeval tv;
+ unsigned long flags;
+
+ if (!host || !cycle_timer || !local_time)
+ return -EINVAL;
+
+ preempt_disable();
+ local_irq_save(flags);
+
+ ctr = host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
+ if (ctr)
+ do_gettimeofday(&tv);
+
+ local_irq_restore(flags);
+ preempt_enable();
+
+ if (!ctr)
+ return -EIO;
+ *cycle_timer = ctr;
+ *local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
+ return 0;
+}
int hpsb_bus_reset(struct hpsb_host *host)
{
@@ -1190,6 +1232,7 @@ EXPORT_SYMBOL(hpsb_alloc_packet);
EXPORT_SYMBOL(hpsb_free_packet);
EXPORT_SYMBOL(hpsb_send_packet);
EXPORT_SYMBOL(hpsb_reset_bus);
+EXPORT_SYMBOL(hpsb_read_cycle_timer);
EXPORT_SYMBOL(hpsb_bus_reset);
EXPORT_SYMBOL(hpsb_selfid_received);
EXPORT_SYMBOL(hpsb_selfid_complete);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index 536ba3f580f..bd29d8ef5bb 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -127,6 +127,9 @@ int hpsb_send_packet_and_wait(struct hpsb_packet *packet);
* progress, 0 otherwise. */
int hpsb_reset_bus(struct hpsb_host *host, int type);
+int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
+ u64 *local_time);
+
/*
* The following functions are exported for host driver module usage. All of
* them are safe to use in interrupt contexts, although some are quite
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index ba9faeff479..c5ace190bfe 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -1681,7 +1681,8 @@ static int nodemgr_host_thread(void *__hi)
for (;;) {
/* Sleep until next bus reset */
set_current_state(TASK_INTERRUPTIBLE);
- if (get_hpsb_generation(host) == generation)
+ if (get_hpsb_generation(host) == generation &&
+ !kthread_should_stop())
schedule();
__set_current_state(TASK_RUNNING);
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index aa9ca8385ec..bb897a37d9f 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -2669,6 +2669,18 @@ static void raw1394_iso_shutdown(struct file_info *fi)
fi->iso_state = RAW1394_ISO_INACTIVE;
}
+static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr)
+{
+ struct raw1394_cycle_timer ct;
+ int err;
+
+ err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
+ if (!err)
+ if (copy_to_user(uaddr, &ct, sizeof(ct)))
+ err = -EFAULT;
+ return err;
+}
+
/* mmap the rawiso xmit/recv buffer */
static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
{
@@ -2777,6 +2789,14 @@ static int raw1394_ioctl(struct inode *inode, struct file *file,
break;
}
+ /* state-independent commands */
+ switch(cmd) {
+ case RAW1394_IOC_GET_CYCLE_TIMER:
+ return raw1394_read_cycle_timer(fi, argp);
+ default:
+ break;
+ }
+
return -EINVAL;
}
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
index 35bfc38f013..7bd22ee1afb 100644
--- a/drivers/ieee1394/raw1394.h
+++ b/drivers/ieee1394/raw1394.h
@@ -178,4 +178,14 @@ struct raw1394_iso_status {
__s16 xmit_cycle;
};
+/* argument to RAW1394_IOC_GET_CYCLE_TIMER ioctl */
+struct raw1394_cycle_timer {
+ /* contents of Isochronous Cycle Timer register,
+ as in OHCI 1.1 clause 5.13 (also with non-OHCI hosts) */
+ __u32 cycle_timer;
+
+ /* local time in microseconds since Epoch,
+ simultaneously read with cycle timer */
+ __u64 local_time;
+};
#endif /* IEEE1394_RAW1394_H */
diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index 50fb1cd447b..189e5d4b9b1 100644
--- a/drivers/infiniband/core/Makefile
+++ b/drivers/infiniband/core/Makefile
@@ -12,7 +12,7 @@ ib_core-y := packer.o ud_header.o verbs.o sysfs.o \
ib_mad-y := mad.o smi.o agent.o mad_rmpp.o
-ib_sa-y := sa_query.o
+ib_sa-y := sa_query.o multicast.o
ib_cm-y := cm.o
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index db88e609bf4..f8d69b3fa30 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -71,6 +71,7 @@ static struct workqueue_struct *cma_wq;
static DEFINE_IDR(sdp_ps);
static DEFINE_IDR(tcp_ps);
static DEFINE_IDR(udp_ps);
+static DEFINE_IDR(ipoib_ps);
static int next_port;
struct cma_device {
@@ -116,6 +117,7 @@ struct rdma_id_private {
struct list_head list;
struct list_head listen_list;
struct cma_device *cma_dev;
+ struct list_head mc_list;
enum cma_state state;
spinlock_t lock;
@@ -134,10 +136,23 @@ struct rdma_id_private {
} cm_id;
u32 seq_num;
+ u32 qkey;
u32 qp_num;
u8 srq;
};
+struct cma_multicast {
+ struct rdma_id_private *id_priv;
+ union {
+ struct ib_sa_multicast *ib;
+ } multicast;
+ struct list_head list;
+ void *context;
+ struct sockaddr addr;
+ u8 pad[sizeof(struct sockaddr_in6) -
+ sizeof(struct sockaddr)];
+};
+
struct cma_work {
struct work_struct work;
struct rdma_id_private *id;
@@ -243,6 +258,11 @@ static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver)
hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF);
}
+static inline int cma_is_ud_ps(enum rdma_port_space ps)
+{
+ return (ps == RDMA_PS_UDP || ps == RDMA_PS_IPOIB);
+}
+
static void cma_attach_to_dev(struct rdma_id_private *id_priv,
struct cma_device *cma_dev)
{
@@ -265,19 +285,41 @@ static void cma_detach_from_dev(struct rdma_id_private *id_priv)
id_priv->cma_dev = NULL;
}
+static int cma_set_qkey(struct ib_device *device, u8 port_num,
+ enum rdma_port_space ps,
+ struct rdma_dev_addr *dev_addr, u32 *qkey)
+{
+ struct ib_sa_mcmember_rec rec;
+ int ret = 0;
+
+ switch (ps) {
+ case RDMA_PS_UDP:
+ *qkey = RDMA_UDP_QKEY;
+ break;
+ case RDMA_PS_IPOIB:
+ ib_addr_get_mgid(dev_addr, &rec.mgid);
+ ret = ib_sa_get_mcmember_rec(device, port_num, &rec.mgid, &rec);
+ *qkey = be32_to_cpu(rec.qkey);
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
static int cma_acquire_dev(struct rdma_id_private *id_priv)
{
- enum rdma_node_type dev_type = id_priv->id.route.addr.dev_addr.dev_type;
+ struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
struct cma_device *cma_dev;
union ib_gid gid;
int ret = -ENODEV;
- switch (rdma_node_get_transport(dev_type)) {
+ switch (rdma_node_get_transport(dev_addr->dev_type)) {
case RDMA_TRANSPORT_IB:
- ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+ ib_addr_get_sgid(dev_addr, &gid);
break;
case RDMA_TRANSPORT_IWARP:
- iw_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+ iw_addr_get_sgid(dev_addr, &gid);
break;
default:
return -ENODEV;
@@ -287,7 +329,12 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
ret = ib_find_cached_gid(cma_dev->device, &gid,
&id_priv->id.port_num, NULL);
if (!ret) {
- cma_attach_to_dev(id_priv, cma_dev);
+ ret = cma_set_qkey(cma_dev->device,
+ id_priv->id.port_num,
+ id_priv->id.ps, dev_addr,
+ &id_priv->qkey);
+ if (!ret)
+ cma_attach_to_dev(id_priv, cma_dev);
break;
}
}
@@ -325,40 +372,50 @@ struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
init_waitqueue_head(&id_priv->wait_remove);
atomic_set(&id_priv->dev_remove, 0);
INIT_LIST_HEAD(&id_priv->listen_list);
+ INIT_LIST_HEAD(&id_priv->mc_list);
get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
return &id_priv->id;
}
EXPORT_SYMBOL(rdma_create_id);
-static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
+static int cma_init_ud_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
{
struct ib_qp_attr qp_attr;
- struct rdma_dev_addr *dev_addr;
- int ret;
+ int qp_attr_mask, ret;
- dev_addr = &id_priv->id.route.addr.dev_addr;
- ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
- ib_addr_get_pkey(dev_addr),
- &qp_attr.pkey_index);
+ qp_attr.qp_state = IB_QPS_INIT;
+ ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
if (ret)
return ret;
- qp_attr.qp_state = IB_QPS_INIT;
- qp_attr.qp_access_flags = 0;
- qp_attr.port_num = id_priv->id.port_num;
- return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS |
- IB_QP_PKEY_INDEX | IB_QP_PORT);
+ ret = ib_modify_qp(qp, &qp_attr, qp_attr_mask);
+ if (ret)
+ return ret;
+
+ qp_attr.qp_state = IB_QPS_RTR;
+ ret = ib_modify_qp(qp, &qp_attr, IB_QP_STATE);
+ if (ret)
+ return ret;
+
+ qp_attr.qp_state = IB_QPS_RTS;
+ qp_attr.sq_psn = 0;
+ ret = ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_SQ_PSN);
+
+ return ret;
}
-static int cma_init_iw_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
+static int cma_init_conn_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
{
struct ib_qp_attr qp_attr;
+ int qp_attr_mask, ret;
qp_attr.qp_state = IB_QPS_INIT;
- qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+ ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
+ if (ret)
+ return ret;
- return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS);
+ return ib_modify_qp(qp, &qp_attr, qp_attr_mask);
}
int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
@@ -376,18 +433,10 @@ int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
if (IS_ERR(qp))
return PTR_ERR(qp);
- switch (rdma_node_get_transport(id->device->node_type)) {
- case RDMA_TRANSPORT_IB:
- ret = cma_init_ib_qp(id_priv, qp);
- break;
- case RDMA_TRANSPORT_IWARP:
- ret = cma_init_iw_qp(id_priv, qp);
- break;
- default:
- ret = -ENOSYS;
- break;
- }
-
+ if (cma_is_ud_ps(id_priv->id.ps))
+ ret = cma_init_ud_qp(id_priv, qp);
+ else
+ ret = cma_init_conn_qp(id_priv, qp);
if (ret)
goto err;
@@ -460,23 +509,55 @@ static int cma_modify_qp_err(struct rdma_cm_id *id)
return ib_modify_qp(id->qp, &qp_attr, IB_QP_STATE);
}
+static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,
+ struct ib_qp_attr *qp_attr, int *qp_attr_mask)
+{
+ struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+ int ret;
+
+ ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
+ ib_addr_get_pkey(dev_addr),
+ &qp_attr->pkey_index);
+ if (ret)
+ return ret;
+
+ qp_attr->port_num = id_priv->id.port_num;
+ *qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT;
+
+ if (cma_is_ud_ps(id_priv->id.ps)) {
+ qp_attr->qkey = id_priv->qkey;
+ *qp_attr_mask |= IB_QP_QKEY;
+ } else {
+ qp_attr->qp_access_flags = 0;
+ *qp_attr_mask |= IB_QP_ACCESS_FLAGS;
+ }
+ return 0;
+}
+
int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
int *qp_attr_mask)
{
struct rdma_id_private *id_priv;
- int ret;
+ int ret = 0;
id_priv = container_of(id, struct rdma_id_private, id);
switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
case RDMA_TRANSPORT_IB:
- ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
- qp_attr_mask);
+ if (!id_priv->cm_id.ib || cma_is_ud_ps(id_priv->id.ps))
+ ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask);
+ else
+ ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
+ qp_attr_mask);
if (qp_attr->qp_state == IB_QPS_RTR)
qp_attr->rq_psn = id_priv->seq_num;
break;
case RDMA_TRANSPORT_IWARP:
- ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,
- qp_attr_mask);
+ if (!id_priv->cm_id.iw) {
+ qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+ *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS;
+ } else
+ ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,
+ qp_attr_mask);
break;
default:
ret = -ENOSYS;
@@ -698,6 +779,19 @@ static void cma_release_port(struct rdma_id_private *id_priv)
mutex_unlock(&lock);
}
+static void cma_leave_mc_groups(struct rdma_id_private *id_priv)
+{
+ struct cma_multicast *mc;
+
+ while (!list_empty(&id_priv->mc_list)) {
+ mc = container_of(id_priv->mc_list.next,
+ struct cma_multicast, list);
+ list_del(&mc->list);
+ ib_sa_free_multicast(mc->multicast.ib);
+ kfree(mc);
+ }
+}
+
void rdma_destroy_id(struct rdma_cm_id *id)
{
struct rdma_id_private *id_priv;
@@ -722,6 +816,7 @@ void rdma_destroy_id(struct rdma_cm_id *id)
default:
break;
}
+ cma_leave_mc_groups(id_priv);
mutex_lock(&lock);
cma_detach_from_dev(id_priv);
}
@@ -972,7 +1067,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
memset(&event, 0, sizeof event);
offset = cma_user_data_offset(listen_id->id.ps);
event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
- if (listen_id->id.ps == RDMA_PS_UDP) {
+ if (cma_is_ud_ps(listen_id->id.ps)) {
conn_id = cma_new_udp_id(&listen_id->id, ib_event);
event.param.ud.private_data = ib_event->private_data + offset;
event.param.ud.private_data_len =
@@ -1725,7 +1820,7 @@ static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
struct rdma_bind_list *bind_list;
int port, ret;
- bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
+ bind_list = kmalloc(sizeof *bind_list, GFP_KERNEL);
if (!bind_list)
return -ENOMEM;
@@ -1847,6 +1942,9 @@ static int cma_get_port(struct rdma_id_private *id_priv)
case RDMA_PS_UDP:
ps = &udp_ps;
break;
+ case RDMA_PS_IPOIB:
+ ps = &ipoib_ps;
+ break;
default:
return -EPROTONOSUPPORT;
}
@@ -1961,7 +2059,7 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
event.status = ib_event->param.sidr_rep_rcvd.status;
break;
}
- if (rep->qkey != RDMA_UD_QKEY) {
+ if (id_priv->qkey != rep->qkey) {
event.event = RDMA_CM_EVENT_UNREACHABLE;
event.status = -EINVAL;
break;
@@ -2160,7 +2258,7 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
switch (rdma_node_get_transport(id->device->node_type)) {
case RDMA_TRANSPORT_IB:
- if (id->ps == RDMA_PS_UDP)
+ if (cma_is_ud_ps(id->ps))
ret = cma_resolve_ib_udp(id_priv, conn_param);
else
ret = cma_connect_ib(id_priv, conn_param);
@@ -2256,7 +2354,7 @@ static int cma_send_sidr_rep(struct rdma_id_private *id_priv,
rep.status = status;
if (status == IB_SIDR_SUCCESS) {
rep.qp_num = id_priv->qp_num;
- rep.qkey = RDMA_UD_QKEY;
+ rep.qkey = id_priv->qkey;
}
rep.private_data = private_data;
rep.private_data_len = private_data_len;
@@ -2280,7 +2378,7 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
switch (rdma_node_get_transport(id->device->node_type)) {
case RDMA_TRANSPORT_IB:
- if (id->ps == RDMA_PS_UDP)
+ if (cma_is_ud_ps(id->ps))
ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
conn_param->private_data,
conn_param->private_data_len);
@@ -2341,7 +2439,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
switch (rdma_node_get_transport(id->device->node_type)) {
case RDMA_TRANSPORT_IB:
- if (id->ps == RDMA_PS_UDP)
+ if (cma_is_ud_ps(id->ps))
ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT,
private_data, private_data_len);
else
@@ -2392,6 +2490,178 @@ out:
}
EXPORT_SYMBOL(rdma_disconnect);
+static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
+{
+ struct rdma_id_private *id_priv;
+ struct cma_multicast *mc = multicast->context;
+ struct rdma_cm_event event;
+ int ret;
+
+ id_priv = mc->id_priv;
+ atomic_inc(&id_priv->dev_remove);
+ if (!cma_comp(id_priv, CMA_ADDR_BOUND) &&
+ !cma_comp(id_priv, CMA_ADDR_RESOLVED))
+ goto out;
+
+ if (!status && id_priv->id.qp)
+ status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid,
+ multicast->rec.mlid);
+
+ memset(&event, 0, sizeof event);
+ event.status = status;
+ event.param.ud.private_data = mc->context;
+ if (!status) {
+ event.event = RDMA_CM_EVENT_MULTICAST_JOIN;
+ ib_init_ah_from_mcmember(id_priv->id.device,
+ id_priv->id.port_num, &multicast->rec,
+ &event.param.ud.ah_attr);
+ event.param.ud.qp_num = 0xFFFFFF;
+ event.param.ud.qkey = be32_to_cpu(multicast->rec.qkey);
+ } else
+ event.event = RDMA_CM_EVENT_MULTICAST_ERROR;
+
+ ret = id_priv->id.event_handler(&id_priv->id, &event);
+ if (ret) {
+ cma_exch(id_priv, CMA_DESTROYING);
+ cma_release_remove(id_priv);
+ rdma_destroy_id(&id_priv->id);
+ return 0;
+ }
+out:
+ cma_release_remove(id_priv);
+ return 0;
+}
+
+static void cma_set_mgid(struct rdma_id_private *id_priv,
+ struct sockaddr *addr, union ib_gid *mgid)
+{
+ unsigned char mc_map[MAX_ADDR_LEN];
+ struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+ struct sockaddr_in *sin = (struct sockaddr_in *) addr;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
+
+ if (cma_any_addr(addr)) {
+ memset(mgid, 0, sizeof *mgid);
+ } else if ((addr->sa_family == AF_INET6) &&
+ ((be32_to_cpu(sin6->sin6_addr.s6_addr32[0]) & 0xFF10A01B) ==
+ 0xFF10A01B)) {
+ /* IPv6 address is an SA assigned MGID. */
+ memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
+ } else {
+ ip_ib_mc_map(sin->sin_addr.s_addr, mc_map);
+ if (id_priv->id.ps == RDMA_PS_UDP)
+ mc_map[7] = 0x01; /* Use RDMA CM signature */
+ mc_map[8] = ib_addr_get_pkey(dev_addr) >> 8;
+ mc_map[9] = (unsigned char) ib_addr_get_pkey(dev_addr);
+ *mgid = *(union ib_gid *) (mc_map + 4);
+ }
+}
+
+static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
+ struct cma_multicast *mc)
+{
+ struct ib_sa_mcmember_rec rec;
+ struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+ ib_sa_comp_mask comp_mask;
+ int ret;
+
+ ib_addr_get_mgid(dev_addr, &rec.mgid);
+ ret = ib_sa_get_mcmember_rec(id_priv->id.device, id_priv->id.port_num,
+ &rec.mgid, &rec);
+ if (ret)
+ return ret;
+
+ cma_set_mgid(id_priv, &mc->addr, &rec.mgid);
+ if (id_priv->id.ps == RDMA_PS_UDP)
+ rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
+ ib_addr_get_sgid(dev_addr, &rec.port_gid);
+ rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
+ rec.join_state = 1;
+
+ comp_mask = IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
+ IB_SA_MCMEMBER_REC_PKEY | IB_SA_MCMEMBER_REC_JOIN_STATE |
+ IB_SA_MCMEMBER_REC_QKEY | IB_SA_MCMEMBER_REC_SL |
+ IB_SA_MCMEMBER_REC_FLOW_LABEL |
+ IB_SA_MCMEMBER_REC_TRAFFIC_CLASS;
+
+ mc->multicast.ib = ib_sa_join_multicast(&sa_client, id_priv->id.device,
+ id_priv->id.port_num, &rec,
+ comp_mask, GFP_KERNEL,
+ cma_ib_mc_handler, mc);
+ if (IS_ERR(mc->multicast.ib))
+ return PTR_ERR(mc->multicast.ib);
+
+ return 0;
+}
+
+int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
+ void *context)
+{
+ struct rdma_id_private *id_priv;
+ struct cma_multicast *mc;
+ int ret;
+
+ id_priv = container_of(id, struct rdma_id_private, id);
+ if (!cma_comp(id_priv, CMA_ADDR_BOUND) &&
+ !cma_comp(id_priv, CMA_ADDR_RESOLVED))
+ return -EINVAL;
+
+ mc = kmalloc(sizeof *mc, GFP_KERNEL);
+ if (!mc)
+ return -ENOMEM;
+
+ memcpy(&mc->addr, addr, ip_addr_size(addr));
+ mc->context = context;
+ mc->id_priv = id_priv;
+
+ spin_lock(&id_priv->lock);
+ list_add(&mc->list, &id_priv->mc_list);
+ spin_unlock(&id_priv->lock);
+
+ switch (rdma_node_get_transport(id->device->node_type)) {
+ case RDMA_TRANSPORT_IB:
+ ret = cma_join_ib_multicast(id_priv, mc);
+ break;
+ default:
+ ret = -ENOSYS;
+ break;
+ }
+
+ if (ret) {
+ spin_lock_irq(&id_priv->lock);
+ list_del(&mc->list);
+ spin_unlock_irq(&id_priv->lock);
+ kfree(mc);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(rdma_join_multicast);
+
+void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
+{
+ struct rdma_id_private *id_priv;
+ struct cma_multicast *mc;
+
+ id_priv = container_of(id, struct rdma_id_private, id);
+ spin_lock_irq(&id_priv->lock);
+ list_for_each_entry(mc, &id_priv->mc_list, list) {
+ if (!memcmp(&mc->addr, addr, ip_addr_size(addr))) {
+ list_del(&mc->list);
+ spin_unlock_irq(&id_priv->lock);
+
+ if (id->qp)
+ ib_detach_mcast(id->qp,
+ &mc->multicast.ib->rec.mgid,
+ mc->multicast.ib->rec.mlid);
+ ib_sa_free_multicast(mc->multicast.ib);
+ kfree(mc);
+ return;
+ }
+ }
+ spin_unlock_irq(&id_priv->lock);
+}
+EXPORT_SYMBOL(rdma_leave_multicast);
+
static void cma_add_one(struct ib_device *device)
{
struct cma_device *cma_dev;
@@ -2522,6 +2792,7 @@ static void cma_cleanup(void)
idr_destroy(&sdp_ps);
idr_destroy(&tcp_ps);
idr_destroy(&udp_ps);
+ idr_destroy(&ipoib_ps);
}
module_init(cma_init);
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
index 8926a2bd4a8..1d796e7c819 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -301,7 +301,7 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd *pd,
{
struct ib_pool_fmr *fmr;
- struct ib_fmr_attr attr = {
+ struct ib_fmr_attr fmr_attr = {
.max_pages = params->max_pages_per_fmr,
.max_maps = pool->max_remaps,
.page_shift = params->page_shift
@@ -321,7 +321,7 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd *pd,
fmr->ref_count = 0;
INIT_HLIST_NODE(&fmr->cache_node);
- fmr->fmr = ib_alloc_fmr(pd, params->access, &attr);
+ fmr->fmr = ib_alloc_fmr(pd, params->access, &fmr_attr);
if (IS_ERR(fmr->fmr)) {
printk(KERN_WARNING "fmr_create failed for FMR %d", i);
kfree(fmr);
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index 1039ad57d53..891d1fa7b2e 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -146,6 +146,12 @@ static int copy_private_data(struct iw_cm_event *event)
return 0;
}
+static void free_cm_id(struct iwcm_id_private *cm_id_priv)
+{
+ dealloc_work_entries(cm_id_priv);
+ kfree(cm_id_priv);
+}
+
/*
* Release a reference on cm_id. If the last reference is being
* released, enable the waiting thread (in iw_destroy_cm_id) to
@@ -153,21 +159,14 @@ static int copy_private_data(struct iw_cm_event *event)
*/
static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
{
- int ret = 0;
-
BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
if (atomic_dec_and_test(&cm_id_priv->refcount)) {
BUG_ON(!list_empty(&cm_id_priv->work_list));
- if (waitqueue_active(&cm_id_priv->destroy_comp.wait)) {
- BUG_ON(cm_id_priv->state != IW_CM_STATE_DESTROYING);
- BUG_ON(test_bit(IWCM_F_CALLBACK_DESTROY,
- &cm_id_priv->flags));
- ret = 1;
- }
complete(&cm_id_priv->destroy_comp);
+ return 1;
}
- return ret;
+ return 0;
}
static void add_ref(struct iw_cm_id *cm_id)
@@ -181,7 +180,11 @@ static void rem_ref(struct iw_cm_id *cm_id)
{
struct iwcm_id_private *cm_id_priv;
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
- iwcm_deref_id(cm_id_priv);
+ if (iwcm_deref_id(cm_id_priv) &&
+ test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
+ BUG_ON(!list_empty(&cm_id_priv->work_list));
+ free_cm_id(cm_id_priv);
+ }
}
static int cm_event_handler(struct iw_cm_id *cm_id, struct iw_cm_event *event);
@@ -355,7 +358,9 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
case IW_CM_STATE_CONN_RECV:
/*
* App called destroy before/without calling accept after
- * receiving connection request event notification.
+ * receiving connection request event notification or
+ * returned non zero from the event callback function.
+ * In either case, must tell the provider to reject.
*/
cm_id_priv->state = IW_CM_STATE_DESTROYING;
break;
@@ -391,9 +396,7 @@ void iw_destroy_cm_id(struct iw_cm_id *cm_id)
wait_for_completion(&cm_id_priv->destroy_comp);
- dealloc_work_entries(cm_id_priv);
-
- kfree(cm_id_priv);
+ free_cm_id(cm_id_priv);
}
EXPORT_SYMBOL(iw_destroy_cm_id);
@@ -647,10 +650,11 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
/* Call the client CM handler */
ret = cm_id->cm_handler(cm_id, iw_event);
if (ret) {
+ iw_cm_reject(cm_id, NULL, 0);
set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
destroy_cm_id(cm_id);
if (atomic_read(&cm_id_priv->refcount)==0)
- kfree(cm_id);
+ free_cm_id(cm_id_priv);
}
out:
@@ -854,13 +858,12 @@ static void cm_work_handler(struct work_struct *_work)
destroy_cm_id(&cm_id_priv->id);
}
BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
- if (iwcm_deref_id(cm_id_priv))
- return;
-
- if (atomic_read(&cm_id_priv->refcount)==0 &&
- test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
- dealloc_work_entries(cm_id_priv);
- kfree(cm_id_priv);
+ if (iwcm_deref_id(cm_id_priv)) {
+ if (test_bit(IWCM_F_CALLBACK_DESTROY,
+ &cm_id_priv->flags)) {
+ BUG_ON(!list_empty(&cm_id_priv->work_list));
+ free_cm_id(cm_id_priv);
+ }
return;
}
spin_lock_irqsave(&cm_id_priv->lock, flags);
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
new file mode 100644
index 00000000000..4a579b3a1c9
--- /dev/null
+++ b/drivers/infiniband/core/multicast.c
@@ -0,0 +1,837 @@
+/*
+ * Copyright (c) 2006 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <linux/random.h>
+
+#include <rdma/ib_cache.h>
+#include "sa.h"
+
+static void mcast_add_one(struct ib_device *device);
+static void mcast_remove_one(struct ib_device *device);
+
+static struct ib_client mcast_client = {
+ .name = "ib_multicast",
+ .add = mcast_add_one,
+ .remove = mcast_remove_one
+};
+
+static struct ib_sa_client sa_client;
+static struct workqueue_struct *mcast_wq;
+static union ib_gid mgid0;
+
+struct mcast_device;
+
+struct mcast_port {
+ struct mcast_device *dev;
+ spinlock_t lock;
+ struct rb_root table;
+ atomic_t refcount;
+ struct completion comp;
+ u8 port_num;
+};
+
+struct mcast_device {
+ struct ib_device *device;
+ struct ib_event_handler event_handler;
+ int start_port;
+ int end_port;
+ struct mcast_port port[0];
+};
+
+enum mcast_state {
+ MCAST_IDLE,
+ MCAST_JOINING,
+ MCAST_MEMBER,
+ MCAST_BUSY,
+ MCAST_ERROR
+};
+
+struct mcast_member;
+
+struct mcast_group {
+ struct ib_sa_mcmember_rec rec;
+ struct rb_node node;
+ struct mcast_port *port;
+ spinlock_t lock;
+ struct work_struct work;
+ struct list_head pending_list;
+ struct list_head active_list;
+ struct mcast_member *last_join;
+ int members[3];
+ atomic_t refcount;
+ enum mcast_state state;
+ struct ib_sa_query *query;
+ int query_id;
+};
+
+struct mcast_member {
+ struct ib_sa_multicast multicast;
+ struct ib_sa_client *client;
+ struct mcast_group *group;
+ struct list_head list;
+ enum mcast_state state;
+ atomic_t refcount;
+ struct completion comp;
+};
+
+static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
+ void *context);
+static void leave_handler(int status, struct ib_sa_mcmember_rec *rec,
+ void *context);
+
+static struct mcast_group *mcast_find(struct mcast_port *port,
+ union ib_gid *mgid)
+{
+ struct rb_node *node = port->table.rb_node;
+ struct mcast_group *group;
+ int ret;
+
+ while (node) {
+ group = rb_entry(node, struct mcast_group, node);
+ ret = memcmp(mgid->raw, group->rec.mgid.raw, sizeof *mgid);
+ if (!ret)
+ return group;
+
+ if (ret < 0)
+ node = node->rb_left;
+ else
+ node = node->rb_right;
+ }
+ return NULL;
+}
+
+static struct mcast_group *mcast_insert(struct mcast_port *port,
+ struct mcast_group *group,
+ int allow_duplicates)
+{
+ struct rb_node **link = &port->table.rb_node;
+ struct rb_node *parent = NULL;
+ struct mcast_group *cur_group;
+ int ret;
+
+ while (*link) {
+ parent = *link;
+ cur_group = rb_entry(parent, struct mcast_group, node);
+
+ ret = memcmp(group->rec.mgid.raw, cur_group->rec.mgid.raw,
+ sizeof group->rec.mgid);
+ if (ret < 0)
+ link = &(*link)->rb_left;
+ else if (ret > 0)
+ link = &(*link)->rb_right;
+ else if (allow_duplicates)
+ link = &(*link)->rb_left;
+ else
+ return cur_group;
+ }
+ rb_link_node(&group->node, parent, link);
+ rb_insert_color(&group->node, &port->table);
+ return NULL;
+}
+
+static void deref_port(struct mcast_port *port)
+{
+ if (atomic_dec_and_test(&port->refcount))
+ complete(&port->comp);
+}
+
+static void release_group(struct mcast_group *group)
+{
+ struct mcast_port *port = group->port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (atomic_dec_and_test(&group->refcount)) {
+ rb_erase(&group->node, &port->table);
+ spin_unlock_irqrestore(&port->lock, flags);
+ kfree(group);
+ deref_port(port);
+ } else
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void deref_member(struct mcast_member *member)
+{
+ if (atomic_dec_and_test(&member->refcount))
+ complete(&member->comp);
+}
+
+static void queue_join(struct mcast_member *member)
+{
+ struct mcast_group *group = member->group;
+ unsigned long flags;
+
+ spin_lock_irqsave(&group->lock, flags);
+ list_add(&member->list, &group->pending_list);
+ if (group->state == MCAST_IDLE) {
+ group->state = MCAST_BUSY;
+ atomic_inc(&group->refcount);
+ queue_work(mcast_wq, &group->work);
+ }
+ spin_unlock_irqrestore(&group->lock, flags);
+}
+
+/*
+ * A multicast group has three types of members: full member, non member, and
+ * send only member. We need to keep track of the number of members of each
+ * type based on their join state. Adjust the number of members the belong to
+ * the specified join states.
+ */
+static void adjust_membership(struct mcast_group *group, u8 join_state, int inc)
+{
+ int i;
+
+ for (i = 0; i < 3; i++, join_state >>= 1)
+ if (join_state & 0x1)
+ group->members[i] += inc;
+}
+
+/*
+ * If a multicast group has zero members left for a particular join state, but
+ * the group is still a member with the SA, we need to leave that join state.
+ * Determine which join states we still belong to, but that do not have any
+ * active members.
+ */
+static u8 get_leave_state(struct mcast_group *group)
+{
+ u8 leave_state = 0;
+ int i;
+
+ for (i = 0; i < 3; i++)
+ if (!group->members[i])
+ leave_state |= (0x1 << i);
+
+ return leave_state & group->rec.join_state;
+}
+
+static int check_selector(ib_sa_comp_mask comp_mask,
+ ib_sa_comp_mask selector_mask,
+ ib_sa_comp_mask value_mask,
+ u8 selector, u8 src_value, u8 dst_value)
+{
+ int err;
+
+ if (!(comp_mask & selector_mask) || !(comp_mask & value_mask))
+ return 0;
+
+ switch (selector) {
+ case IB_SA_GT:
+ err = (src_value <= dst_value);
+ break;
+ case IB_SA_LT:
+ err = (src_value >= dst_value);
+ break;
+ case IB_SA_EQ:
+ err = (src_value != dst_value);
+ break;
+ default:
+ err = 0;
+ break;
+ }
+
+ return err;
+}
+
+static int cmp_rec(struct ib_sa_mcmember_rec *src,
+ struct ib_sa_mcmember_rec *dst, ib_sa_comp_mask comp_mask)
+{
+ /* MGID must already match */
+
+ if (comp_mask & IB_SA_MCMEMBER_REC_PORT_GID &&
+ memcmp(&src->port_gid, &dst->port_gid, sizeof src->port_gid))
+ return -EINVAL;
+ if (comp_mask & IB_SA_MCMEMBER_REC_QKEY && src->qkey != dst->qkey)
+ return -EINVAL;
+ if (comp_mask & IB_SA_MCMEMBER_REC_MLID && src->mlid != dst->mlid)
+ return -EINVAL;
+ if (check_selector(comp_mask, IB_SA_MCMEMBER_REC_MTU_SELECTOR,
+ IB_SA_MCMEMBER_REC_MTU, dst->mtu_selector,
+ src->mtu, dst->mtu))
+ return -EINVAL;
+ if (comp_mask & IB_SA_MCMEMBER_REC_TRAFFIC_CLASS &&
+ src->traffic_class != dst->traffic_class)
+ return -EINVAL;
+ if (comp_mask & IB_SA_MCMEMBER_REC_PKEY && src->pkey != dst->pkey)
+ return -EINVAL;
+ if (check_selector(comp_mask, IB_SA_MCMEMBER_REC_RATE_SELECTOR,
+ IB_SA_MCMEMBER_REC_RATE, dst->rate_selector,
+ src->rate, dst->rate))
+ return -EINVAL;
+ if (check_selector(comp_mask,
+ IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME_SELECTOR,
+ IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME,
+ dst->packet_life_time_selector,
+ src->packet_life_time, dst->packet_life_time))
+ return -EINVAL;
+ if (comp_mask & IB_SA_MCMEMBER_REC_SL && src->sl != dst->sl)
+ return -EINVAL;
+ if (comp_mask & IB_SA_MCMEMBER_REC_FLOW_LABEL &&
+ src->flow_label != dst->flow_label)
+ return -EINVAL;
+ if (comp_mask & IB_SA_MCMEMBER_REC_HOP_LIMIT &&
+ src->hop_limit != dst->hop_limit)
+ return -EINVAL;
+ if (comp_mask & IB_SA_MCMEMBER_REC_SCOPE && src->scope != dst->scope)
+ return -EINVAL;
+
+ /* join_state checked separately, proxy_join ignored */
+
+ return 0;
+}
+
+static int send_join(struct mcast_group *group, struct mcast_member *member)
+{
+ struct mcast_port *port = group->port;
+ int ret;
+
+ group->last_join = member;
+ ret = ib_sa_mcmember_rec_query(&sa_client, port->dev->device,
+ port->port_num, IB_MGMT_METHOD_SET,
+ &member->multicast.rec,
+ member->multicast.comp_mask,
+ 3000, GFP_KERNEL, join_handler, group,
+ &group->query);
+ if (ret >= 0) {
+ group->query_id = ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+static int send_leave(struct mcast_group *group, u8 leave_state)
+{
+ struct mcast_port *port = group->port;
+ struct ib_sa_mcmember_rec rec;
+ int ret;
+
+ rec = group->rec;
+ rec.join_state = leave_state;
+
+ ret = ib_sa_mcmember_rec_query(&sa_client, port->dev->device,
+ port->port_num, IB_SA_METHOD_DELETE, &rec,
+ IB_SA_MCMEMBER_REC_MGID |
+ IB_SA_MCMEMBER_REC_PORT_GID |
+ IB_SA_MCMEMBER_REC_JOIN_STATE,
+ 3000, GFP_KERNEL, leave_handler,
+ group, &group->query);
+ if (ret >= 0) {
+ group->query_id = ret;
+ ret = 0;
+ }
+ return ret;
+}
+
+static void join_group(struct mcast_group *group, struct mcast_member *member,
+ u8 join_state)
+{
+ member->state = MCAST_MEMBER;
+ adjust_membership(group, join_state, 1);
+ group->rec.join_state |= join_state;
+ member->multicast.rec = group->rec;
+ member->multicast.rec.join_state = join_state;
+ list_move(&member->list, &group->active_list);
+}
+
+static int fail_join(struct mcast_group *group, struct mcast_member *member,
+ int status)
+{
+ spin_lock_irq(&group->lock);
+ list_del_init(&member->list);
+ spin_unlock_irq(&group->lock);
+ return member->multicast.callback(status, &member->multicast);
+}
+
+static void process_group_error(struct mcast_group *group)
+{
+ struct mcast_member *member;
+ int ret;
+
+ spin_lock_irq(&group->lock);
+ while (!list_empty(&group->active_list)) {
+ member = list_entry(group->active_list.next,
+ struct mcast_member, list);
+ atomic_inc(&member->refcount);
+ list_del_init(&member->list);
+ adjust_membership(group, member->multicast.rec.join_state, -1);
+ member->state = MCAST_ERROR;
+ spin_unlock_irq(&group->lock);
+
+ ret = member->multicast.callback(-ENETRESET,
+ &member->multicast);
+ deref_member(member);
+ if (ret)
+ ib_sa_free_multicast(&member->multicast);
+ spin_lock_irq(&group->lock);
+ }
+
+ group->rec.join_state = 0;
+ group->state = MCAST_BUSY;
+ spin_unlock_irq(&group->lock);
+}
+
+static void mcast_work_handler(struct work_struct *work)
+{
+ struct mcast_group *group;
+ struct mcast_member *member;
+ struct ib_sa_multicast *multicast;
+ int status, ret;
+ u8 join_state;
+
+ group = container_of(work, typeof(*group), work);
+retest:
+ spin_lock_irq(&group->lock);
+ while (!list_empty(&group->pending_list) ||
+ (group->state == MCAST_ERROR)) {
+
+ if (group->state == MCAST_ERROR) {
+ spin_unlock_irq(&group->lock);
+ process_group_error(group);
+ goto retest;
+ }
+
+ member = list_entry(group->pending_list.next,
+ struct mcast_member, list);
+ multicast = &member->multicast;
+ join_state = multicast->rec.join_state;
+ atomic_inc(&member->refcount);
+
+ if (join_state == (group->rec.join_state & join_state)) {
+ status = cmp_rec(&group->rec, &multicast->rec,
+ multicast->comp_mask);
+ if (!status)
+ join_group(group, member, join_state);
+ else
+ list_del_init(&member->list);
+ spin_unlock_irq(&group->lock);
+ ret = multicast->callback(status, multicast);
+ } else {
+ spin_unlock_irq(&group->lock);
+ status = send_join(group, member);
+ if (!status) {
+ deref_member(member);
+ return;
+ }
+ ret = fail_join(group, member, status);
+ }
+
+ deref_member(member);
+ if (ret)
+ ib_sa_free_multicast(&member->multicast);
+ spin_lock_irq(&group->lock);
+ }
+
+ join_state = get_leave_state(group);
+ if (join_state) {
+ group->rec.join_state &= ~join_state;
+ spin_unlock_irq(&group->lock);
+ if (send_leave(group, join_state))
+ goto retest;
+ } else {
+ group->state = MCAST_IDLE;
+ spin_unlock_irq(&group->lock);
+ release_group(group);
+ }
+}
+
+/*
+ * Fail a join request if it is still active - at the head of the pending queue.
+ */
+static void process_join_error(struct mcast_group *group, int status)
+{
+ struct mcast_member *member;
+ int ret;
+
+ spin_lock_irq(&group->lock);
+ member = list_entry(group->pending_list.next,
+ struct mcast_member, list);
+ if (group->last_join == member) {
+ atomic_inc(&member->refcount);
+ list_del_init(&member->list);
+ spin_unlock_irq(&group->lock);
+ ret = member->multicast.callback(status, &member->multicast);
+ deref_member(member);
+ if (ret)
+ ib_sa_free_multicast(&member->multicast);
+ } else
+ spin_unlock_irq(&group->lock);
+}
+
+static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
+ void *context)
+{
+ struct mcast_group *group = context;
+
+ if (status)
+ process_join_error(group, status);
+ else {
+ spin_lock_irq(&group->port->lock);
+ group->rec = *rec;
+ if (!memcmp(&mgid0, &group->rec.mgid, sizeof mgid0)) {
+ rb_erase(&group->node, &group->port->table);
+ mcast_insert(group->port, group, 1);
+ }
+ spin_unlock_irq(&group->port->lock);
+ }
+ mcast_work_handler(&group->work);
+}
+
+static void leave_handler(int status, struct ib_sa_mcmember_rec *rec,
+ void *context)
+{
+ struct mcast_group *group = context;
+
+ mcast_work_handler(&group->work);
+}
+
+static struct mcast_group *acquire_group(struct mcast_port *port,
+ union ib_gid *mgid, gfp_t gfp_mask)
+{
+ struct mcast_group *group, *cur_group;
+ unsigned long flags;
+ int is_mgid0;
+
+ is_mgid0 = !memcmp(&mgid0, mgid, sizeof mgid0);
+ if (!is_mgid0) {
+ spin_lock_irqsave(&port->lock, flags);
+ group = mcast_find(port, mgid);
+ if (group)
+ goto found;
+ spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+ group = kzalloc(sizeof *group, gfp_mask);
+ if (!group)
+ return NULL;
+
+ group->port = port;
+ group->rec.mgid = *mgid;
+ INIT_LIST_HEAD(&group->pending_list);
+ INIT_LIST_HEAD(&group->active_list);
+ INIT_WORK(&group->work, mcast_work_handler);
+ spin_lock_init(&group->lock);
+
+ spin_lock_irqsave(&port->lock, flags);
+ cur_group = mcast_insert(port, group, is_mgid0);
+ if (cur_group) {
+ kfree(group);
+ group = cur_group;
+ } else
+ atomic_inc(&port->refcount);
+found:
+ atomic_inc(&group->refcount);
+ spin_unlock_irqrestore(&port->lock, flags);
+ return group;
+}
+
+/*
+ * We serialize all join requests to a single group to make our lives much
+ * easier. Otherwise, two users could try to join the same group
+ * simultaneously, with different configurations, one could leave while the
+ * join is in progress, etc., which makes locking around error recovery
+ * difficult.
+ */
+struct ib_sa_multicast *
+ib_sa_join_multicast(struct ib_sa_client *client,
+ struct ib_device *device, u8 port_num,
+ struct ib_sa_mcmember_rec *rec,
+ ib_sa_comp_mask comp_mask, gfp_t gfp_mask,
+ int (*callback)(int status,
+ struct ib_sa_multicast *multicast),
+ void *context)
+{
+ struct mcast_device *dev;
+ struct mcast_member *member;
+ struct ib_sa_multicast *multicast;
+ int ret;
+
+ dev = ib_get_client_data(device, &mcast_client);
+ if (!dev)
+ return ERR_PTR(-ENODEV);
+
+ member = kmalloc(sizeof *member, gfp_mask);
+ if (!member)
+ return ERR_PTR(-ENOMEM);
+
+ ib_sa_client_get(client);
+ member->client = client;
+ member->multicast.rec = *rec;
+ member->multicast.comp_mask = comp_mask;
+ member->multicast.callback = callback;
+ member->multicast.context = context;
+ init_completion(&member->comp);
+ atomic_set(&member->refcount, 1);
+ member->state = MCAST_JOINING;
+
+ member->group = acquire_group(&dev->port[port_num - dev->start_port],
+ &rec->mgid, gfp_mask);
+ if (!member->group) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /*
+ * The user will get the multicast structure in their callback. They
+ * could then free the multicast structure before we can return from
+ * this routine. So we save the pointer to return before queuing
+ * any callback.
+ */
+ multicast = &member->multicast;
+ queue_join(member);
+ return multicast;
+
+err:
+ ib_sa_client_put(client);
+ kfree(member);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(ib_sa_join_multicast);
+
+void ib_sa_free_multicast(struct ib_sa_multicast *multicast)
+{
+ struct mcast_member *member;
+ struct mcast_group *group;
+
+ member = container_of(multicast, struct mcast_member, multicast);
+ group = member->group;
+
+ spin_lock_irq(&group->lock);
+ if (member->state == MCAST_MEMBER)
+ adjust_membership(group, multicast->rec.join_state, -1);
+
+ list_del_init(&member->list);
+
+ if (group->state == MCAST_IDLE) {
+ group->state = MCAST_BUSY;
+ spin_unlock_irq(&group->lock);
+ /* Continue to hold reference on group until callback */
+ queue_work(mcast_wq, &group->work);
+ } else {
+ spin_unlock_irq(&group->lock);
+ release_group(group);
+ }
+
+ deref_member(member);
+ wait_for_completion(&member->comp);
+ ib_sa_client_put(member->client);
+ kfree(member);
+}
+EXPORT_SYMBOL(ib_sa_free_multicast);
+
+int ib_sa_get_mcmember_rec(struct ib_device *device, u8 port_num,
+ union ib_gid *mgid, struct ib_sa_mcmember_rec *rec)
+{
+ struct mcast_device *dev;
+ struct mcast_port *port;
+ struct mcast_group *group;
+ unsigned long flags;
+ int ret = 0;
+
+ dev = ib_get_client_data(device, &mcast_client);
+ if (!dev)
+ return -ENODEV;
+
+ port = &dev->port[port_num - dev->start_port];
+ spin_lock_irqsave(&port->lock, flags);
+ group = mcast_find(port, mgid);
+ if (group)
+ *rec = group->rec;
+ else
+ ret = -EADDRNOTAVAIL;
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(ib_sa_get_mcmember_rec);
+
+int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
+ struct ib_sa_mcmember_rec *rec,
+ struct ib_ah_attr *ah_attr)
+{
+ int ret;
+ u16 gid_index;
+ u8 p;
+
+ ret = ib_find_cached_gid(device, &rec->port_gid, &p, &gid_index);
+ if (ret)
+ return ret;
+
+ memset(ah_attr, 0, sizeof *ah_attr);
+ ah_attr->dlid = be16_to_cpu(rec->mlid);
+ ah_attr->sl = rec->sl;
+ ah_attr->port_num = port_num;
+ ah_attr->static_rate = rec->rate;
+
+ ah_attr->ah_flags = IB_AH_GRH;
+ ah_attr->grh.dgid = rec->mgid;
+
+ ah_attr->grh.sgid_index = (u8) gid_index;
+ ah_attr->grh.flow_label = be32_to_cpu(rec->flow_label);
+ ah_attr->grh.hop_limit = rec->hop_limit;
+ ah_attr->grh.traffic_class = rec->traffic_class;
+
+ return 0;
+}
+EXPORT_SYMBOL(ib_init_ah_from_mcmember);
+
+static void mcast_groups_lost(struct mcast_port *port)
+{
+ struct mcast_group *group;
+ struct rb_node *node;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ for (node = rb_first(&port->table); node; node = rb_next(node)) {
+ group = rb_entry(node, struct mcast_group, node);
+ spin_lock(&group->lock);
+ if (group->state == MCAST_IDLE) {
+ atomic_inc(&group->refcount);
+ queue_work(mcast_wq, &group->work);
+ }
+ group->state = MCAST_ERROR;
+ spin_unlock(&group->lock);
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void mcast_event_handler(struct ib_event_handler *handler,
+ struct ib_event *event)
+{
+ struct mcast_device *dev;
+
+ dev = container_of(handler, struct mcast_device, event_handler);
+
+ switch (event->event) {
+ case IB_EVENT_PORT_ERR:
+ case IB_EVENT_LID_CHANGE:
+ case IB_EVENT_SM_CHANGE:
+ case IB_EVENT_CLIENT_REREGISTER:
+ mcast_groups_lost(&dev->port[event->element.port_num -
+ dev->start_port]);
+ break;
+ default:
+ break;
+ }
+}
+
+static void mcast_add_one(struct ib_device *device)
+{
+ struct mcast_device *dev;
+ struct mcast_port *port;
+ int i;
+
+ if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+ return;
+
+ dev = kmalloc(sizeof *dev + device->phys_port_cnt * sizeof *port,
+ GFP_KERNEL);
+ if (!dev)
+ return;
+
+ if (device->node_type == RDMA_NODE_IB_SWITCH)
+ dev->start_port = dev->end_port = 0;
+ else {
+ dev->start_port = 1;
+ dev->end_port = device->phys_port_cnt;
+ }
+
+ for (i = 0; i <= dev->end_port - dev->start_port; i++) {
+ port = &dev->port[i];
+ port->dev = dev;
+ port->port_num = dev->start_port + i;
+ spin_lock_init(&port->lock);
+ port->table = RB_ROOT;
+ init_completion(&port->comp);
+ atomic_set(&port->refcount, 1);
+ }
+
+ dev->device = device;
+ ib_set_client_data(device, &mcast_client, dev);
+
+ INIT_IB_EVENT_HANDLER(&dev->event_handler, device, mcast_event_handler);
+ ib_register_event_handler(&dev->event_handler);
+}
+
+static void mcast_remove_one(struct ib_device *device)
+{
+ struct mcast_device *dev;
+ struct mcast_port *port;
+ int i;
+
+ dev = ib_get_client_data(device, &mcast_client);
+ if (!dev)
+ return;
+
+ ib_unregister_event_handler(&dev->event_handler);
+ flush_workqueue(mcast_wq);
+
+ for (i = 0; i <= dev->end_port - dev->start_port; i++) {
+ port = &dev->port[i];
+ deref_port(port);
+ wait_for_completion(&port->comp);
+ }
+
+ kfree(dev);
+}
+
+int mcast_init(void)
+{
+ int ret;
+
+ mcast_wq = create_singlethread_workqueue("ib_mcast");
+ if (!mcast_wq)
+ return -ENOMEM;
+
+ ib_sa_register_client(&sa_client);
+
+ ret = ib_register_client(&mcast_client);
+ if (ret)
+ goto err;
+ return 0;
+
+err:
+ ib_sa_unregister_client(&sa_client);
+ destroy_workqueue(mcast_wq);
+ return ret;
+}
+
+void mcast_cleanup(void)
+{
+ ib_unregister_client(&mcast_client);
+ ib_sa_unregister_client(&sa_client);
+ destroy_workqueue(mcast_wq);
+}
diff --git a/drivers/infiniband/core/sa.h b/drivers/infiniband/core/sa.h
new file mode 100644
index 00000000000..24c93fd320f
--- /dev/null
+++ b/drivers/infiniband/core/sa.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2004 Topspin Communications. All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
+ * Copyright (c) 2006 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef SA_H
+#define SA_H
+
+#include <rdma/ib_sa.h>
+
+static inline void ib_sa_client_get(struct ib_sa_client *client)
+{
+ atomic_inc(&client->users);
+}
+
+static inline void ib_sa_client_put(struct ib_sa_client *client)
+{
+ if (atomic_dec_and_test(&client->users))
+ complete(&client->comp);
+}
+
+int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
+ struct ib_device *device, u8 port_num,
+ u8 method,
+ struct ib_sa_mcmember_rec *rec,
+ ib_sa_comp_mask comp_mask,
+ int timeout_ms, gfp_t gfp_mask,
+ void (*callback)(int status,
+ struct ib_sa_mcmember_rec *resp,
+ void *context),
+ void *context,
+ struct ib_sa_query **sa_query);
+
+int mcast_init(void);
+void mcast_cleanup(void);
+
+#endif /* SA_H */
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index e45afba7534..68db633711c 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -47,8 +47,8 @@
#include <linux/workqueue.h>
#include <rdma/ib_pack.h>
-#include <rdma/ib_sa.h>
#include <rdma/ib_cache.h>
+#include "sa.h"
MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("InfiniBand subnet administration query support");
@@ -425,17 +425,6 @@ void ib_sa_register_client(struct ib_sa_client *client)
}
EXPORT_SYMBOL(ib_sa_register_client);
-static inline void ib_sa_client_get(struct ib_sa_client *client)
-{
- atomic_inc(&client->users);
-}
-
-static inline void ib_sa_client_put(struct ib_sa_client *client)
-{
- if (atomic_dec_and_test(&client->users))
- complete(&client->comp);
-}
-
void ib_sa_unregister_client(struct ib_sa_client *client)
{
ib_sa_client_put(client);
@@ -482,6 +471,7 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
ah_attr->sl = rec->sl;
ah_attr->src_path_bits = be16_to_cpu(rec->slid) & 0x7f;
ah_attr->port_num = port_num;
+ ah_attr->static_rate = rec->rate;
if (rec->hop_limit > 1) {
ah_attr->ah_flags = IB_AH_GRH;
@@ -901,7 +891,6 @@ err1:
kfree(query);
return ret;
}
-EXPORT_SYMBOL(ib_sa_mcmember_rec_query);
static void send_handler(struct ib_mad_agent *agent,
struct ib_mad_send_wc *mad_send_wc)
@@ -1053,14 +1042,27 @@ static int __init ib_sa_init(void)
get_random_bytes(&tid, sizeof tid);
ret = ib_register_client(&sa_client);
- if (ret)
+ if (ret) {
printk(KERN_ERR "Couldn't register ib_sa client\n");
+ goto err1;
+ }
+
+ ret = mcast_init();
+ if (ret) {
+ printk(KERN_ERR "Couldn't initialize multicast handling\n");
+ goto err2;
+ }
+ return 0;
+err2:
+ ib_unregister_client(&sa_client);
+err1:
return ret;
}
static void __exit ib_sa_cleanup(void)
{
+ mcast_cleanup();
ib_unregister_client(&sa_client);
idr_destroy(&query_idr);
}
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 709323c14c5..000c086bf2e 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -714,8 +714,6 @@ int ib_device_register_sysfs(struct ib_device *device)
if (ret)
goto err_put;
} else {
- int i;
-
for (i = 1; i <= device->phys_port_cnt; ++i) {
ret = add_port(device, i);
if (ret)
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 6b81b98961c..b516b93b855 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -70,10 +70,24 @@ struct ucma_context {
u64 uid;
struct list_head list;
+ struct list_head mc_list;
+};
+
+struct ucma_multicast {
+ struct ucma_context *ctx;
+ int id;
+ int events_reported;
+
+ u64 uid;
+ struct list_head list;
+ struct sockaddr addr;
+ u8 pad[sizeof(struct sockaddr_in6) -
+ sizeof(struct sockaddr)];
};
struct ucma_event {
struct ucma_context *ctx;
+ struct ucma_multicast *mc;
struct list_head list;
struct rdma_cm_id *cm_id;
struct rdma_ucm_event_resp resp;
@@ -81,6 +95,7 @@ struct ucma_event {
static DEFINE_MUTEX(mut);
static DEFINE_IDR(ctx_idr);
+static DEFINE_IDR(multicast_idr);
static inline struct ucma_context *_ucma_find_context(int id,
struct ucma_file *file)
@@ -124,6 +139,7 @@ static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file)
atomic_set(&ctx->ref, 1);
init_completion(&ctx->comp);
+ INIT_LIST_HEAD(&ctx->mc_list);
ctx->file = file;
do {
@@ -147,6 +163,37 @@ error:
return NULL;
}
+static struct ucma_multicast* ucma_alloc_multicast(struct ucma_context *ctx)
+{
+ struct ucma_multicast *mc;
+ int ret;
+
+ mc = kzalloc(sizeof(*mc), GFP_KERNEL);
+ if (!mc)
+ return NULL;
+
+ do {
+ ret = idr_pre_get(&multicast_idr, GFP_KERNEL);
+ if (!ret)
+ goto error;
+
+ mutex_lock(&mut);
+ ret = idr_get_new(&multicast_idr, mc, &mc->id);
+ mutex_unlock(&mut);
+ } while (ret == -EAGAIN);
+
+ if (ret)
+ goto error;
+
+ mc->ctx = ctx;
+ list_add_tail(&mc->list, &ctx->mc_list);
+ return mc;
+
+error:
+ kfree(mc);
+ return NULL;
+}
+
static void ucma_copy_conn_event(struct rdma_ucm_conn_param *dst,
struct rdma_conn_param *src)
{
@@ -180,8 +227,19 @@ static void ucma_set_event_context(struct ucma_context *ctx,
struct ucma_event *uevent)
{
uevent->ctx = ctx;
- uevent->resp.uid = ctx->uid;
- uevent->resp.id = ctx->id;
+ switch (event->event) {
+ case RDMA_CM_EVENT_MULTICAST_JOIN:
+ case RDMA_CM_EVENT_MULTICAST_ERROR:
+ uevent->mc = (struct ucma_multicast *)
+ event->param.ud.private_data;
+ uevent->resp.uid = uevent->mc->uid;
+ uevent->resp.id = uevent->mc->id;
+ break;
+ default:
+ uevent->resp.uid = ctx->uid;
+ uevent->resp.id = ctx->id;
+ break;
+ }
}
static int ucma_event_handler(struct rdma_cm_id *cm_id,
@@ -199,7 +257,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,
ucma_set_event_context(ctx, event, uevent);
uevent->resp.event = event->event;
uevent->resp.status = event->status;
- if (cm_id->ps == RDMA_PS_UDP)
+ if (cm_id->ps == RDMA_PS_UDP || cm_id->ps == RDMA_PS_IPOIB)
ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
else
ucma_copy_conn_event(&uevent->resp.param.conn,
@@ -290,6 +348,8 @@ static ssize_t ucma_get_event(struct ucma_file *file, const char __user *inbuf,
list_del(&uevent->list);
uevent->ctx->events_reported++;
+ if (uevent->mc)
+ uevent->mc->events_reported++;
kfree(uevent);
done:
mutex_unlock(&file->mut);
@@ -342,6 +402,19 @@ err1:
return ret;
}
+static void ucma_cleanup_multicast(struct ucma_context *ctx)
+{
+ struct ucma_multicast *mc, *tmp;
+
+ mutex_lock(&mut);
+ list_for_each_entry_safe(mc, tmp, &ctx->mc_list, list) {
+ list_del(&mc->list);
+ idr_remove(&multicast_idr, mc->id);
+ kfree(mc);
+ }
+ mutex_unlock(&mut);
+}
+
static void ucma_cleanup_events(struct ucma_context *ctx)
{
struct ucma_event *uevent, *tmp;
@@ -360,6 +433,19 @@ static void ucma_cleanup_events(struct ucma_context *ctx)
}
}
+static void ucma_cleanup_mc_events(struct ucma_multicast *mc)
+{
+ struct ucma_event *uevent, *tmp;
+
+ list_for_each_entry_safe(uevent, tmp, &mc->ctx->file->event_list, list) {
+ if (uevent->mc != mc)
+ continue;
+
+ list_del(&uevent->list);
+ kfree(uevent);
+ }
+}
+
static int ucma_free_ctx(struct ucma_context *ctx)
{
int events_reported;
@@ -367,6 +453,8 @@ static int ucma_free_ctx(struct ucma_context *ctx)
/* No new events will be generated after destroying the id. */
rdma_destroy_id(ctx->cm_id);
+ ucma_cleanup_multicast(ctx);
+
/* Cleanup events not yet reported to the user. */
mutex_lock(&ctx->file->mut);
ucma_cleanup_events(ctx);
@@ -731,6 +819,114 @@ static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf,
return ret;
}
+static ssize_t ucma_join_multicast(struct ucma_file *file,
+ const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_join_mcast cmd;
+ struct rdma_ucm_create_id_resp resp;
+ struct ucma_context *ctx;
+ struct ucma_multicast *mc;
+ int ret;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ ctx = ucma_get_ctx(file, cmd.id);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ mutex_lock(&file->mut);
+ mc = ucma_alloc_multicast(ctx);
+ if (IS_ERR(mc)) {
+ ret = PTR_ERR(mc);
+ goto err1;
+ }
+
+ mc->uid = cmd.uid;
+ memcpy(&mc->addr, &cmd.addr, sizeof cmd.addr);
+ ret = rdma_join_multicast(ctx->cm_id, &mc->addr, mc);
+ if (ret)
+ goto err2;
+
+ resp.id = mc->id;
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &resp, sizeof(resp))) {
+ ret = -EFAULT;
+ goto err3;
+ }
+
+ mutex_unlock(&file->mut);
+ ucma_put_ctx(ctx);
+ return 0;
+
+err3:
+ rdma_leave_multicast(ctx->cm_id, &mc->addr);
+ ucma_cleanup_mc_events(mc);
+err2:
+ mutex_lock(&mut);
+ idr_remove(&multicast_idr, mc->id);
+ mutex_unlock(&mut);
+ list_del(&mc->list);
+ kfree(mc);
+err1:
+ mutex_unlock(&file->mut);
+ ucma_put_ctx(ctx);
+ return ret;
+}
+
+static ssize_t ucma_leave_multicast(struct ucma_file *file,
+ const char __user *inbuf,
+ int in_len, int out_len)
+{
+ struct rdma_ucm_destroy_id cmd;
+ struct rdma_ucm_destroy_id_resp resp;
+ struct ucma_multicast *mc;
+ int ret = 0;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+ return -EFAULT;
+
+ mutex_lock(&mut);
+ mc = idr_find(&multicast_idr, cmd.id);
+ if (!mc)
+ mc = ERR_PTR(-ENOENT);
+ else if (mc->ctx->file != file)
+ mc = ERR_PTR(-EINVAL);
+ else {
+ idr_remove(&multicast_idr, mc->id);
+ atomic_inc(&mc->ctx->ref);
+ }
+ mutex_unlock(&mut);
+
+ if (IS_ERR(mc)) {
+ ret = PTR_ERR(mc);
+ goto out;
+ }
+
+ rdma_leave_multicast(mc->ctx->cm_id, &mc->addr);
+ mutex_lock(&mc->ctx->file->mut);
+ ucma_cleanup_mc_events(mc);
+ list_del(&mc->list);
+ mutex_unlock(&mc->ctx->file->mut);
+
+ ucma_put_ctx(mc->ctx);
+ resp.events_reported = mc->events_reported;
+ kfree(mc);
+
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &resp, sizeof(resp)))
+ ret = -EFAULT;
+out:
+ return ret;
+}
+
static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
const char __user *inbuf,
int in_len, int out_len) = {
@@ -750,6 +946,8 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
[RDMA_USER_CM_CMD_GET_OPTION] = NULL,
[RDMA_USER_CM_CMD_SET_OPTION] = NULL,
[RDMA_USER_CM_CMD_NOTIFY] = ucma_notify,
+ [RDMA_USER_CM_CMD_JOIN_MCAST] = ucma_join_multicast,
+ [RDMA_USER_CM_CMD_LEAVE_MCAST] = ucma_leave_multicast,
};
static ssize_t ucma_write(struct file *filp, const char __user *buf,
diff --git a/drivers/infiniband/hw/cxgb3/cxio_dbg.c b/drivers/infiniband/hw/cxgb3/cxio_dbg.c
index 5a7306f5efa..75f7b16a271 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_dbg.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_dbg.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
index 82fa7204198..114ac3b775d 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h
index 1b97e80b878..8ab04a7c6f6 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.h
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c
index 997aa32cbf0..65bf577311a 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_resource.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.h b/drivers/infiniband/hw/cxgb3/cxio_resource.h
index a6bbe8370d8..a2703a3d882 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_resource.h
+++ b/drivers/infiniband/hw/cxgb3/cxio_resource.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/cxio_wr.h b/drivers/infiniband/hw/cxgb3/cxio_wr.h
index 103fc42d697..90d7b8972cb 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_wr.h
+++ b/drivers/infiniband/hw/cxgb3/cxio_wr.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c
index 4611afa5222..0315c9d9fce 100644
--- a/drivers/infiniband/hw/cxgb3/iwch.c
+++ b/drivers/infiniband/hw/cxgb3/iwch.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/iwch.h b/drivers/infiniband/hw/cxgb3/iwch.h
index 6517ef85026..caf4e6007a4 100644
--- a/drivers/infiniband/hw/cxgb3/iwch.h
+++ b/drivers/infiniband/hw/cxgb3/iwch.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index a522b1baa3b..e5442e34b78 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h
index 7c810d90427..0c6f281bd4a 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cq.c b/drivers/infiniband/hw/cxgb3/iwch_cq.c
index 98b3bdb5de9..d7624c170ee 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cq.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cq.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/iwch_ev.c b/drivers/infiniband/hw/cxgb3/iwch_ev.c
index a6efa8fe15d..54362afbf72 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_ev.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_ev.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/iwch_mem.c b/drivers/infiniband/hw/cxgb3/iwch_mem.c
index 2b6cd53bb3f..a6c2c4ba29e 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_mem.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_mem.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index 6861087d776..2aef122f995 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h
index 61e3278fd7a..2af3e93b607 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index e066727504b..4dda2f6da2d 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -846,6 +845,8 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
break;
case IWCH_QP_STATE_TERMINATE:
qhp->attr.state = IWCH_QP_STATE_TERMINATE;
+ if (t3b_device(qhp->rhp))
+ cxio_set_wq_in_error(&qhp->wq);
if (!internal)
terminate = 1;
break;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_user.h b/drivers/infiniband/hw/cxgb3/iwch_user.h
index c4e7fbea8bb..cb7086f558c 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_user.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_user.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/ehca/Kconfig b/drivers/infiniband/hw/ehca/Kconfig
index 727b10d8968..1a854598e0e 100644
--- a/drivers/infiniband/hw/ehca/Kconfig
+++ b/drivers/infiniband/hw/ehca/Kconfig
@@ -7,11 +7,3 @@ config INFINIBAND_EHCA
To compile the driver as a module, choose M here. The module
will be called ib_ehca.
-config INFINIBAND_EHCA_SCALING
- bool "Scaling support (EXPERIMENTAL)"
- depends on IBMEBUS && INFINIBAND_EHCA && HOTPLUG_CPU && EXPERIMENTAL
- default y
- ---help---
- eHCA scaling support schedules the CQ callbacks to different CPUs.
-
- To enable this feature choose Y here.
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index cf95ee474b0..40404c9e281 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -42,8 +42,6 @@
#ifndef __EHCA_CLASSES_H__
#define __EHCA_CLASSES_H__
-#include "ehca_classes.h"
-#include "ipz_pt_fn.h"
struct ehca_module;
struct ehca_qp;
@@ -54,14 +52,22 @@ struct ehca_mw;
struct ehca_pd;
struct ehca_av;
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
+
#ifdef CONFIG_PPC64
#include "ehca_classes_pSeries.h"
#endif
+#include "ipz_pt_fn.h"
+#include "ehca_qes.h"
+#include "ehca_irq.h"
-#include <rdma/ib_verbs.h>
-#include <rdma/ib_user_verbs.h>
+#define EHCA_EQE_CACHE_SIZE 20
-#include "ehca_irq.h"
+struct ehca_eqe_cache_entry {
+ struct ehca_eqe *eqe;
+ struct ehca_cq *cq;
+};
struct ehca_eq {
u32 length;
@@ -74,6 +80,8 @@ struct ehca_eq {
spinlock_t spinlock;
struct tasklet_struct interrupt_task;
u32 ist;
+ spinlock_t irq_spinlock;
+ struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE];
};
struct ehca_sport {
@@ -269,6 +277,7 @@ extern struct idr ehca_cq_idr;
extern int ehca_static_rate;
extern int ehca_port_act_time;
extern int ehca_use_hp_mr;
+extern int ehca_scaling_code;
struct ipzu_queue_resp {
u32 qe_size; /* queue entry size */
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index 24ceab0bae4..4961eb88827 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -61,6 +61,7 @@ int ehca_create_eq(struct ehca_shca *shca,
struct ib_device *ib_dev = &shca->ib_device;
spin_lock_init(&eq->spinlock);
+ spin_lock_init(&eq->irq_spinlock);
eq->is_initialized = 0;
if (type != EHCA_EQ && type != EHCA_NEQ) {
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index b7be950ab47..30eb45df9f0 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -162,6 +162,9 @@ int ehca_query_port(struct ib_device *ibdev,
props->active_width = IB_WIDTH_12X;
props->active_speed = 0x1;
+ /* at the moment (logical) link state is always LINK_UP */
+ props->phys_state = 0x5;
+
query_port1:
ehca_free_fw_ctrlblock(rblock);
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 6c4f9f91b15..3ec53c687d0 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -63,15 +63,11 @@
#define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52,63)
#define ERROR_DATA_TYPE EHCA_BMASK_IBM(0,7)
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
-
static void queue_comp_task(struct ehca_cq *__cq);
static struct ehca_comp_pool* pool;
static struct notifier_block comp_pool_callback_nb;
-#endif
-
static inline void comp_event_callback(struct ehca_cq *cq)
{
if (!cq->ib_cq.comp_handler)
@@ -206,7 +202,7 @@ static void qp_event_callback(struct ehca_shca *shca,
}
static void cq_event_callback(struct ehca_shca *shca,
- u64 eqe)
+ u64 eqe)
{
struct ehca_cq *cq;
unsigned long flags;
@@ -318,7 +314,7 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
"disruptive port %x configuration change", port);
ehca_info(&shca->ib_device,
- "port %x is inactive.", port);
+ "port %x is inactive.", port);
event.device = &shca->ib_device;
event.event = IB_EVENT_PORT_ERR;
event.element.port_num = port;
@@ -326,7 +322,7 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
ib_dispatch_event(&event);
ehca_info(&shca->ib_device,
- "port %x is active.", port);
+ "port %x is active.", port);
event.device = &shca->ib_device;
event.event = IB_EVENT_PORT_ACTIVE;
event.element.port_num = port;
@@ -401,115 +397,170 @@ irqreturn_t ehca_interrupt_eq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-void ehca_tasklet_eq(unsigned long data)
-{
- struct ehca_shca *shca = (struct ehca_shca*)data;
- struct ehca_eqe *eqe;
- int int_state;
- int query_cnt = 0;
- do {
- eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
+static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
+{
+ u64 eqe_value;
+ u32 token;
+ unsigned long flags;
+ struct ehca_cq *cq;
+ eqe_value = eqe->entry;
+ ehca_dbg(&shca->ib_device, "eqe_value=%lx", eqe_value);
+ if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
+ ehca_dbg(&shca->ib_device, "... completion event");
+ token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
+ spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ cq = idr_find(&ehca_cq_idr, token);
+ if (cq == NULL) {
+ spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ ehca_err(&shca->ib_device,
+ "Invalid eqe for non-existing cq token=%x",
+ token);
+ return;
+ }
+ reset_eq_pending(cq);
+ if (ehca_scaling_code) {
+ queue_comp_task(cq);
+ spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ } else {
+ spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ comp_event_callback(cq);
+ }
+ } else {
+ ehca_dbg(&shca->ib_device,
+ "Got non completion event");
+ parse_identifier(shca, eqe_value);
+ }
+}
- if ((shca->hw_level >= 2) && eqe)
- int_state = 1;
- else
- int_state = 0;
-
- while ((int_state == 1) || eqe) {
- while (eqe) {
- u64 eqe_value = eqe->entry;
-
- ehca_dbg(&shca->ib_device,
- "eqe_value=%lx", eqe_value);
-
- /* TODO: better structure */
- if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT,
- eqe_value)) {
- unsigned long flags;
- u32 token;
- struct ehca_cq *cq;
-
- ehca_dbg(&shca->ib_device,
- "... completion event");
- token =
- EHCA_BMASK_GET(EQE_CQ_TOKEN,
- eqe_value);
- spin_lock_irqsave(&ehca_cq_idr_lock,
- flags);
- cq = idr_find(&ehca_cq_idr, token);
-
- if (cq == NULL) {
- spin_unlock_irqrestore(&ehca_cq_idr_lock,
- flags);
- break;
- }
-
- reset_eq_pending(cq);
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
- queue_comp_task(cq);
- spin_unlock_irqrestore(&ehca_cq_idr_lock,
- flags);
-#else
- spin_unlock_irqrestore(&ehca_cq_idr_lock,
- flags);
- comp_event_callback(cq);
-#endif
- } else {
- ehca_dbg(&shca->ib_device,
- "... non completion event");
- parse_identifier(shca, eqe_value);
- }
- eqe =
- (struct ehca_eqe *)ehca_poll_eq(shca,
- &shca->eq);
- }
+void ehca_process_eq(struct ehca_shca *shca, int is_irq)
+{
+ struct ehca_eq *eq = &shca->eq;
+ struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache;
+ u64 eqe_value;
+ unsigned long flags;
+ int eqe_cnt, i;
+ int eq_empty = 0;
+
+ spin_lock_irqsave(&eq->irq_spinlock, flags);
+ if (is_irq) {
+ const int max_query_cnt = 100;
+ int query_cnt = 0;
+ int int_state = 1;
+ do {
+ int_state = hipz_h_query_int_state(
+ shca->ipz_hca_handle, eq->ist);
+ query_cnt++;
+ iosync();
+ } while (int_state && query_cnt < max_query_cnt);
+ if (unlikely((query_cnt == max_query_cnt)))
+ ehca_dbg(&shca->ib_device, "int_state=%x query_cnt=%x",
+ int_state, query_cnt);
+ }
- if (shca->hw_level >= 2) {
- int_state =
- hipz_h_query_int_state(shca->ipz_hca_handle,
- shca->eq.ist);
- query_cnt++;
- iosync();
- if (query_cnt >= 100) {
- query_cnt = 0;
- int_state = 0;
- }
+ /* read out all eqes */
+ eqe_cnt = 0;
+ do {
+ u32 token;
+ eqe_cache[eqe_cnt].eqe =
+ (struct ehca_eqe *)ehca_poll_eq(shca, eq);
+ if (!eqe_cache[eqe_cnt].eqe)
+ break;
+ eqe_value = eqe_cache[eqe_cnt].eqe->entry;
+ if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
+ token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
+ spin_lock(&ehca_cq_idr_lock);
+ eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token);
+ if (!eqe_cache[eqe_cnt].cq) {
+ spin_unlock(&ehca_cq_idr_lock);
+ ehca_err(&shca->ib_device,
+ "Invalid eqe for non-existing cq "
+ "token=%x", token);
+ continue;
}
- eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
-
+ spin_unlock(&ehca_cq_idr_lock);
+ } else
+ eqe_cache[eqe_cnt].cq = NULL;
+ eqe_cnt++;
+ } while (eqe_cnt < EHCA_EQE_CACHE_SIZE);
+ if (!eqe_cnt) {
+ if (is_irq)
+ ehca_dbg(&shca->ib_device,
+ "No eqe found for irq event");
+ goto unlock_irq_spinlock;
+ } else if (!is_irq)
+ ehca_dbg(&shca->ib_device, "deadman found %x eqe", eqe_cnt);
+ if (unlikely(eqe_cnt == EHCA_EQE_CACHE_SIZE))
+ ehca_dbg(&shca->ib_device, "too many eqes for one irq event");
+ /* enable irq for new packets */
+ for (i = 0; i < eqe_cnt; i++) {
+ if (eq->eqe_cache[i].cq)
+ reset_eq_pending(eq->eqe_cache[i].cq);
+ }
+ /* check eq */
+ spin_lock(&eq->spinlock);
+ eq_empty = (!ipz_eqit_eq_peek_valid(&shca->eq.ipz_queue));
+ spin_unlock(&eq->spinlock);
+ /* call completion handler for cached eqes */
+ for (i = 0; i < eqe_cnt; i++)
+ if (eq->eqe_cache[i].cq) {
+ if (ehca_scaling_code) {
+ spin_lock(&ehca_cq_idr_lock);
+ queue_comp_task(eq->eqe_cache[i].cq);
+ spin_unlock(&ehca_cq_idr_lock);
+ } else
+ comp_event_callback(eq->eqe_cache[i].cq);
+ } else {
+ ehca_dbg(&shca->ib_device, "Got non completion event");
+ parse_identifier(shca, eq->eqe_cache[i].eqe->entry);
}
- } while (int_state != 0);
-
- return;
+ /* poll eq if not empty */
+ if (eq_empty)
+ goto unlock_irq_spinlock;
+ do {
+ struct ehca_eqe *eqe;
+ eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq);
+ if (!eqe)
+ break;
+ process_eqe(shca, eqe);
+ eqe_cnt++;
+ } while (1);
+
+unlock_irq_spinlock:
+ spin_unlock_irqrestore(&eq->irq_spinlock, flags);
}
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
+void ehca_tasklet_eq(unsigned long data)
+{
+ ehca_process_eq((struct ehca_shca*)data, 1);
+}
static inline int find_next_online_cpu(struct ehca_comp_pool* pool)
{
- unsigned long flags_last_cpu;
+ int cpu;
+ unsigned long flags;
+ WARN_ON_ONCE(!in_interrupt());
if (ehca_debug_level)
ehca_dmp(&cpu_online_map, sizeof(cpumask_t), "");
- spin_lock_irqsave(&pool->last_cpu_lock, flags_last_cpu);
- pool->last_cpu = next_cpu(pool->last_cpu, cpu_online_map);
- if (pool->last_cpu == NR_CPUS)
- pool->last_cpu = first_cpu(cpu_online_map);
- spin_unlock_irqrestore(&pool->last_cpu_lock, flags_last_cpu);
+ spin_lock_irqsave(&pool->last_cpu_lock, flags);
+ cpu = next_cpu(pool->last_cpu, cpu_online_map);
+ if (cpu == NR_CPUS)
+ cpu = first_cpu(cpu_online_map);
+ pool->last_cpu = cpu;
+ spin_unlock_irqrestore(&pool->last_cpu_lock, flags);
- return pool->last_cpu;
+ return cpu;
}
static void __queue_comp_task(struct ehca_cq *__cq,
struct ehca_cpu_comp_task *cct)
{
- unsigned long flags_cct;
- unsigned long flags_cq;
+ unsigned long flags;
- spin_lock_irqsave(&cct->task_lock, flags_cct);
- spin_lock_irqsave(&__cq->task_lock, flags_cq);
+ spin_lock_irqsave(&cct->task_lock, flags);
+ spin_lock(&__cq->task_lock);
if (__cq->nr_callbacks == 0) {
__cq->nr_callbacks++;
@@ -520,8 +571,8 @@ static void __queue_comp_task(struct ehca_cq *__cq,
else
__cq->nr_callbacks++;
- spin_unlock_irqrestore(&__cq->task_lock, flags_cq);
- spin_unlock_irqrestore(&cct->task_lock, flags_cct);
+ spin_unlock(&__cq->task_lock);
+ spin_unlock_irqrestore(&cct->task_lock, flags);
}
static void queue_comp_task(struct ehca_cq *__cq)
@@ -532,69 +583,69 @@ static void queue_comp_task(struct ehca_cq *__cq)
cpu = get_cpu();
cpu_id = find_next_online_cpu(pool);
-
BUG_ON(!cpu_online(cpu_id));
cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
+ BUG_ON(!cct);
if (cct->cq_jobs > 0) {
cpu_id = find_next_online_cpu(pool);
cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
+ BUG_ON(!cct);
}
__queue_comp_task(__cq, cct);
-
- put_cpu();
-
- return;
}
static void run_comp_task(struct ehca_cpu_comp_task* cct)
{
struct ehca_cq *cq;
- unsigned long flags_cct;
- unsigned long flags_cq;
+ unsigned long flags;
- spin_lock_irqsave(&cct->task_lock, flags_cct);
+ spin_lock_irqsave(&cct->task_lock, flags);
while (!list_empty(&cct->cq_list)) {
cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
- spin_unlock_irqrestore(&cct->task_lock, flags_cct);
+ spin_unlock_irqrestore(&cct->task_lock, flags);
comp_event_callback(cq);
- spin_lock_irqsave(&cct->task_lock, flags_cct);
+ spin_lock_irqsave(&cct->task_lock, flags);
- spin_lock_irqsave(&cq->task_lock, flags_cq);
+ spin_lock(&cq->task_lock);
cq->nr_callbacks--;
if (cq->nr_callbacks == 0) {
list_del_init(cct->cq_list.next);
cct->cq_jobs--;
}
- spin_unlock_irqrestore(&cq->task_lock, flags_cq);
-
+ spin_unlock(&cq->task_lock);
}
- spin_unlock_irqrestore(&cct->task_lock, flags_cct);
-
- return;
+ spin_unlock_irqrestore(&cct->task_lock, flags);
}
static int comp_task(void *__cct)
{
struct ehca_cpu_comp_task* cct = __cct;
+ int cql_empty;
DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_INTERRUPTIBLE);
while(!kthread_should_stop()) {
add_wait_queue(&cct->wait_queue, &wait);
- if (list_empty(&cct->cq_list))
+ spin_lock_irq(&cct->task_lock);
+ cql_empty = list_empty(&cct->cq_list);
+ spin_unlock_irq(&cct->task_lock);
+ if (cql_empty)
schedule();
else
__set_current_state(TASK_RUNNING);
remove_wait_queue(&cct->wait_queue, &wait);
- if (!list_empty(&cct->cq_list))
+ spin_lock_irq(&cct->task_lock);
+ cql_empty = list_empty(&cct->cq_list);
+ spin_unlock_irq(&cct->task_lock);
+ if (!cql_empty)
run_comp_task(__cct);
set_current_state(TASK_INTERRUPTIBLE);
@@ -637,8 +688,6 @@ static void destroy_comp_task(struct ehca_comp_pool *pool,
if (task)
kthread_stop(task);
-
- return;
}
static void take_over_work(struct ehca_comp_pool *pool,
@@ -654,11 +703,11 @@ static void take_over_work(struct ehca_comp_pool *pool,
list_splice_init(&cct->cq_list, &list);
while(!list_empty(&list)) {
- cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
+ cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
- list_del(&cq->entry);
- __queue_comp_task(cq, per_cpu_ptr(pool->cpu_comp_tasks,
- smp_processor_id()));
+ list_del(&cq->entry);
+ __queue_comp_task(cq, per_cpu_ptr(pool->cpu_comp_tasks,
+ smp_processor_id()));
}
spin_unlock_irqrestore(&cct->task_lock, flags_cct);
@@ -708,14 +757,14 @@ static int comp_pool_callback(struct notifier_block *nfb,
return NOTIFY_OK;
}
-#endif
-
int ehca_create_comp_pool(void)
{
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
int cpu;
struct task_struct *task;
+ if (!ehca_scaling_code)
+ return 0;
+
pool = kzalloc(sizeof(struct ehca_comp_pool), GFP_KERNEL);
if (pool == NULL)
return -ENOMEM;
@@ -740,16 +789,19 @@ int ehca_create_comp_pool(void)
comp_pool_callback_nb.notifier_call = comp_pool_callback;
comp_pool_callback_nb.priority =0;
register_cpu_notifier(&comp_pool_callback_nb);
-#endif
+
+ printk(KERN_INFO "eHCA scaling code enabled\n");
return 0;
}
void ehca_destroy_comp_pool(void)
{
-#ifdef CONFIG_INFINIBAND_EHCA_SCALING
int i;
+ if (!ehca_scaling_code)
+ return;
+
unregister_cpu_notifier(&comp_pool_callback_nb);
for (i = 0; i < NR_CPUS; i++) {
@@ -758,7 +810,4 @@ void ehca_destroy_comp_pool(void)
}
free_percpu(pool->cpu_comp_tasks);
kfree(pool);
-#endif
-
- return;
}
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.h b/drivers/infiniband/hw/ehca/ehca_irq.h
index be579cc0adf..6ed06ee033e 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.h
+++ b/drivers/infiniband/hw/ehca/ehca_irq.h
@@ -56,6 +56,7 @@ void ehca_tasklet_neq(unsigned long data);
irqreturn_t ehca_interrupt_eq(int irq, void *dev_id);
void ehca_tasklet_eq(unsigned long data);
+void ehca_process_eq(struct ehca_shca *shca, int is_irq);
struct ehca_cpu_comp_task {
wait_queue_head_t wait_queue;
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 1155bcf4821..c1835121a82 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -52,7 +52,7 @@
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0020");
+MODULE_VERSION("SVNEHCA_0021");
int ehca_open_aqp1 = 0;
int ehca_debug_level = 0;
@@ -62,6 +62,7 @@ int ehca_use_hp_mr = 0;
int ehca_port_act_time = 30;
int ehca_poll_all_eqs = 1;
int ehca_static_rate = -1;
+int ehca_scaling_code = 1;
module_param_named(open_aqp1, ehca_open_aqp1, int, 0);
module_param_named(debug_level, ehca_debug_level, int, 0);
@@ -71,6 +72,7 @@ module_param_named(use_hp_mr, ehca_use_hp_mr, int, 0);
module_param_named(port_act_time, ehca_port_act_time, int, 0);
module_param_named(poll_all_eqs, ehca_poll_all_eqs, int, 0);
module_param_named(static_rate, ehca_static_rate, int, 0);
+module_param_named(scaling_code, ehca_scaling_code, int, 0);
MODULE_PARM_DESC(open_aqp1,
"AQP1 on startup (0: no (default), 1: yes)");
@@ -91,6 +93,8 @@ MODULE_PARM_DESC(poll_all_eqs,
" (0: no, 1: yes (default))");
MODULE_PARM_DESC(static_rate,
"set permanent static rate (default: disabled)");
+MODULE_PARM_DESC(scaling_code,
+ "set scaling code (0: disabled, 1: enabled/default)");
spinlock_t ehca_qp_idr_lock;
spinlock_t ehca_cq_idr_lock;
@@ -432,8 +436,8 @@ static int ehca_destroy_aqp1(struct ehca_sport *sport)
static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n",
- ehca_debug_level);
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ ehca_debug_level);
}
static ssize_t ehca_store_debug_level(struct device_driver *ddp,
@@ -778,8 +782,24 @@ void ehca_poll_eqs(unsigned long data)
spin_lock(&shca_list_lock);
list_for_each_entry(shca, &shca_list, shca_list) {
- if (shca->eq.is_initialized)
- ehca_tasklet_eq((unsigned long)(void*)shca);
+ if (shca->eq.is_initialized) {
+ /* call deadman proc only if eq ptr does not change */
+ struct ehca_eq *eq = &shca->eq;
+ int max = 3;
+ volatile u64 q_ofs, q_ofs2;
+ u64 flags;
+ spin_lock_irqsave(&eq->spinlock, flags);
+ q_ofs = eq->ipz_queue.current_q_offset;
+ spin_unlock_irqrestore(&eq->spinlock, flags);
+ do {
+ spin_lock_irqsave(&eq->spinlock, flags);
+ q_ofs2 = eq->ipz_queue.current_q_offset;
+ spin_unlock_irqrestore(&eq->spinlock, flags);
+ max--;
+ } while (q_ofs == q_ofs2 && max > 0);
+ if (q_ofs == q_ofs2)
+ ehca_process_eq(shca, 0);
+ }
}
mod_timer(&poll_eqs_timer, jiffies + HZ);
spin_unlock(&shca_list_lock);
@@ -790,7 +810,7 @@ int __init ehca_module_init(void)
int ret;
printk(KERN_INFO "eHCA Infiniband Device Driver "
- "(Rel.: SVNEHCA_0020)\n");
+ "(Rel.: SVNEHCA_0021)\n");
idr_init(&ehca_qp_idr);
idr_init(&ehca_cq_idr);
spin_lock_init(&ehca_qp_idr_lock);
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.h b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
index dc3bda2634b..8199c45768a 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.h
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
@@ -79,7 +79,7 @@ static inline void *ipz_qeit_calc(struct ipz_queue *queue, u64 q_offset)
if (q_offset >= queue->queue_length)
return NULL;
current_page = (queue->queue_pages)[q_offset >> EHCA_PAGESHIFT];
- return &current_page->entries[q_offset & (EHCA_PAGESIZE - 1)];
+ return &current_page->entries[q_offset & (EHCA_PAGESIZE - 1)];
}
/*
@@ -247,6 +247,15 @@ static inline void *ipz_eqit_eq_get_inc_valid(struct ipz_queue *queue)
return ret;
}
+static inline void *ipz_eqit_eq_peek_valid(struct ipz_queue *queue)
+{
+ void *ret = ipz_qeit_get(queue);
+ u32 qe = *(u8 *) ret;
+ if ((qe >> 7) != (queue->toggle_state & 1))
+ return NULL;
+ return ret;
+}
+
/* returns address (GX) of first queue entry */
static inline u64 ipz_qpt_get_firstpage(struct ipz_qpt *qpt)
{
diff --git a/drivers/infiniband/hw/ipath/ipath_dma.c b/drivers/infiniband/hw/ipath/ipath_dma.c
index 6e0f2b8918c..f6f94904082 100644
--- a/drivers/infiniband/hw/ipath/ipath_dma.c
+++ b/drivers/infiniband/hw/ipath/ipath_dma.c
@@ -96,8 +96,8 @@ static void ipath_dma_unmap_page(struct ib_device *dev,
BUG_ON(!valid_dma_direction(direction));
}
-int ipath_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction direction)
+static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
{
u64 addr;
int i;
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 0b9d053a599..48f7c65e9ae 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -175,7 +175,9 @@ struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
if (!ret) {
++chunk->npages;
- if (!coherent && chunk->npages == MTHCA_ICM_CHUNK_LEN) {
+ if (coherent)
+ ++chunk->nsg;
+ else if (chunk->npages == MTHCA_ICM_CHUNK_LEN) {
chunk->nsg = pci_map_sg(dev->pdev, chunk->mem,
chunk->npages,
PCI_DMA_BIDIRECTIONAL);
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 224c93dd29e..71dc84bd425 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -573,6 +573,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
goto out;
}
+ if (cur_state == new_state && cur_state == IB_QPS_RESET) {
+ err = 0;
+ goto out;
+ }
+
if ((attr_mask & IB_QP_PKEY_INDEX) &&
attr->pkey_index >= dev->limits.pkey_table_len) {
mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n",
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 2d483874a58..4d59682f7d4 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -145,7 +145,7 @@ partial_error:
for (; i >= 0; --i)
ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
- kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return -ENOMEM;
}
@@ -1138,7 +1138,7 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
return -EINVAL;
}
-static DEVICE_ATTR(mode, S_IWUGO | S_IRUGO, show_mode, set_mode);
+static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode);
int ipoib_cm_add_mode_attr(struct net_device *dev)
{
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index fea737f520f..b303ce6bc21 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -60,14 +60,11 @@ static DEFINE_MUTEX(mcast_mutex);
/* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
struct ipoib_mcast {
struct ib_sa_mcmember_rec mcmember;
+ struct ib_sa_multicast *mc;
struct ipoib_ah *ah;
struct rb_node rb_node;
struct list_head list;
- struct completion done;
-
- int query_id;
- struct ib_sa_query *query;
unsigned long created;
unsigned long backoff;
@@ -299,18 +296,22 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
return 0;
}
-static void
+static int
ipoib_mcast_sendonly_join_complete(int status,
- struct ib_sa_mcmember_rec *mcmember,
- void *mcast_ptr)
+ struct ib_sa_multicast *multicast)
{
- struct ipoib_mcast *mcast = mcast_ptr;
+ struct ipoib_mcast *mcast = multicast->context;
struct net_device *dev = mcast->dev;
struct ipoib_dev_priv *priv = netdev_priv(dev);
+ /* We trap for port events ourselves. */
+ if (status == -ENETRESET)
+ return 0;
+
if (!status)
- ipoib_mcast_join_finish(mcast, mcmember);
- else {
+ status = ipoib_mcast_join_finish(mcast, &multicast->rec);
+
+ if (status) {
if (mcast->logcount++ < 20)
ipoib_dbg_mcast(netdev_priv(dev), "multicast join failed for "
IPOIB_GID_FMT ", status %d\n",
@@ -325,11 +326,10 @@ ipoib_mcast_sendonly_join_complete(int status,
spin_unlock_irq(&priv->tx_lock);
/* Clear the busy flag so we try again */
- clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
- mcast->query = NULL;
+ status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY,
+ &mcast->flags);
}
-
- complete(&mcast->done);
+ return status;
}
static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
@@ -359,35 +359,33 @@ static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
rec.port_gid = priv->local_gid;
rec.pkey = cpu_to_be16(priv->pkey);
- init_completion(&mcast->done);
-
- ret = ib_sa_mcmember_rec_set(&ipoib_sa_client, priv->ca, priv->port, &rec,
- IB_SA_MCMEMBER_REC_MGID |
- IB_SA_MCMEMBER_REC_PORT_GID |
- IB_SA_MCMEMBER_REC_PKEY |
- IB_SA_MCMEMBER_REC_JOIN_STATE,
- 1000, GFP_ATOMIC,
- ipoib_mcast_sendonly_join_complete,
- mcast, &mcast->query);
- if (ret < 0) {
- ipoib_warn(priv, "ib_sa_mcmember_rec_set failed (ret = %d)\n",
+ mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca,
+ priv->port, &rec,
+ IB_SA_MCMEMBER_REC_MGID |
+ IB_SA_MCMEMBER_REC_PORT_GID |
+ IB_SA_MCMEMBER_REC_PKEY |
+ IB_SA_MCMEMBER_REC_JOIN_STATE,
+ GFP_ATOMIC,
+ ipoib_mcast_sendonly_join_complete,
+ mcast);
+ if (IS_ERR(mcast->mc)) {
+ ret = PTR_ERR(mcast->mc);
+ clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+ ipoib_warn(priv, "ib_sa_join_multicast failed (ret = %d)\n",
ret);
} else {
ipoib_dbg_mcast(priv, "no multicast record for " IPOIB_GID_FMT
", starting join\n",
IPOIB_GID_ARG(mcast->mcmember.mgid));
-
- mcast->query_id = ret;
}
return ret;
}
-static void ipoib_mcast_join_complete(int status,
- struct ib_sa_mcmember_rec *mcmember,
- void *mcast_ptr)
+static int ipoib_mcast_join_complete(int status,
+ struct ib_sa_multicast *multicast)
{
- struct ipoib_mcast *mcast = mcast_ptr;
+ struct ipoib_mcast *mcast = multicast->context;
struct net_device *dev = mcast->dev;
struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -395,24 +393,25 @@ static void ipoib_mcast_join_complete(int status,
" (status %d)\n",
IPOIB_GID_ARG(mcast->mcmember.mgid), status);
- if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) {
+ /* We trap for port events ourselves. */
+ if (status == -ENETRESET)
+ return 0;
+
+ if (!status)
+ status = ipoib_mcast_join_finish(mcast, &multicast->rec);
+
+ if (!status) {
mcast->backoff = 1;
mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_delayed_work(ipoib_workqueue,
&priv->mcast_task, 0);
mutex_unlock(&mcast_mutex);
- complete(&mcast->done);
- return;
- }
-
- if (status == -EINTR) {
- complete(&mcast->done);
- return;
+ return 0;
}
- if (status && mcast->logcount++ < 20) {
- if (status == -ETIMEDOUT || status == -EINTR) {
+ if (mcast->logcount++ < 20) {
+ if (status == -ETIMEDOUT) {
ipoib_dbg_mcast(priv, "multicast join failed for " IPOIB_GID_FMT
", status %d\n",
IPOIB_GID_ARG(mcast->mcmember.mgid),
@@ -429,24 +428,18 @@ static void ipoib_mcast_join_complete(int status,
if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
- mutex_lock(&mcast_mutex);
+ /* Clear the busy flag so we try again */
+ status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+ mutex_lock(&mcast_mutex);
spin_lock_irq(&priv->lock);
- mcast->query = NULL;
-
- if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) {
- if (status == -ETIMEDOUT)
- queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
- 0);
- else
- queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
- mcast->backoff * HZ);
- } else
- complete(&mcast->done);
+ if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
+ queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
+ mcast->backoff * HZ);
spin_unlock_irq(&priv->lock);
mutex_unlock(&mcast_mutex);
- return;
+ return status;
}
static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
@@ -495,15 +488,14 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
rec.hop_limit = priv->broadcast->mcmember.hop_limit;
}
- init_completion(&mcast->done);
-
- ret = ib_sa_mcmember_rec_set(&ipoib_sa_client, priv->ca, priv->port,
- &rec, comp_mask, mcast->backoff * 1000,
- GFP_ATOMIC, ipoib_mcast_join_complete,
- mcast, &mcast->query);
-
- if (ret < 0) {
- ipoib_warn(priv, "ib_sa_mcmember_rec_set failed, status %d\n", ret);
+ set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+ mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
+ &rec, comp_mask, GFP_KERNEL,
+ ipoib_mcast_join_complete, mcast);
+ if (IS_ERR(mcast->mc)) {
+ clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+ ret = PTR_ERR(mcast->mc);
+ ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
mcast->backoff *= 2;
if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
@@ -515,8 +507,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
&priv->mcast_task,
mcast->backoff * HZ);
mutex_unlock(&mcast_mutex);
- } else
- mcast->query_id = ret;
+ }
}
void ipoib_mcast_join_task(struct work_struct *work)
@@ -541,7 +532,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
priv->local_rate = attr.active_speed *
ib_width_enum_to_int(attr.active_width);
} else
- ipoib_warn(priv, "ib_query_port failed\n");
+ ipoib_warn(priv, "ib_query_port failed\n");
}
if (!priv->broadcast) {
@@ -568,7 +559,8 @@ void ipoib_mcast_join_task(struct work_struct *work)
}
if (!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
- ipoib_mcast_join(dev, priv->broadcast, 0);
+ if (!test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags))
+ ipoib_mcast_join(dev, priv->broadcast, 0);
return;
}
@@ -625,26 +617,9 @@ int ipoib_mcast_start_thread(struct net_device *dev)
return 0;
}
-static void wait_for_mcast_join(struct ipoib_dev_priv *priv,
- struct ipoib_mcast *mcast)
-{
- spin_lock_irq(&priv->lock);
- if (mcast && mcast->query) {
- ib_sa_cancel_query(mcast->query_id, mcast->query);
- mcast->query = NULL;
- spin_unlock_irq(&priv->lock);
- ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
- IPOIB_GID_ARG(mcast->mcmember.mgid));
- wait_for_completion(&mcast->done);
- }
- else
- spin_unlock_irq(&priv->lock);
-}
-
int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- struct ipoib_mcast *mcast;
ipoib_dbg_mcast(priv, "stopping multicast thread\n");
@@ -660,52 +635,27 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
if (flush)
flush_workqueue(ipoib_workqueue);
- wait_for_mcast_join(priv, priv->broadcast);
-
- list_for_each_entry(mcast, &priv->multicast_list, list)
- wait_for_mcast_join(priv, mcast);
-
return 0;
}
static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- struct ib_sa_mcmember_rec rec = {
- .join_state = 1
- };
int ret = 0;
- if (!test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags))
- return 0;
-
- ipoib_dbg_mcast(priv, "leaving MGID " IPOIB_GID_FMT "\n",
- IPOIB_GID_ARG(mcast->mcmember.mgid));
-
- rec.mgid = mcast->mcmember.mgid;
- rec.port_gid = priv->local_gid;
- rec.pkey = cpu_to_be16(priv->pkey);
+ if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
+ ipoib_dbg_mcast(priv, "leaving MGID " IPOIB_GID_FMT "\n",
+ IPOIB_GID_ARG(mcast->mcmember.mgid));
- /* Remove ourselves from the multicast group */
- ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
- &mcast->mcmember.mgid);
- if (ret)
- ipoib_warn(priv, "ipoib_mcast_detach failed (result = %d)\n", ret);
+ /* Remove ourselves from the multicast group */
+ ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
+ &mcast->mcmember.mgid);
+ if (ret)
+ ipoib_warn(priv, "ipoib_mcast_detach failed (result = %d)\n", ret);
+ }
- /*
- * Just make one shot at leaving and don't wait for a reply;
- * if we fail, too bad.
- */
- ret = ib_sa_mcmember_rec_delete(&ipoib_sa_client, priv->ca, priv->port, &rec,
- IB_SA_MCMEMBER_REC_MGID |
- IB_SA_MCMEMBER_REC_PORT_GID |
- IB_SA_MCMEMBER_REC_PKEY |
- IB_SA_MCMEMBER_REC_JOIN_STATE,
- 0, GFP_ATOMIC, NULL,
- mcast, &mcast->query);
- if (ret < 0)
- ipoib_warn(priv, "ib_sa_mcmember_rec_delete failed "
- "for leave (result = %d)\n", ret);
+ if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
+ ib_sa_free_multicast(mcast->mc);
return 0;
}
@@ -758,7 +708,7 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
dev_kfree_skb_any(skb);
}
- if (mcast->query)
+ if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
ipoib_dbg_mcast(priv, "no address vector, "
"but multicast join already started\n");
else if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
@@ -916,7 +866,6 @@ void ipoib_mcast_restart_task(struct work_struct *work)
/* We have to cancel outside of the spinlock */
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
- wait_for_mcast_join(priv, mcast);
ipoib_mcast_leave(mcast->dev, mcast);
ipoib_mcast_free(mcast);
}
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index bedae4ad3f7..80b199fa0aa 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -107,4 +107,19 @@ config MSI_LAPTOP
If you have an MSI S270 laptop, say Y or M here.
+config SONY_LAPTOP
+ tristate "Sony Laptop Extras"
+ depends on X86 && ACPI
+ select BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This mini-driver drives the SNC device present in the ACPI BIOS of
+ the Sony Vaio laptops.
+
+ It gives access to some extra laptop functionalities. In its current
+ form, this driver let the user set or query the screen brightness
+ through the backlight subsystem and remove/apply power to some
+ devices.
+
+ Read <file:Documentation/sony-laptop.txt> for more information.
+
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 35da53c409c..7793ccd7904 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_LKDTM) += lkdtm.o
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
+obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 861c39935f9..e4e2b707a35 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -1088,11 +1088,6 @@ static int __init asus_laptop_init(void)
if (acpi_disabled)
return -ENODEV;
- if (!acpi_specific_hotkey_enabled) {
- printk(ASUS_ERR "Using generic hotkey driver\n");
- return -ENODEV;
- }
-
result = acpi_bus_register_driver(&asus_hotk_driver);
if (result < 0)
return result;
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
new file mode 100644
index 00000000000..cabbed0015e
--- /dev/null
+++ b/drivers/misc/sony-laptop.c
@@ -0,0 +1,562 @@
+/*
+ * ACPI Sony Notebook Control Driver (SNC)
+ *
+ * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
+ * Copyright (C) 2007 Mattia Dongili <malattia@linux.it>
+ *
+ * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
+ * which are copyrighted by their respective authors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/backlight.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/acpi_bus.h>
+#include <asm/uaccess.h>
+
+#define ACPI_SNC_CLASS "sony"
+#define ACPI_SNC_HID "SNY5001"
+#define ACPI_SNC_DRIVER_NAME "ACPI Sony Notebook Control Driver v0.4"
+
+/* the device uses 1-based values, while the backlight subsystem uses
+ 0-based values */
+#define SONY_MAX_BRIGHTNESS 8
+
+#define LOG_PFX KERN_WARNING "sony-laptop: "
+
+MODULE_AUTHOR("Stelian Pop, Mattia Dongili");
+MODULE_DESCRIPTION(ACPI_SNC_DRIVER_NAME);
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
+ "the development of this driver");
+
+static ssize_t sony_acpi_show(struct device *, struct device_attribute *,
+ char *);
+static ssize_t sony_acpi_store(struct device *, struct device_attribute *,
+ const char *, size_t);
+static int boolean_validate(const int, const int);
+static int brightness_default_validate(const int, const int);
+
+#define SNC_VALIDATE_IN 0
+#define SNC_VALIDATE_OUT 1
+
+struct sony_acpi_value {
+ char *name; /* name of the entry */
+ char **acpiget; /* names of the ACPI get function */
+ char **acpiset; /* names of the ACPI set function */
+ int (*validate)(const int, const int); /* input/output validation */
+ int value; /* current setting */
+ int valid; /* Has ever been set */
+ int debug; /* active only in debug mode ? */
+ struct device_attribute devattr; /* sysfs atribute */
+};
+
+#define HANDLE_NAMES(_name, _values...) \
+ static char *snc_##_name[] = { _values, NULL }
+
+#define SONY_ACPI_VALUE(_name, _getters, _setters, _validate, _debug) \
+ { \
+ .name = __stringify(_name), \
+ .acpiget = _getters, \
+ .acpiset = _setters, \
+ .validate = _validate, \
+ .debug = _debug, \
+ .devattr = __ATTR(_name, 0, sony_acpi_show, sony_acpi_store), \
+ }
+
+#define SONY_ACPI_VALUE_NULL { .name = NULL }
+
+HANDLE_NAMES(fnkey_get, "GHKE");
+
+HANDLE_NAMES(brightness_def_get, "GPBR");
+HANDLE_NAMES(brightness_def_set, "SPBR");
+
+HANDLE_NAMES(cdpower_get, "GCDP");
+HANDLE_NAMES(cdpower_set, "SCDP", "CDPW");
+
+HANDLE_NAMES(audiopower_get, "GAZP");
+HANDLE_NAMES(audiopower_set, "AZPW");
+
+HANDLE_NAMES(lanpower_get, "GLNP");
+HANDLE_NAMES(lanpower_set, "LNPW");
+
+HANDLE_NAMES(PID_get, "GPID");
+
+HANDLE_NAMES(CTR_get, "GCTR");
+HANDLE_NAMES(CTR_set, "SCTR");
+
+HANDLE_NAMES(PCR_get, "GPCR");
+HANDLE_NAMES(PCR_set, "SPCR");
+
+HANDLE_NAMES(CMI_get, "GCMI");
+HANDLE_NAMES(CMI_set, "SCMI");
+
+static struct sony_acpi_value sony_acpi_values[] = {
+ SONY_ACPI_VALUE(brightness_default, snc_brightness_def_get,
+ snc_brightness_def_set, brightness_default_validate, 0),
+ SONY_ACPI_VALUE(fnkey, snc_fnkey_get, NULL, NULL, 0),
+ SONY_ACPI_VALUE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
+ SONY_ACPI_VALUE(audiopower, snc_audiopower_get, snc_audiopower_set,
+ boolean_validate, 0),
+ SONY_ACPI_VALUE(lanpower, snc_lanpower_get, snc_lanpower_set,
+ boolean_validate, 1),
+ /* unknown methods */
+ SONY_ACPI_VALUE(PID, snc_PID_get, NULL, NULL, 1),
+ SONY_ACPI_VALUE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
+ SONY_ACPI_VALUE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1),
+ SONY_ACPI_VALUE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1),
+ SONY_ACPI_VALUE_NULL
+};
+
+static acpi_handle sony_acpi_handle;
+static struct acpi_device *sony_acpi_acpi_device = NULL;
+
+/*
+ * acpi_evaluate_object wrappers
+ */
+static int acpi_callgetfunc(acpi_handle handle, char *name, int *result)
+{
+ struct acpi_buffer output;
+ union acpi_object out_obj;
+ acpi_status status;
+
+ output.length = sizeof(out_obj);
+ output.pointer = &out_obj;
+
+ status = acpi_evaluate_object(handle, name, NULL, &output);
+ if ((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)) {
+ *result = out_obj.integer.value;
+ return 0;
+ }
+
+ printk(LOG_PFX "acpi_callreadfunc failed\n");
+
+ return -1;
+}
+
+static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
+ int *result)
+{
+ struct acpi_object_list params;
+ union acpi_object in_obj;
+ struct acpi_buffer output;
+ union acpi_object out_obj;
+ acpi_status status;
+
+ params.count = 1;
+ params.pointer = &in_obj;
+ in_obj.type = ACPI_TYPE_INTEGER;
+ in_obj.integer.value = value;
+
+ output.length = sizeof(out_obj);
+ output.pointer = &out_obj;
+
+ status = acpi_evaluate_object(handle, name, &params, &output);
+ if (status == AE_OK) {
+ if (result != NULL) {
+ if (out_obj.type != ACPI_TYPE_INTEGER) {
+ printk(LOG_PFX "acpi_evaluate_object bad "
+ "return type\n");
+ return -1;
+ }
+ *result = out_obj.integer.value;
+ }
+ return 0;
+ }
+
+ printk(LOG_PFX "acpi_evaluate_object failed\n");
+
+ return -1;
+}
+
+/*
+ * sony_acpi_values input/output validate functions
+ */
+
+/* brightness_default_validate:
+ *
+ * manipulate input output values to keep consistency with the
+ * backlight framework for which brightness values are 0-based.
+ */
+static int brightness_default_validate(const int direction, const int value)
+{
+ switch (direction) {
+ case SNC_VALIDATE_OUT:
+ return value - 1;
+ case SNC_VALIDATE_IN:
+ if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
+ return value + 1;
+ }
+ return -EINVAL;
+}
+
+/* boolean_validate:
+ *
+ * on input validate boolean values 0/1, on output just pass the
+ * received value.
+ */
+static int boolean_validate(const int direction, const int value)
+{
+ if (direction == SNC_VALIDATE_IN) {
+ if (value != 0 && value != 1)
+ return -EINVAL;
+ }
+ return value;
+}
+
+/*
+ * Sysfs show/store common to all sony_acpi_values
+ */
+static ssize_t sony_acpi_show(struct device *dev, struct device_attribute *attr,
+ char *buffer)
+{
+ int value;
+ struct sony_acpi_value *item =
+ container_of(attr, struct sony_acpi_value, devattr);
+
+ if (!*item->acpiget)
+ return -EIO;
+
+ if (acpi_callgetfunc(sony_acpi_handle, *item->acpiget, &value) < 0)
+ return -EIO;
+
+ if (item->validate)
+ value = item->validate(SNC_VALIDATE_OUT, value);
+
+ return snprintf(buffer, PAGE_SIZE, "%d\n", value);
+}
+
+static ssize_t sony_acpi_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buffer, size_t count)
+{
+ int value;
+ struct sony_acpi_value *item =
+ container_of(attr, struct sony_acpi_value, devattr);
+
+ if (!item->acpiset)
+ return -EIO;
+
+ if (count > 31)
+ return -EINVAL;
+
+ value = simple_strtoul(buffer, NULL, 10);
+
+ if (item->validate)
+ value = item->validate(SNC_VALIDATE_IN, value);
+
+ if (value < 0)
+ return value;
+
+ if (acpi_callsetfunc(sony_acpi_handle, *item->acpiset, value, NULL) < 0)
+ return -EIO;
+ item->value = value;
+ item->valid = 1;
+ return count;
+}
+
+/*
+ * Platform device
+ */
+static struct platform_driver sncpf_driver = {
+ .driver = {
+ .name = "sony-laptop",
+ .owner = THIS_MODULE,
+ }
+};
+static struct platform_device *sncpf_device;
+
+static int sony_snc_pf_add(void)
+{
+ acpi_handle handle;
+ struct sony_acpi_value *item;
+ int ret = 0;
+
+ ret = platform_driver_register(&sncpf_driver);
+ if (ret)
+ goto out;
+
+ sncpf_device = platform_device_alloc("sony-laptop", -1);
+ if (!sncpf_device) {
+ ret = -ENOMEM;
+ goto out_platform_registered;
+ }
+
+ ret = platform_device_add(sncpf_device);
+ if (ret)
+ goto out_platform_alloced;
+
+ for (item = sony_acpi_values; item->name; ++item) {
+
+ if (!debug && item->debug)
+ continue;
+
+ /* find the available acpiget as described in the DSDT */
+ for (; item->acpiget && *item->acpiget; ++item->acpiget) {
+ if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle,
+ *item->acpiget,
+ &handle))) {
+ if (debug)
+ printk(LOG_PFX "Found %s getter: %s\n",
+ item->name, *item->acpiget);
+ item->devattr.attr.mode |= S_IRUGO;
+ break;
+ }
+ }
+
+ /* find the available acpiset as described in the DSDT */
+ for (; item->acpiset && *item->acpiset; ++item->acpiset) {
+ if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle,
+ *item->acpiset,
+ &handle))) {
+ if (debug)
+ printk(LOG_PFX "Found %s setter: %s\n",
+ item->name, *item->acpiset);
+ item->devattr.attr.mode |= S_IWUSR;
+ break;
+ }
+ }
+
+ if (item->devattr.attr.mode != 0) {
+ ret =
+ device_create_file(&sncpf_device->dev,
+ &item->devattr);
+ if (ret)
+ goto out_sysfs;
+ }
+ }
+
+ return 0;
+
+ out_sysfs:
+ for (item = sony_acpi_values; item->name; ++item) {
+ device_remove_file(&sncpf_device->dev, &item->devattr);
+ }
+ platform_device_del(sncpf_device);
+ out_platform_alloced:
+ platform_device_put(sncpf_device);
+ out_platform_registered:
+ platform_driver_unregister(&sncpf_driver);
+ out:
+ return ret;
+}
+
+static void sony_snc_pf_remove(void)
+{
+ struct sony_acpi_value *item;
+
+ for (item = sony_acpi_values; item->name; ++item) {
+ device_remove_file(&sncpf_device->dev, &item->devattr);
+ }
+
+ platform_device_del(sncpf_device);
+ platform_device_put(sncpf_device);
+ platform_driver_unregister(&sncpf_driver);
+}
+
+/*
+ * Backlight device
+ */
+static int sony_backlight_update_status(struct backlight_device *bd)
+{
+ return acpi_callsetfunc(sony_acpi_handle, "SBRT",
+ bd->props->brightness + 1, NULL);
+}
+
+static int sony_backlight_get_brightness(struct backlight_device *bd)
+{
+ int value;
+
+ if (acpi_callgetfunc(sony_acpi_handle, "GBRT", &value))
+ return 0;
+ /* brightness levels are 1-based, while backlight ones are 0-based */
+ return value - 1;
+}
+
+static struct backlight_device *sony_backlight_device;
+static struct backlight_properties sony_backlight_properties = {
+ .owner = THIS_MODULE,
+ .update_status = sony_backlight_update_status,
+ .get_brightness = sony_backlight_get_brightness,
+ .max_brightness = SONY_MAX_BRIGHTNESS - 1,
+};
+
+/*
+ * ACPI callbacks
+ */
+static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+ if (debug)
+ printk(LOG_PFX "sony_acpi_notify, event: %d\n", event);
+ acpi_bus_generate_event(sony_acpi_acpi_device, 1, event);
+}
+
+static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
+ void *context, void **return_value)
+{
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *operand;
+
+ node = (struct acpi_namespace_node *)handle;
+ operand = (union acpi_operand_object *)node->object;
+
+ printk(LOG_PFX "method: name: %4.4s, args %X\n", node->name.ascii,
+ (u32) operand->method.param_count);
+
+ return AE_OK;
+}
+
+/*
+ * ACPI device
+ */
+static int sony_acpi_resume(struct acpi_device *device)
+{
+ struct sony_acpi_value *item;
+
+ for (item = sony_acpi_values; item->name; item++) {
+ int ret;
+
+ if (!item->valid)
+ continue;
+ ret = acpi_callsetfunc(sony_acpi_handle, *item->acpiset,
+ item->value, NULL);
+ if (ret < 0) {
+ printk("%s: %d\n", __FUNCTION__, ret);
+ break;
+ }
+ }
+ return 0;
+}
+
+static int sony_acpi_add(struct acpi_device *device)
+{
+ acpi_status status;
+ int result;
+ acpi_handle handle;
+
+ sony_acpi_acpi_device = device;
+
+ sony_acpi_handle = device->handle;
+
+ if (debug) {
+ status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_acpi_handle,
+ 1, sony_walk_callback, NULL, NULL);
+ if (ACPI_FAILURE(status)) {
+ printk(LOG_PFX "unable to walk acpi resources\n");
+ result = -ENODEV;
+ goto outwalk;
+ }
+ }
+
+ status = acpi_install_notify_handler(sony_acpi_handle,
+ ACPI_DEVICE_NOTIFY,
+ sony_acpi_notify, NULL);
+ if (ACPI_FAILURE(status)) {
+ printk(LOG_PFX "unable to install notify handler\n");
+ result = -ENODEV;
+ goto outwalk;
+ }
+
+ if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle, "GBRT", &handle))) {
+ sony_backlight_device = backlight_device_register("sony", NULL,
+ NULL,
+ &sony_backlight_properties);
+
+ if (IS_ERR(sony_backlight_device)) {
+ printk(LOG_PFX "unable to register backlight device\n");
+ sony_backlight_device = NULL;
+ } else
+ sony_backlight_properties.brightness =
+ sony_backlight_get_brightness
+ (sony_backlight_device);
+ }
+
+ if (sony_snc_pf_add())
+ goto outbacklight;
+
+ printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully installed\n");
+
+ return 0;
+
+ outbacklight:
+ if (sony_backlight_device)
+ backlight_device_unregister(sony_backlight_device);
+
+ status = acpi_remove_notify_handler(sony_acpi_handle,
+ ACPI_DEVICE_NOTIFY,
+ sony_acpi_notify);
+ if (ACPI_FAILURE(status))
+ printk(LOG_PFX "unable to remove notify handler\n");
+ outwalk:
+ return result;
+}
+
+static int sony_acpi_remove(struct acpi_device *device, int type)
+{
+ acpi_status status;
+
+ if (sony_backlight_device)
+ backlight_device_unregister(sony_backlight_device);
+
+ sony_acpi_acpi_device = NULL;
+
+ status = acpi_remove_notify_handler(sony_acpi_handle,
+ ACPI_DEVICE_NOTIFY,
+ sony_acpi_notify);
+ if (ACPI_FAILURE(status))
+ printk(LOG_PFX "unable to remove notify handler\n");
+
+ sony_snc_pf_remove();
+
+ printk(KERN_INFO ACPI_SNC_DRIVER_NAME " successfully removed\n");
+
+ return 0;
+}
+
+static struct acpi_driver sony_acpi_driver = {
+ .name = ACPI_SNC_DRIVER_NAME,
+ .class = ACPI_SNC_CLASS,
+ .ids = ACPI_SNC_HID,
+ .ops = {
+ .add = sony_acpi_add,
+ .remove = sony_acpi_remove,
+ .resume = sony_acpi_resume,
+ },
+};
+
+static int __init sony_acpi_init(void)
+{
+ return acpi_bus_register_driver(&sony_acpi_driver);
+}
+
+static void __exit sony_acpi_exit(void)
+{
+ acpi_bus_unregister_driver(&sony_acpi_driver);
+}
+
+module_init(sony_acpi_init);
+module_exit(sony_acpi_exit);
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 2ce50f38e3c..459f4b4fede 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -64,6 +64,7 @@
#include <linux/err.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
+#include <linux/atmel_pdc.h>
#include <linux/mmc/host.h>
#include <linux/mmc/protocol.h>
@@ -75,7 +76,6 @@
#include <asm/arch/cpu.h>
#include <asm/arch/gpio.h>
#include <asm/arch/at91_mci.h>
-#include <asm/arch/at91_pdc.h>
#define DRIVER_NAME "at91_mci"
@@ -211,13 +211,13 @@ static void at91mci_pre_dma_read(struct at91mci_host *host)
/* Check to see if this needs filling */
if (i == 0) {
- if (at91_mci_read(host, AT91_PDC_RCR) != 0) {
+ if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
pr_debug("Transfer active in current\n");
continue;
}
}
else {
- if (at91_mci_read(host, AT91_PDC_RNCR) != 0) {
+ if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
pr_debug("Transfer active in next\n");
continue;
}
@@ -234,12 +234,12 @@ static void at91mci_pre_dma_read(struct at91mci_host *host)
pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
if (i == 0) {
- at91_mci_write(host, AT91_PDC_RPR, sg->dma_address);
- at91_mci_write(host, AT91_PDC_RCR, sg->length / 4);
+ at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
+ at91_mci_write(host, ATMEL_PDC_RCR, sg->length / 4);
}
else {
- at91_mci_write(host, AT91_PDC_RNPR, sg->dma_address);
- at91_mci_write(host, AT91_PDC_RNCR, sg->length / 4);
+ at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
+ at91_mci_write(host, ATMEL_PDC_RNCR, sg->length / 4);
}
}
@@ -303,7 +303,7 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
at91mci_pre_dma_read(host);
else {
at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
}
pr_debug("post dma read done\n");
@@ -320,7 +320,7 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
pr_debug("Handling the transmit\n");
/* Disable the transfer */
- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
/* Now wait for cmd ready */
at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
@@ -431,15 +431,15 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
if (!data) {
- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
- at91_mci_write(host, AT91_PDC_RPR, 0);
- at91_mci_write(host, AT91_PDC_RCR, 0);
- at91_mci_write(host, AT91_PDC_RNPR, 0);
- at91_mci_write(host, AT91_PDC_RNCR, 0);
- at91_mci_write(host, AT91_PDC_TPR, 0);
- at91_mci_write(host, AT91_PDC_TCR, 0);
- at91_mci_write(host, AT91_PDC_TNPR, 0);
- at91_mci_write(host, AT91_PDC_TNCR, 0);
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
+ at91_mci_write(host, ATMEL_PDC_RPR, 0);
+ at91_mci_write(host, ATMEL_PDC_RCR, 0);
+ at91_mci_write(host, ATMEL_PDC_RNPR, 0);
+ at91_mci_write(host, ATMEL_PDC_RNCR, 0);
+ at91_mci_write(host, ATMEL_PDC_TPR, 0);
+ at91_mci_write(host, ATMEL_PDC_TCR, 0);
+ at91_mci_write(host, ATMEL_PDC_TNPR, 0);
+ at91_mci_write(host, ATMEL_PDC_TNCR, 0);
at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
at91_mci_write(host, AT91_MCI_CMDR, cmdr);
@@ -452,7 +452,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
/*
* Disable the PDC controller
*/
- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
if (cmdr & AT91_MCI_TRCMD_START) {
data->bytes_xfered = 0;
@@ -481,8 +481,8 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
pr_debug("Transmitting %d bytes\n", host->total_length);
- at91_mci_write(host, AT91_PDC_TPR, host->physical_address);
- at91_mci_write(host, AT91_PDC_TCR, host->total_length / 4);
+ at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
+ at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
ier = AT91_MCI_TXBUFE;
}
}
@@ -497,9 +497,9 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
if (cmdr & AT91_MCI_TRCMD_START) {
if (cmdr & AT91_MCI_TRDIR)
- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_RXTEN);
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
else
- at91_mci_write(host, AT91_PDC_PTCR, AT91_PDC_TXTEN);
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
}
return ier;
}
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 38f41a593b1..d9400ef8719 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1284,8 +1284,8 @@ config PCNET32
will be called pcnet32.
config PCNET32_NAPI
- bool "Use RX polling (NAPI) (EXPERIMENTAL)"
- depends on PCNET32 && EXPERIMENTAL
+ bool "Use RX polling (NAPI)"
+ depends on PCNET32
help
NAPI is a new driver API designed to reduce CPU and interrupt load
when the driver is receiving lots of packets from the card. It is
@@ -2125,14 +2125,16 @@ config SKY2
will be called sky2. This is recommended.
config SK98LIN
- tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
+ tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)"
depends on PCI
---help---
Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
compliant Gigabit Ethernet Adapter.
- This driver supports the original Yukon chipset. A cleaner driver is
- also available (skge) which seems to work better than this one.
+ This driver supports the original Yukon chipset. This driver is
+ deprecated and will be removed from the kernel in the near future,
+ it has been replaced by the skge driver. skge is cleaner and
+ seems to work better.
This driver does not support the newer Yukon2 chipset. A separate
driver, sky2, is provided to support Yukon2-based adapters.
@@ -2337,7 +2339,7 @@ config QLA3XXX
config ATL1
tristate "Attansic L1 Gigabit Ethernet support (EXPERIMENTAL)"
- depends on NET_PCI && PCI && EXPERIMENTAL
+ depends on PCI && EXPERIMENTAL
select CRC32
select MII
help
diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c
index e7555d4e6ff..6318814a11a 100644
--- a/drivers/net/arcnet/arc-rawmode.c
+++ b/drivers/net/arcnet/arc-rawmode.c
@@ -94,7 +94,7 @@ static void rx(struct net_device *dev, int bufnum,
BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length);
- if (length >= MinTU)
+ if (length > MTU)
ofs = 512 - length;
else
ofs = 256 - length;
@@ -183,7 +183,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
length, XMTU);
length = XMTU;
}
- if (length > MinTU) {
+ if (length >= MinTU) {
hard->offset[0] = 0;
hard->offset[1] = ofs = 512 - length;
} else if (length > MTU) {
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 4e91dab1f17..83004fdab0a 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -41,7 +41,7 @@
* <jojo@repas.de>
*/
-#define VERSION "arcnet: v3.93 BETA 2000/04/29 - by Avery Pennarun et al.\n"
+#define VERSION "arcnet: v3.94 BETA 2007/02/08 - by Avery Pennarun et al.\n"
#include <linux/module.h>
#include <linux/types.h>
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 98d326b23c9..b8c0fa6d401 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -155,6 +155,7 @@ static struct pci_device_id com20020pci_id_table[] = {
{ 0x1571, 0xa00b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
{ 0x1571, 0xa00c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
{ 0x1571, 0xa00d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
+ { 0x1571, 0xa00e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
{ 0x1571, 0xa201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
{ 0x1571, 0xa202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
{ 0x1571, 0xa203, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
@@ -163,6 +164,8 @@ static struct pci_device_id com20020pci_id_table[] = {
{ 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
{ 0x10B5, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
{ 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+ { 0x14BA, 0x6000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+ { 0x10B5, 0x2200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
{0,}
};
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index 4218075c8aa..7cf0a251169 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -104,7 +104,7 @@ int com20020_check(struct net_device *dev)
SET_SUBADR(SUB_SETUP1);
outb(lp->setup, _XREG);
- if (lp->card_flags & ARC_CAN_10MBIT)
+ if (lp->clockm != 0)
{
SET_SUBADR(SUB_SETUP2);
outb(lp->setup2, _XREG);
diff --git a/drivers/net/atl1/atl1_hw.c b/drivers/net/atl1/atl1_hw.c
index 08b2d785469..314dbaabb64 100644
--- a/drivers/net/atl1/atl1_hw.c
+++ b/drivers/net/atl1/atl1_hw.c
@@ -243,14 +243,8 @@ static int atl1_get_permanent_address(struct atl1_hw *hw)
i += 4;
}
-/*
- * The following 2 lines are the Attansic originals. Saving for posterity.
- * *(u32 *) & eth_addr[2] = LONGSWAP(addr[0]);
- * *(u16 *) & eth_addr[0] = SHORTSWAP(*(u16 *) & addr[1]);
- */
- *(u32 *) & eth_addr[2] = swab32(addr[0]);
- *(u16 *) & eth_addr[0] = swab16(*(u16 *) & addr[1]);
-
+ *(u32 *) &eth_addr[2] = swab32(addr[0]);
+ *(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
if (is_valid_ether_addr(eth_addr)) {
memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
return 0;
@@ -281,17 +275,28 @@ static int atl1_get_permanent_address(struct atl1_hw *hw)
i += 4;
}
-/*
- * The following 2 lines are the Attansic originals. Saving for posterity.
- * *(u32 *) & eth_addr[2] = LONGSWAP(addr[0]);
- * *(u16 *) & eth_addr[0] = SHORTSWAP(*(u16 *) & addr[1]);
- */
- *(u32 *) & eth_addr[2] = swab32(addr[0]);
- *(u16 *) & eth_addr[0] = swab16(*(u16 *) & addr[1]);
+ *(u32 *) &eth_addr[2] = swab32(addr[0]);
+ *(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
if (is_valid_ether_addr(eth_addr)) {
memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
return 0;
}
+
+ /*
+ * On some motherboards, the MAC address is written by the
+ * BIOS directly to the MAC register during POST, and is
+ * not stored in eeprom. If all else thus far has failed
+ * to fetch the permanent MAC address, try reading it directly.
+ */
+ addr[0] = ioread32(hw->hw_addr + REG_MAC_STA_ADDR);
+ addr[1] = ioread16(hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+ *(u32 *) &eth_addr[2] = swab32(addr[0]);
+ *(u16 *) &eth_addr[0] = swab16(*(u16 *) &addr[1]);
+ if (is_valid_ether_addr(eth_addr)) {
+ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ return 0;
+ }
+
return 1;
}
@@ -357,7 +362,7 @@ void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
*/
hash_reg = (hash_value >> 31) & 0x1;
hash_bit = (hash_value >> 26) & 0x1F;
- mta = ioread32((hw + REG_RX_HASH_TABLE) + (hash_reg << 2));
+ mta = ioread32((hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
mta |= (1 << hash_bit);
iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
}
diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
index 6655640eb4c..65673485bb6 100644
--- a/drivers/net/atl1/atl1_main.c
+++ b/drivers/net/atl1/atl1_main.c
@@ -82,8 +82,7 @@
#include "atl1.h"
-#define RUN_REALTIME 0
-#define DRIVER_VERSION "2.0.6"
+#define DRIVER_VERSION "2.0.7"
char atl1_driver_name[] = "atl1";
static const char atl1_driver_string[] = "Attansic L1 Ethernet Network Driver";
@@ -100,7 +99,7 @@ MODULE_VERSION(DRIVER_VERSION);
* atl1_pci_tbl - PCI Device ID Table
*/
static const struct pci_device_id atl1_pci_tbl[] = {
- {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1048)},
+ {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
/* required last entry */
{0,}
};
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 5ff7882297d..aaada572732 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -59,7 +59,6 @@
#define B44_DEF_TX_RING_PENDING (B44_TX_RING_SIZE - 1)
#define B44_TX_RING_BYTES (sizeof(struct dma_desc) * \
B44_TX_RING_SIZE)
-#define B44_DMA_MASK 0x3fffffff
#define TX_RING_GAP(BP) \
(B44_TX_RING_SIZE - (BP)->tx_pending)
@@ -665,7 +664,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
/* Hardware bug work-around, the chip is unable to do PCI DMA
to/from anything above 1GB :-( */
if (dma_mapping_error(mapping) ||
- mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+ mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
/* Sigh... */
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
@@ -677,7 +676,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
RX_PKT_BUF_SZ,
PCI_DMA_FROMDEVICE);
if (dma_mapping_error(mapping) ||
- mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
+ mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(skb);
@@ -988,7 +987,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
- if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
+ if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
@@ -1000,7 +999,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
mapping = pci_map_single(bp->pdev, bounce_skb->data,
len, PCI_DMA_TODEVICE);
- if (dma_mapping_error(mapping) || mapping + len > B44_DMA_MASK) {
+ if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping,
len, PCI_DMA_TODEVICE);
@@ -1227,7 +1226,7 @@ static int b44_alloc_consistent(struct b44 *bp)
DMA_BIDIRECTIONAL);
if (dma_mapping_error(rx_ring_dma) ||
- rx_ring_dma + size > B44_DMA_MASK) {
+ rx_ring_dma + size > DMA_30BIT_MASK) {
kfree(rx_ring);
goto out_err;
}
@@ -1254,7 +1253,7 @@ static int b44_alloc_consistent(struct b44 *bp)
DMA_TO_DEVICE);
if (dma_mapping_error(tx_ring_dma) ||
- tx_ring_dma + size > B44_DMA_MASK) {
+ tx_ring_dma + size > DMA_30BIT_MASK) {
kfree(tx_ring);
goto out_err;
}
@@ -1289,7 +1288,7 @@ static void b44_chip_reset(struct b44 *bp)
if (ssb_is_core_up(bp)) {
bw32(bp, B44_RCV_LAZY, 0);
bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
- b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 100, 1);
+ b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 200, 1);
bw32(bp, B44_DMATX_CTRL, 0);
bp->tx_prod = bp->tx_cons = 0;
if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK) {
@@ -2151,13 +2150,13 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
pci_set_master(pdev);
- err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK);
+ err = pci_set_dma_mask(pdev, (u64) DMA_30BIT_MASK);
if (err) {
dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
goto err_out_free_res;
}
- err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
+ err = pci_set_consistent_dma_mask(pdev, (u64) DMA_30BIT_MASK);
if (err) {
dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
goto err_out_free_res;
diff --git a/drivers/net/cxgb3/cxgb3_defs.h b/drivers/net/cxgb3/cxgb3_defs.h
index 16e004990c5..e14862b43d1 100644
--- a/drivers/net/cxgb3/cxgb3_defs.h
+++ b/drivers/net/cxgb3/cxgb3_defs.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index c6b72664318..b2cf5f6feb4 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/cxgb3/cxgb3_offload.h b/drivers/net/cxgb3/cxgb3_offload.h
index 0e6beb69ba1..f15446a32ef 100644
--- a/drivers/net/cxgb3/cxgb3_offload.h
+++ b/drivers/net/cxgb3/cxgb3_offload.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c
index 3c0cb855705..d660af74606 100644
--- a/drivers/net/cxgb3/l2t.c
+++ b/drivers/net/cxgb3/l2t.c
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/cxgb3/l2t.h b/drivers/net/cxgb3/l2t.h
index ba5d2cbd724..d79001336cf 100644
--- a/drivers/net/cxgb3/l2t.h
+++ b/drivers/net/cxgb3/l2t.h
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
- * Copyright (c) 2006-2007 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h
index 9af3bcd64b3..fa4099bc041 100644
--- a/drivers/net/cxgb3/t3cdev.h
+++ b/drivers/net/cxgb3/t3cdev.h
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006-2007 Chelsio Communications. All rights reserved.
- * Copyright (C) 2006-2007 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 689f158a469..dd4b728ac4b 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -337,7 +337,6 @@ struct e1000_adapter {
struct e1000_rx_ring test_rx_ring;
- uint32_t *config_space;
int msg_enable;
#ifdef CONFIG_PCI_MSI
boolean_t have_msi;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 44ebc72962d..6777887295f 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -166,7 +166,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->transceiver = XCVR_EXTERNAL;
}
- if (netif_carrier_ok(adapter->netdev)) {
+ if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) {
e1000_get_speed_and_duplex(hw, &adapter->link_speed,
&adapter->link_duplex);
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 619c89218b4..a71023741c3 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1417,10 +1417,6 @@ e1000_open(struct net_device *netdev)
if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
- err = e1000_request_irq(adapter);
- if (err)
- goto err_req_irq;
-
e1000_power_up_phy(adapter);
if ((err = e1000_up(adapter)))
@@ -1431,6 +1427,10 @@ e1000_open(struct net_device *netdev)
e1000_update_mng_vlan(adapter);
}
+ err = e1000_request_irq(adapter);
+ if (err)
+ goto err_req_irq;
+
/* If AMT is enabled, let the firmware know that the network
* interface is now open */
if (adapter->hw.mac_type == e1000_82573 &&
@@ -1439,10 +1439,10 @@ e1000_open(struct net_device *netdev)
return E1000_SUCCESS;
+err_req_irq:
+ e1000_down(adapter);
err_up:
e1000_power_down_phy(adapter);
- e1000_free_irq(adapter);
-err_req_irq:
e1000_free_all_rx_resources(adapter);
err_setup_rx:
e1000_free_all_tx_resources(adapter);
@@ -5071,58 +5071,6 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
return 0;
}
-#ifdef CONFIG_PM
-/* Save/restore 16 or 64 dwords of PCI config space depending on which
- * bus we're on (PCI(X) vs. PCI-E)
- */
-#define PCIE_CONFIG_SPACE_LEN 256
-#define PCI_CONFIG_SPACE_LEN 64
-static int
-e1000_pci_save_state(struct e1000_adapter *adapter)
-{
- struct pci_dev *dev = adapter->pdev;
- int size;
- int i;
-
- if (adapter->hw.mac_type >= e1000_82571)
- size = PCIE_CONFIG_SPACE_LEN;
- else
- size = PCI_CONFIG_SPACE_LEN;
-
- WARN_ON(adapter->config_space != NULL);
-
- adapter->config_space = kmalloc(size, GFP_KERNEL);
- if (!adapter->config_space) {
- DPRINTK(PROBE, ERR, "unable to allocate %d bytes\n", size);
- return -ENOMEM;
- }
- for (i = 0; i < (size / 4); i++)
- pci_read_config_dword(dev, i * 4, &adapter->config_space[i]);
- return 0;
-}
-
-static void
-e1000_pci_restore_state(struct e1000_adapter *adapter)
-{
- struct pci_dev *dev = adapter->pdev;
- int size;
- int i;
-
- if (adapter->config_space == NULL)
- return;
-
- if (adapter->hw.mac_type >= e1000_82571)
- size = PCIE_CONFIG_SPACE_LEN;
- else
- size = PCI_CONFIG_SPACE_LEN;
- for (i = 0; i < (size / 4); i++)
- pci_write_config_dword(dev, i * 4, adapter->config_space[i]);
- kfree(adapter->config_space);
- adapter->config_space = NULL;
- return;
-}
-#endif /* CONFIG_PM */
-
static int
e1000_suspend(struct pci_dev *pdev, pm_message_t state)
{
@@ -5142,9 +5090,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
}
#ifdef CONFIG_PM
- /* Implement our own version of pci_save_state(pdev) because pci-
- * express adapters have 256-byte config spaces. */
- retval = e1000_pci_save_state(adapter);
+ retval = pci_save_state(pdev);
if (retval)
return retval;
#endif
@@ -5231,7 +5177,7 @@ e1000_resume(struct pci_dev *pdev)
uint32_t err;
pci_set_power_state(pdev, PCI_D0);
- e1000_pci_restore_state(adapter);
+ pci_restore_state(pdev);
if ((err = pci_enable_device(pdev))) {
printk(KERN_ERR "e1000: Cannot enable PCI device from suspend\n");
return err;
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 272e1ec51aa..42295d61ecd 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,7 +39,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0045"
+#define DRV_VERSION "EHEA_0046"
#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 38b2fa424b2..88ad1c8bcee 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -76,7 +76,7 @@ void ehea_dump(void *adr, int len, char *msg) {
int x;
unsigned char *deb = adr;
for (x = 0; x < len; x += 16) {
- printk(DRV_NAME "%s adr=%p ofs=%04x %016lx %016lx\n", msg,
+ printk(DRV_NAME " %s adr=%p ofs=%04x %016lx %016lx\n", msg,
deb, x, *((u64*)&deb[0]), *((u64*)&deb[8]));
deb += 16;
}
@@ -555,6 +555,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
{
struct ehea_port *port = param;
struct ehea_eqe *eqe;
+ struct ehea_qp *qp;
u32 qp_token;
eqe = ehea_poll_eq(port->qp_eq);
@@ -563,9 +564,14 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
ehea_error("QP aff_err: entry=0x%lx, token=0x%x",
eqe->entry, qp_token);
+
+ qp = port->port_res[qp_token].qp;
+ ehea_error_data(port->adapter, qp->fw_handle);
eqe = ehea_poll_eq(port->qp_eq);
}
+ queue_work(port->adapter->ehea_wq, &port->reset_task);
+
return IRQ_HANDLED;
}
diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c
index 37716e05e80..bc3c0054726 100644
--- a/drivers/net/ehea/ehea_phyp.c
+++ b/drivers/net/ehea/ehea_phyp.c
@@ -612,3 +612,13 @@ u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle,
event_mask, /* R6 */
0, 0, 0, 0); /* R7-R12 */
}
+
+u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
+ void *rblock)
+{
+ return ehea_plpar_hcall_norets(H_ERROR_DATA,
+ adapter_handle, /* R4 */
+ ressource_handle, /* R5 */
+ virt_to_abs(rblock), /* R6 */
+ 0, 0, 0, 0); /* R7-R12 */
+}
diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ehea/ehea_phyp.h
index 919f94b7593..90acddb068a 100644
--- a/drivers/net/ehea/ehea_phyp.h
+++ b/drivers/net/ehea/ehea_phyp.h
@@ -454,4 +454,7 @@ u64 ehea_h_reg_dereg_bcmc(const u64 adapter_handle, const u16 port_num,
u64 ehea_h_reset_events(const u64 adapter_handle, const u64 neq_handle,
const u64 event_mask);
+u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
+ void *rblock);
+
#endif /* __EHEA_PHYP_H__ */
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index f143e13b229..96ff3b67999 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -486,6 +486,7 @@ int ehea_destroy_qp(struct ehea_qp *qp)
if (!qp)
return 0;
+ ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle);
if (hret != H_SUCCESS) {
ehea_error("destroy_qp failed");
@@ -581,4 +582,45 @@ out:
return ret;
}
+void print_error_data(u64 *data)
+{
+ int length;
+ u64 type = EHEA_BMASK_GET(ERROR_DATA_TYPE, data[2]);
+ u64 resource = data[1];
+
+ length = EHEA_BMASK_GET(ERROR_DATA_LENGTH, data[0]);
+
+ if (length > EHEA_PAGESIZE)
+ length = EHEA_PAGESIZE;
+
+ if (type == 0x8) /* Queue Pair */
+ ehea_error("QP (resource=%lX) state: AER=0x%lX, AERR=0x%lX, "
+ "port=%lX", resource, data[6], data[12], data[22]);
+
+ ehea_dump(data, length, "error data");
+}
+
+void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle)
+{
+ unsigned long ret;
+ u64 *rblock;
+
+ rblock = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!rblock) {
+ ehea_error("Cannot allocate rblock memory.");
+ return;
+ }
+ ret = ehea_h_error_data(adapter->handle,
+ res_handle,
+ rblock);
+
+ if (ret == H_R_STATE)
+ ehea_error("No error data is available: %lX.", res_handle);
+ else if (ret == H_SUCCESS)
+ print_error_data(rblock);
+ else
+ ehea_error("Error data could not be fetched: %lX", res_handle);
+
+ kfree(rblock);
+}
diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h
index 7efdc96919c..1ff60983504 100644
--- a/drivers/net/ehea/ehea_qmr.h
+++ b/drivers/net/ehea/ehea_qmr.h
@@ -180,6 +180,9 @@ struct ehea_eqe {
u64 entry;
};
+#define ERROR_DATA_LENGTH EHEA_BMASK_IBM(52,63)
+#define ERROR_DATA_TYPE EHEA_BMASK_IBM(0,7)
+
static inline void *hw_qeit_calc(struct hw_queue *queue, u64 q_offset)
{
struct ehea_page *current_page;
@@ -355,4 +358,6 @@ int ehea_destroy_qp(struct ehea_qp *qp);
int ehea_reg_mr_adapter(struct ehea_adapter *adapter);
+void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle);
+
#endif /* __EHEA_QMR_H__ */
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 1be4a84dce0..1f83988a6a6 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -10,6 +10,7 @@
* Maintainer: Kumar Gala
*
* Copyright (c) 2002-2006 Freescale Semiconductor, Inc.
+ * Copyright (c) 2007 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 as published by the
@@ -1612,71 +1613,17 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id)
/* Save ievent for future reference */
u32 events = gfar_read(&priv->regs->ievent);
- /* Clear IEVENT */
- gfar_write(&priv->regs->ievent, events);
-
/* Check for reception */
- if ((events & IEVENT_RXF0) || (events & IEVENT_RXB0))
+ if (events & IEVENT_RX_MASK)
gfar_receive(irq, dev_id);
/* Check for transmit completion */
- if ((events & IEVENT_TXF) || (events & IEVENT_TXB))
+ if (events & IEVENT_TX_MASK)
gfar_transmit(irq, dev_id);
- /* Update error statistics */
- if (events & IEVENT_TXE) {
- priv->stats.tx_errors++;
-
- if (events & IEVENT_LC)
- priv->stats.tx_window_errors++;
- if (events & IEVENT_CRL)
- priv->stats.tx_aborted_errors++;
- if (events & IEVENT_XFUN) {
- if (netif_msg_tx_err(priv))
- printk(KERN_WARNING "%s: tx underrun. dropped packet\n", dev->name);
- priv->stats.tx_dropped++;
- priv->extra_stats.tx_underrun++;
-
- /* Reactivate the Tx Queues */
- gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
- }
- }
- if (events & IEVENT_BSY) {
- priv->stats.rx_errors++;
- priv->extra_stats.rx_bsy++;
-
- gfar_receive(irq, dev_id);
-
-#ifndef CONFIG_GFAR_NAPI
- /* Clear the halt bit in RSTAT */
- gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
-#endif
-
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n",
- dev->name,
- gfar_read(&priv->regs->rstat));
- }
- if (events & IEVENT_BABR) {
- priv->stats.rx_errors++;
- priv->extra_stats.rx_babr++;
-
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: babbling error\n", dev->name);
- }
- if (events & IEVENT_EBERR) {
- priv->extra_stats.eberr++;
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: EBERR\n", dev->name);
- }
- if ((events & IEVENT_RXC) && (netif_msg_rx_err(priv)))
- printk(KERN_DEBUG "%s: control frame\n", dev->name);
-
- if (events & IEVENT_BABT) {
- priv->extra_stats.tx_babt++;
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: babt error\n", dev->name);
- }
+ /* Check for errors */
+ if (events & IEVENT_ERR_MASK)
+ gfar_error(irq, dev_id);
return IRQ_HANDLED;
}
@@ -1938,7 +1885,7 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
/* Hmm... */
if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n",
- dev->name, events, gfar_read(&priv->regs->imask));
+ dev->name, events, gfar_read(&priv->regs->imask));
/* Update the error counters */
if (events & IEVENT_TXE) {
@@ -1950,8 +1897,8 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
priv->stats.tx_aborted_errors++;
if (events & IEVENT_XFUN) {
if (netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: underrun. packet dropped.\n",
- dev->name);
+ printk(KERN_DEBUG "%s: TX FIFO underrun, "
+ "packet dropped.\n", dev->name);
priv->stats.tx_dropped++;
priv->extra_stats.tx_underrun++;
@@ -1973,30 +1920,28 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
#endif
if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n",
- dev->name,
- gfar_read(&priv->regs->rstat));
+ printk(KERN_DEBUG "%s: busy error (rstat: %x)\n",
+ dev->name, gfar_read(&priv->regs->rstat));
}
if (events & IEVENT_BABR) {
priv->stats.rx_errors++;
priv->extra_stats.rx_babr++;
if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: babbling error\n", dev->name);
+ printk(KERN_DEBUG "%s: babbling RX error\n", dev->name);
}
if (events & IEVENT_EBERR) {
priv->extra_stats.eberr++;
if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: EBERR\n", dev->name);
+ printk(KERN_DEBUG "%s: bus error\n", dev->name);
}
if ((events & IEVENT_RXC) && netif_msg_rx_status(priv))
- if (netif_msg_rx_status(priv))
- printk(KERN_DEBUG "%s: control frame\n", dev->name);
+ printk(KERN_DEBUG "%s: control frame\n", dev->name);
if (events & IEVENT_BABT) {
priv->extra_stats.tx_babt++;
if (netif_msg_tx_err(priv))
- printk(KERN_DEBUG "%s: babt error\n", dev->name);
+ printk(KERN_DEBUG "%s: babbling TX error\n", dev->name);
}
return IRQ_HANDLED;
}
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c
index 45ffb5d0ca3..aec9ab17a9a 100644
--- a/drivers/net/gianfar_sysfs.c
+++ b/drivers/net/gianfar_sysfs.c
@@ -38,13 +38,15 @@
#include "gianfar.h"
#define GFAR_ATTR(_name) \
-static ssize_t gfar_show_##_name(struct class_device *cdev, char *buf); \
-static ssize_t gfar_set_##_name(struct class_device *cdev, \
+static ssize_t gfar_show_##_name(struct device *dev, \
+ struct device_attribute *attr, char *buf); \
+static ssize_t gfar_set_##_name(struct device *dev, \
+ struct device_attribute *attr, \
const char *buf, size_t count); \
-static CLASS_DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name)
+static DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name)
#define GFAR_CREATE_FILE(_dev, _name) \
- class_device_create_file(&_dev->class_dev, &class_device_attr_##_name)
+ device_create_file(&_dev->dev, &dev_attr_##_name)
GFAR_ATTR(bd_stash);
GFAR_ATTR(rx_stash_size);
@@ -53,29 +55,28 @@ GFAR_ATTR(fifo_threshold);
GFAR_ATTR(fifo_starve);
GFAR_ATTR(fifo_starve_off);
-#define to_net_dev(cd) container_of(cd, struct net_device, class_dev)
-
-static ssize_t gfar_show_bd_stash(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_bd_stash(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- return sprintf(buf, "%s\n", priv->bd_stash_en? "on" : "off");
+ return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off");
}
-static ssize_t gfar_set_bd_stash(struct class_device *cdev,
- const char *buf, size_t count)
+static ssize_t gfar_set_bd_stash(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
int new_setting = 0;
u32 temp;
unsigned long flags;
/* Find out the new setting */
- if (!strncmp("on", buf, count-1) || !strncmp("1", buf, count-1))
+ if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
new_setting = 1;
- else if (!strncmp("off", buf, count-1) || !strncmp("0", buf, count-1))
+ else if (!strncmp("off", buf, count - 1)
+ || !strncmp("0", buf, count - 1))
new_setting = 0;
else
return count;
@@ -99,19 +100,19 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev,
return count;
}
-static ssize_t gfar_show_rx_stash_size(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_rx_stash_size(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
return sprintf(buf, "%d\n", priv->rx_stash_size);
}
-static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
- const char *buf, size_t count)
+static ssize_t gfar_set_rx_stash_size(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
unsigned int length = simple_strtoul(buf, NULL, 0);
u32 temp;
unsigned long flags;
@@ -145,21 +146,21 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
return count;
}
-
/* Stashing will only be enabled when rx_stash_size != 0 */
-static ssize_t gfar_show_rx_stash_index(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_rx_stash_index(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
return sprintf(buf, "%d\n", priv->rx_stash_index);
}
-static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
- const char *buf, size_t count)
+static ssize_t gfar_set_rx_stash_index(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
unsigned short index = simple_strtoul(buf, NULL, 0);
u32 temp;
unsigned long flags;
@@ -183,19 +184,20 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
return count;
}
-static ssize_t gfar_show_fifo_threshold(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_fifo_threshold(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
return sprintf(buf, "%d\n", priv->fifo_threshold);
}
-static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
- const char *buf, size_t count)
+static ssize_t gfar_set_fifo_threshold(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
unsigned int length = simple_strtoul(buf, NULL, 0);
u32 temp;
unsigned long flags;
@@ -217,20 +219,19 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
return count;
}
-static ssize_t gfar_show_fifo_starve(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_fifo_starve(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
return sprintf(buf, "%d\n", priv->fifo_starve);
}
-
-static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
- const char *buf, size_t count)
+static ssize_t gfar_set_fifo_starve(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
unsigned int num = simple_strtoul(buf, NULL, 0);
u32 temp;
unsigned long flags;
@@ -252,19 +253,20 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
return count;
}
-static ssize_t gfar_show_fifo_starve_off(struct class_device *cdev, char *buf)
+static ssize_t gfar_show_fifo_starve_off(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
return sprintf(buf, "%d\n", priv->fifo_starve_off);
}
-static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev,
- const char *buf, size_t count)
+static ssize_t gfar_set_fifo_starve_off(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct net_device *dev = to_net_dev(cdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = netdev_priv(to_net_dev(dev));
unsigned int num = simple_strtoul(buf, NULL, 0);
u32 temp;
unsigned long flags;
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index f0d30cf67b5..4ad780719a8 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -836,13 +836,17 @@ static int ioc3_mii_init(struct ioc3_private *ip)
}
ip->mii.phy_id = i;
+
+out:
+ return res;
+}
+
+static void ioc3_mii_start(struct ioc3_private *ip)
+{
ip->ioc3_timer.expires = jiffies + (12 * HZ)/10; /* 1.2 sec. */
ip->ioc3_timer.data = (unsigned long) ip;
ip->ioc3_timer.function = &ioc3_timer;
add_timer(&ip->ioc3_timer);
-
-out:
- return res;
}
static inline void ioc3_clean_rx_ring(struct ioc3_private *ip)
@@ -1071,6 +1075,7 @@ static int ioc3_open(struct net_device *dev)
ip->ehar_h = 0;
ip->ehar_l = 0;
ioc3_init(dev);
+ ioc3_mii_start(ip);
netif_start_queue(dev);
return 0;
@@ -1274,6 +1279,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_stop;
}
+ ioc3_mii_start(ip);
ioc3_ssram_disc(ip);
ioc3_get_eaddr(ip);
@@ -1314,6 +1320,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
out_stop:
ioc3_stop(ip);
+ del_timer_sync(&ip->ioc3_timer);
ioc3_free_rings(ip);
out_res:
pci_release_regions(pdev);
@@ -1335,6 +1342,8 @@ static void __devexit ioc3_remove_one (struct pci_dev *pdev)
struct ioc3 *ioc3 = ip->regs;
unregister_netdev(dev);
+ del_timer_sync(&ip->ioc3_timer);
+
iounmap(ioc3);
pci_release_regions(pdev);
free_netdev(dev);
@@ -1492,6 +1501,7 @@ static void ioc3_timeout(struct net_device *dev)
ioc3_stop(ip);
ioc3_init(dev);
ioc3_mii_init(ip);
+ ioc3_mii_start(ip);
spin_unlock_irq(&ip->ioc3_lock);
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index a41418b3c51..2e9571bf073 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -881,27 +881,15 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct macb *bp = netdev_priv(dev);
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&bp->lock, flags);
- ret = mii_ethtool_gset(&bp->mii, cmd);
- spin_unlock_irqrestore(&bp->lock, flags);
- return ret;
+ return mii_ethtool_gset(&bp->mii, cmd);
}
static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct macb *bp = netdev_priv(dev);
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&bp->lock, flags);
- ret = mii_ethtool_sset(&bp->mii, cmd);
- spin_unlock_irqrestore(&bp->lock, flags);
- return ret;
+ return mii_ethtool_sset(&bp->mii, cmd);
}
static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
@@ -930,17 +918,11 @@ static struct ethtool_ops macb_ethtool_ops = {
static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct macb *bp = netdev_priv(dev);
- int ret;
- unsigned long flags;
if (!netif_running(dev))
return -EINVAL;
- spin_lock_irqsave(&bp->lock, flags);
- ret = generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
- spin_unlock_irqrestore(&bp->lock, flags);
-
- return ret;
+ return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
}
static ssize_t macb_mii_show(const struct device *_dev, char *buf,
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index d38b7c72362..7e69ca6edd9 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -170,7 +170,7 @@ static int mdio_probe(struct meth_private *priv)
static void meth_check_link(struct net_device *dev)
{
- struct meth_private *priv = (struct meth_private *) dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
unsigned long mii_advertising = mdio_read(priv, 4);
unsigned long mii_partner = mdio_read(priv, 5);
unsigned long negotiated = mii_advertising & mii_partner;
@@ -268,7 +268,7 @@ static void meth_free_rx_ring(struct meth_private *priv)
int meth_reset(struct net_device *dev)
{
- struct meth_private *priv = (struct meth_private *) dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
/* Reset card */
mace->eth.mac_ctrl = SGI_MAC_RESET;
@@ -310,7 +310,7 @@ int meth_reset(struct net_device *dev)
*/
static int meth_open(struct net_device *dev)
{
- struct meth_private *priv = dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
int ret;
priv->phy_addr = -1; /* No PHY is known yet... */
@@ -354,7 +354,7 @@ out_free_tx_ring:
static int meth_release(struct net_device *dev)
{
- struct meth_private *priv = dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
DPRINTK("Stopping queue\n");
netif_stop_queue(dev); /* can't transmit any more */
@@ -376,7 +376,7 @@ static void meth_rx(struct net_device* dev, unsigned long int_status)
{
struct sk_buff *skb;
unsigned long status;
- struct meth_private *priv = (struct meth_private *) dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
unsigned long fifo_rptr = (int_status & METH_INT_RX_RPTR_MASK) >> 8;
spin_lock(&priv->meth_lock);
@@ -466,14 +466,14 @@ static void meth_rx(struct net_device* dev, unsigned long int_status)
static int meth_tx_full(struct net_device *dev)
{
- struct meth_private *priv = (struct meth_private *) dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
return (priv->tx_count >= TX_RING_ENTRIES - 1);
}
static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status)
{
- struct meth_private *priv = dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
unsigned long status;
struct sk_buff *skb;
unsigned long rptr = (int_status&TX_INFO_RPTR) >> 16;
@@ -536,7 +536,7 @@ static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status)
static void meth_error(struct net_device* dev, unsigned status)
{
- struct meth_private *priv = (struct meth_private *) dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
printk(KERN_WARNING "meth: error status: 0x%08x\n",status);
/* check for errors too... */
@@ -570,7 +570,7 @@ static void meth_error(struct net_device* dev, unsigned status)
static irqreturn_t meth_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
- struct meth_private *priv = (struct meth_private *) dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
unsigned long status;
status = mace->eth.int_stat;
@@ -695,7 +695,7 @@ static void meth_add_to_tx_ring(struct meth_private *priv, struct sk_buff *skb)
*/
static int meth_tx(struct sk_buff *skb, struct net_device *dev)
{
- struct meth_private *priv = (struct meth_private *) dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&priv->meth_lock, flags);
@@ -726,7 +726,7 @@ static int meth_tx(struct sk_buff *skb, struct net_device *dev)
*/
static void meth_tx_timeout(struct net_device *dev)
{
- struct meth_private *priv = (struct meth_private *) dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
unsigned long flags;
printk(KERN_WARNING "%s: transmit timed out\n", dev->name);
@@ -778,7 +778,7 @@ static int meth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
*/
static struct net_device_stats *meth_stats(struct net_device *dev)
{
- struct meth_private *priv = (struct meth_private *) dev->priv;
+ struct meth_private *priv = netdev_priv(dev);
return &priv->stats;
}
@@ -807,7 +807,7 @@ static struct net_device *meth_init(void)
dev->irq = MACE_ETHERNET_IRQ;
dev->base_addr = (unsigned long)&mace->eth;
- priv = (struct meth_private *) dev->priv;
+ priv = netdev_priv(dev);
spin_lock_init(&priv->meth_lock);
ret = register_netdev(dev);
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 3f3896e9887..2807ef400fb 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -252,7 +252,7 @@ typedef u32 netxen_ctx_msg;
#define netxen_set_msg_ctxid(config_word, val) \
((config_word) &= ~(0x3ff<<18), (config_word) |= (val & 0x3ff) << 18)
#define netxen_set_msg_opcode(config_word, val) \
- ((config_word) &= ~(0xf<<24), (config_word) |= (val & 0xf) << 24)
+ ((config_word) &= ~(0xf<<28), (config_word) |= (val & 0xf) << 28)
struct netxen_rcv_context {
__le64 rcv_ring_addr;
@@ -303,14 +303,14 @@ struct netxen_ring_ctx {
(cmd_desc)->flags_opcode |= cpu_to_le16((val) & 0x7f))
#define netxen_set_cmd_desc_opcode(cmd_desc, val) \
((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x3f<<7), \
- (cmd_desc)->flags_opcode |= cpu_to_le16((val) & (0x3f<<7)))
+ (cmd_desc)->flags_opcode |= cpu_to_le16(((val & 0x3f)<<7)))
#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \
((cmd_desc)->num_of_buffers_total_length &= ~cpu_to_le32(0xff), \
(cmd_desc)->num_of_buffers_total_length |= cpu_to_le32((val) & 0xff))
#define netxen_set_cmd_desc_totallength(cmd_desc, val) \
- ((cmd_desc)->num_of_buffers_total_length &= cpu_to_le32(0xff), \
- (cmd_desc)->num_of_buffers_total_length |= cpu_to_le32(val << 24))
+ ((cmd_desc)->num_of_buffers_total_length &= ~cpu_to_le32(0xffffff00), \
+ (cmd_desc)->num_of_buffers_total_length |= cpu_to_le32(val << 8))
#define netxen_get_cmd_desc_opcode(cmd_desc) \
((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003F)
@@ -1040,6 +1040,7 @@ int netxen_flash_unlock(struct netxen_adapter *adapter);
int netxen_backup_crbinit(struct netxen_adapter *adapter);
int netxen_flash_erase_secondary(struct netxen_adapter *adapter);
int netxen_flash_erase_primary(struct netxen_adapter *adapter);
+void netxen_halt_pegs(struct netxen_adapter *adapter);
int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data);
int netxen_rom_se(struct netxen_adapter *adapter, int addr);
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index cc0efe213e0..6252e9a8727 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -402,7 +402,7 @@ netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
wol->wolopts = 0;
}
-static u32 netxen_nic_get_link(struct net_device *dev)
+static u32 netxen_nic_test_link(struct net_device *dev)
{
struct netxen_port *port = netdev_priv(dev);
struct netxen_adapter *adapter = port->adapter;
@@ -459,6 +459,7 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
int ret;
if (flash_start == 0) {
+ netxen_halt_pegs(adapter);
ret = netxen_flash_unlock(adapter);
if (ret < 0) {
printk(KERN_ERR "%s: Flash unlock failed.\n",
@@ -712,7 +713,7 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
{
if (eth_test->flags == ETH_TEST_FL_OFFLINE) { /* offline tests */
/* link test */
- if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+ if (!(data[4] = (u64) netxen_nic_test_link(dev)))
eth_test->flags |= ETH_TEST_FL_FAILED;
if (netif_running(dev))
@@ -727,7 +728,7 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
dev->open(dev);
} else { /* online tests */
/* link test */
- if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+ if (!(data[4] = (u64) netxen_nic_test_link(dev)))
eth_test->flags |= ETH_TEST_FL_FAILED;
/* other tests pass by default */
@@ -783,7 +784,7 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
.get_regs_len = netxen_nic_get_regs_len,
.get_regs = netxen_nic_get_regs,
.get_wol = netxen_nic_get_wol,
- .get_link = netxen_nic_get_link,
+ .get_link = ethtool_op_get_link,
.get_eeprom_len = netxen_nic_get_eeprom_len,
.get_eeprom = netxen_nic_get_eeprom,
.set_eeprom = netxen_nic_set_eeprom,
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index f263232f499..7195af3e8f3 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -420,6 +420,7 @@ static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
for (i = 0; i < size / sizeof(u32); i++) {
if (netxen_rom_fast_read(adapter, addr, ptr32) == -1)
return -1;
+ *ptr32 = cpu_to_le32(*ptr32);
ptr32++;
addr += sizeof(u32);
}
@@ -428,6 +429,7 @@ static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
if (netxen_rom_fast_read(adapter, addr, &local) == -1)
return -1;
+ local = cpu_to_le32(local);
memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);
}
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index f7bb8c90537..2f324366784 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -717,6 +717,14 @@ netxen_flash_erase_primary(struct netxen_adapter *adapter)
return ret;
}
+void netxen_halt_pegs(struct netxen_adapter *adapter)
+{
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x3c, 1);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x3c, 1);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x3c, 1);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x3c, 1);
+}
+
int netxen_flash_unlock(struct netxen_adapter *adapter)
{
int ret = 0;
@@ -1246,7 +1254,7 @@ int netxen_process_cmd_ring(unsigned long data)
* the netdev which is associated with that device.
*/
- consumer = *(adapter->cmd_consumer);
+ consumer = le32_to_cpu(*(adapter->cmd_consumer));
if (last_consumer == consumer) { /* Ring is empty */
DPRINTK(INFO, "last_consumer %d == consumer %d\n",
last_consumer, consumer);
@@ -1340,7 +1348,7 @@ int netxen_process_cmd_ring(unsigned long data)
if (adapter->last_cmd_consumer == consumer &&
(((adapter->cmd_producer + 1) %
adapter->max_tx_desc_count) == adapter->last_cmd_consumer)) {
- consumer = *(adapter->cmd_consumer);
+ consumer = le32_to_cpu(*(adapter->cmd_consumer));
}
done = (adapter->last_cmd_consumer == consumer);
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 36ba6a1aa36..225ff55527c 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -434,12 +434,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->port_count++;
adapter->port[i] = port;
}
-
+#ifndef CONFIG_PPC64
writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
netxen_pinit_from_rom(adapter, 0);
udelay(500);
netxen_load_firmware(adapter);
netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+#endif
/*
* delay a while to ensure that the Pegs are up & running.
* Otherwise, we might see some flaky behaviour.
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index 40d7003a371..d5d95074e56 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -458,7 +458,7 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
{
- long reg = 0, ret = 0;
+ u32 reg = 0, ret = 0;
if (adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) {
netxen_crb_writelit_adapter(adapter,
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 448bf4a7801..c7bd9c1c7f3 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -915,7 +915,7 @@ static void media_check(unsigned long arg)
if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) {
if (!lp->fast_poll)
printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
- el3_interrupt(dev->irq, lp);
+ el3_interrupt(dev->irq, dev);
lp->fast_poll = HZ;
}
if (lp->fast_poll) {
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 530df8883fe..2561f76033e 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -1927,7 +1927,7 @@ static void media_check(u_long arg)
if (smc->watchdog++ && ((i>>8) & i)) {
if (!smc->fast_poll)
printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
- smc_interrupt(dev->irq, smc);
+ smc_interrupt(dev->irq, dev);
smc->fast_poll = HZ;
}
if (smc->fast_poll) {
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index f4d4eb659ca..22aec5cce68 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -42,6 +42,19 @@
#define MII_M1011_IMASK_INIT 0x6400
#define MII_M1011_IMASK_CLEAR 0x0000
+#define MII_M1011_PHY_SCR 0x10
+#define MII_M1011_PHY_SCR_AUTO_CROSS 0x0060
+
+#define MII_M1145_PHY_EXT_CR 0x14
+#define MII_M1145_RGMII_RX_DELAY 0x0080
+#define MII_M1145_RGMII_TX_DELAY 0x0002
+
+#define M1145_DEV_FLAGS_RESISTANCE 0x00000001
+
+#define MII_M1111_PHY_LED_CONTROL 0x18
+#define MII_M1111_PHY_LED_DIRECT 0x4100
+#define MII_M1111_PHY_LED_COMBINE 0x411c
+
MODULE_DESCRIPTION("Marvell PHY driver");
MODULE_AUTHOR("Andy Fleming");
MODULE_LICENSE("GPL");
@@ -63,7 +76,7 @@ static int marvell_config_intr(struct phy_device *phydev)
{
int err;
- if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
else
err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
@@ -103,34 +116,153 @@ static int marvell_config_aneg(struct phy_device *phydev)
if (err < 0)
return err;
+ err = phy_write(phydev, MII_M1011_PHY_SCR,
+ MII_M1011_PHY_SCR_AUTO_CROSS);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
+ MII_M1111_PHY_LED_DIRECT);
+ if (err < 0)
+ return err;
err = genphy_config_aneg(phydev);
return err;
}
+static int m88e1145_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ /* Take care of errata E0 & E1 */
+ err = phy_write(phydev, 0x1d, 0x001b);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0x418f);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1d, 0x0016);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0xa2da);
+ if (err < 0)
+ return err;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
+ int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR);
+ if (temp < 0)
+ return temp;
+
+ temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY);
+
+ err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp);
+ if (err < 0)
+ return err;
+
+ if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) {
+ err = phy_write(phydev, 0x1d, 0x0012);
+ if (err < 0)
+ return err;
+
+ temp = phy_read(phydev, 0x1e);
+ if (temp < 0)
+ return temp;
+
+ temp &= 0xf03f;
+ temp |= 2 << 9; /* 36 ohm */
+ temp |= 2 << 6; /* 39 ohm */
+
+ err = phy_write(phydev, 0x1e, temp);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1d, 0x3);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, 0x1e, 0x8000);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
static struct phy_driver m88e1101_driver = {
- .phy_id = 0x01410c00,
- .phy_id_mask = 0xffffff00,
- .name = "Marvell 88E1101",
- .features = PHY_GBIT_FEATURES,
- .flags = PHY_HAS_INTERRUPT,
- .config_aneg = &marvell_config_aneg,
- .read_status = &genphy_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
- .driver = { .owner = THIS_MODULE,},
+ .phy_id = 0x01410c60,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1101",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+};
+
+static struct phy_driver m88e1111s_driver = {
+ .phy_id = 0x01410cc0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1111",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+};
+
+static struct phy_driver m88e1145_driver = {
+ .phy_id = 0x01410cd0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1145",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1145_config_init,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
};
static int __init marvell_init(void)
{
- return phy_driver_register(&m88e1101_driver);
+ int ret;
+
+ ret = phy_driver_register(&m88e1101_driver);
+ if (ret)
+ return ret;
+
+ ret = phy_driver_register(&m88e1111s_driver);
+ if (ret)
+ goto err1111s;
+
+ ret = phy_driver_register(&m88e1145_driver);
+ if (ret)
+ goto err1145;
+
+ return 0;
+
+ err1145:
+ phy_driver_unregister(&m88e1111s_driver);
+ err1111s:
+ phy_driver_unregister(&m88e1101_driver);
+ return ret;
}
static void __exit marvell_exit(void)
{
phy_driver_unregister(&m88e1101_driver);
+ phy_driver_unregister(&m88e1111s_driver);
+ phy_driver_unregister(&m88e1145_driver);
}
module_init(marvell_init);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index fdf45fdb673..7d5b6d1838c 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -138,7 +138,7 @@ void phy_prepare_link(struct phy_device *phydev,
*/
struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
void (*handler)(struct net_device *), u32 flags,
- u32 interface)
+ phy_interface_t interface)
{
struct phy_device *phydev;
@@ -187,7 +187,7 @@ static int phy_compare_id(struct device *dev, void *data)
}
struct phy_device *phy_attach(struct net_device *dev,
- const char *phy_id, u32 flags, u32 interface)
+ const char *phy_id, u32 flags, phy_interface_t interface)
{
struct bus_type *bus = &mdio_bus_type;
struct phy_device *phydev;
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 92d11b961db..e94ab256b54 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -5188,6 +5188,9 @@ static struct pci_driver skge_driver = {
static int __init skge_init(void)
{
+ printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver"
+ " and is scheduled for removal\n");
+
return pci_register_driver(&skge_driver);
}
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index f2ab3d56e56..52edbd7ac17 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -49,7 +49,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.12"
+#define DRV_VERSION "1.13"
#define PFX DRV_NAME " "
/*
@@ -1742,13 +1742,6 @@ static void sky2_link_down(struct sky2_port *sky2)
reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
gma_write16(hw, port, GM_GP_CTRL, reg);
- if (sky2->flow_status == FC_RX) {
- /* restore Asymmetric Pause bit */
- gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
- gm_phy_read(hw, port, PHY_MARV_AUNE_ADV)
- | PHY_M_AN_ASP);
- }
-
netif_carrier_off(sky2->netdev);
netif_stop_queue(sky2->netdev);
@@ -1773,10 +1766,10 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
{
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
- u16 lpa;
+ u16 advert, lpa;
+ advert = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV);
lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP);
-
if (lpa & PHY_M_AN_RF) {
printk(KERN_ERR PFX "%s: remote fault", sky2->netdev->name);
return -1;
@@ -1791,20 +1784,40 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
sky2->speed = sky2_phy_speed(hw, aux);
sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
- /* Pause bits are offset (9..8) */
- if (hw->chip_id == CHIP_ID_YUKON_XL
- || hw->chip_id == CHIP_ID_YUKON_EC_U
- || hw->chip_id == CHIP_ID_YUKON_EX)
- aux >>= 6;
-
- sky2->flow_status = sky2_flow(aux & PHY_M_PS_RX_P_EN,
- aux & PHY_M_PS_TX_P_EN);
+ /* Since the pause result bits seem to in different positions on
+ * different chips. look at registers.
+ */
+ if (!sky2_is_copper(hw)) {
+ /* Shift for bits in fiber PHY */
+ advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM);
+ lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM);
+
+ if (advert & ADVERTISE_1000XPAUSE)
+ advert |= ADVERTISE_PAUSE_CAP;
+ if (advert & ADVERTISE_1000XPSE_ASYM)
+ advert |= ADVERTISE_PAUSE_ASYM;
+ if (lpa & LPA_1000XPAUSE)
+ lpa |= LPA_PAUSE_CAP;
+ if (lpa & LPA_1000XPAUSE_ASYM)
+ lpa |= LPA_PAUSE_ASYM;
+ }
+
+ sky2->flow_status = FC_NONE;
+ if (advert & ADVERTISE_PAUSE_CAP) {
+ if (lpa & LPA_PAUSE_CAP)
+ sky2->flow_status = FC_BOTH;
+ else if (advert & ADVERTISE_PAUSE_ASYM)
+ sky2->flow_status = FC_RX;
+ } else if (advert & ADVERTISE_PAUSE_ASYM) {
+ if ((lpa & LPA_PAUSE_CAP) && (lpa & LPA_PAUSE_ASYM))
+ sky2->flow_status = FC_TX;
+ }
if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000
&& !(hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX))
sky2->flow_status = FC_NONE;
- if (aux & PHY_M_PS_RX_P_EN)
+ if (sky2->flow_status & FC_TX)
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
else
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
@@ -1853,16 +1866,13 @@ out:
spin_unlock(&sky2->phy_lock);
}
-
/* Transmit timeout is only called if we are running, carrier is up
* and tx queue is full (stopped).
- * Called with netif_tx_lock held.
*/
static void sky2_tx_timeout(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
struct sky2_hw *hw = sky2->hw;
- u32 imask;
if (netif_msg_timer(sky2))
printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
@@ -1872,19 +1882,8 @@ static void sky2_tx_timeout(struct net_device *dev)
sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE)));
- imask = sky2_read32(hw, B0_IMSK); /* block IRQ in hw */
- sky2_write32(hw, B0_IMSK, 0);
- sky2_read32(hw, B0_IMSK);
-
- netif_poll_disable(hw->dev[0]); /* stop NAPI poll */
- synchronize_irq(hw->pdev->irq);
-
- netif_start_queue(dev); /* don't wakeup during flush */
- sky2_tx_complete(sky2, sky2->tx_prod); /* Flush transmit queue */
-
- sky2_write32(hw, B0_IMSK, imask);
-
- sky2_phy_reinit(sky2); /* this clears flow control etc */
+ /* can't restart safely under softirq */
+ schedule_work(&hw->restart_work);
}
static int sky2_change_mtu(struct net_device *dev, int new_mtu)
@@ -2057,9 +2056,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
if (!(status & GMR_FS_RX_OK))
goto resubmit;
- if (length > dev->mtu + ETH_HLEN)
- goto oversize;
-
if (length < copybreak)
skb = receive_copy(sky2, re, length);
else
@@ -2069,14 +2065,10 @@ resubmit:
return skb;
-oversize:
- ++sky2->net_stats.rx_over_errors;
- goto resubmit;
-
error:
++sky2->net_stats.rx_errors;
if (status & GMR_FS_RX_FF_OV) {
- sky2->net_stats.rx_fifo_errors++;
+ sky2->net_stats.rx_over_errors++;
goto resubmit;
}
@@ -2638,6 +2630,49 @@ static void sky2_reset(struct sky2_hw *hw)
sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
}
+static void sky2_restart(struct work_struct *work)
+{
+ struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work);
+ struct net_device *dev;
+ int i, err;
+
+ dev_dbg(&hw->pdev->dev, "restarting\n");
+
+ del_timer_sync(&hw->idle_timer);
+
+ rtnl_lock();
+ sky2_write32(hw, B0_IMSK, 0);
+ sky2_read32(hw, B0_IMSK);
+
+ netif_poll_disable(hw->dev[0]);
+
+ for (i = 0; i < hw->ports; i++) {
+ dev = hw->dev[i];
+ if (netif_running(dev))
+ sky2_down(dev);
+ }
+
+ sky2_reset(hw);
+ sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+ netif_poll_enable(hw->dev[0]);
+
+ for (i = 0; i < hw->ports; i++) {
+ dev = hw->dev[i];
+ if (netif_running(dev)) {
+ err = sky2_up(dev);
+ if (err) {
+ printk(KERN_INFO PFX "%s: could not restart %d\n",
+ dev->name, err);
+ dev_close(dev);
+ }
+ }
+ }
+
+ sky2_idle_start(hw);
+
+ rtnl_unlock();
+}
+
static inline u8 sky2_wol_supported(const struct sky2_hw *hw)
{
return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0;
@@ -3600,6 +3635,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
}
setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw);
+ INIT_WORK(&hw->restart_work, sky2_restart);
+
sky2_idle_start(hw);
pci_set_drvdata(pdev, hw);
@@ -3636,6 +3673,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
del_timer_sync(&hw->idle_timer);
+ flush_scheduled_work();
+
sky2_write32(hw, B0_IMSK, 0);
synchronize_irq(hw->pdev->irq);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 3b0189569d5..ac24bdc4297 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1589,7 +1589,7 @@ enum {
GMR_FS_ANY_ERR = GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR |
GMR_FS_FRAGMENT | GMR_FS_LONG_ERR |
- GMR_FS_MII_ERR | GMR_FS_GOOD_FC | GMR_FS_BAD_FC |
+ GMR_FS_MII_ERR | GMR_FS_BAD_FC |
GMR_FS_UN_SIZE | GMR_FS_JABBER,
};
@@ -1933,6 +1933,7 @@ struct sky2_hw {
dma_addr_t st_dma;
struct timer_list idle_timer;
+ struct work_struct restart_work;
int msi;
wait_queue_head_t msi_wait;
};
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 61708cf4c85..8897f538a7c 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -26,7 +26,7 @@ config WAN
# There is no way to detect a comtrol sv11 - force it modular for now.
config HOSTESS_SV11
tristate "Comtrol Hostess SV-11 support"
- depends on WAN && ISA && m && ISA_DMA_API
+ depends on WAN && ISA && m && ISA_DMA_API && INET
help
Driver for Comtrol Hostess SV-11 network card which
operates on low speed synchronous serial links at up to
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index bc156b51678..aff05dba720 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -542,7 +542,7 @@ static int __init pc300_init_module(void)
CLOCK_BASE = use_crystal_clock ? 24576000 : pci_clock_freq;
- return pci_module_init(&pc300_pci_driver);
+ return pci_register_driver(&pc300_pci_driver);
}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 3a064def162..0e790efae68 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -771,6 +771,7 @@ struct bcm43xx_private {
* This is currently always BCM43xx_BUSTYPE_PCI
*/
u8 bustype;
+ u64 dma_mask;
u16 board_vendor;
u16 board_type;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index 978ed099e28..6e0dc76400e 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -145,16 +145,14 @@ dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
int tx)
{
dma_addr_t dmaaddr;
+ int direction = PCI_DMA_FROMDEVICE;
- if (tx) {
- dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
- buf, len,
- DMA_TO_DEVICE);
- } else {
- dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+ if (tx)
+ direction = PCI_DMA_TODEVICE;
+
+ dmaaddr = pci_map_single(ring->bcm->pci_dev,
buf, len,
- DMA_FROM_DEVICE);
- }
+ direction);
return dmaaddr;
}
@@ -166,13 +164,13 @@ void unmap_descbuffer(struct bcm43xx_dmaring *ring,
int tx)
{
if (tx) {
- dma_unmap_single(&ring->bcm->pci_dev->dev,
+ pci_unmap_single(ring->bcm->pci_dev,
addr, len,
- DMA_TO_DEVICE);
+ PCI_DMA_TODEVICE);
} else {
- dma_unmap_single(&ring->bcm->pci_dev->dev,
+ pci_unmap_single(ring->bcm->pci_dev,
addr, len,
- DMA_FROM_DEVICE);
+ PCI_DMA_FROMDEVICE);
}
}
@@ -183,8 +181,8 @@ void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
{
assert(!ring->tx);
- dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev,
- addr, len, DMA_FROM_DEVICE);
+ pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+ addr, len, PCI_DMA_FROMDEVICE);
}
static inline
@@ -194,8 +192,8 @@ void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
{
assert(!ring->tx);
- dma_sync_single_for_device(&ring->bcm->pci_dev->dev,
- addr, len, DMA_FROM_DEVICE);
+ pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
+ addr, len, PCI_DMA_TODEVICE);
}
/* Unmap and free a descriptor buffer. */
@@ -214,17 +212,53 @@ void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
{
- struct device *dev = &(ring->bcm->pci_dev->dev);
-
- ring->descbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
- &(ring->dmabase), GFP_KERNEL);
+ ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE,
+ &(ring->dmabase));
if (!ring->descbase) {
- printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
- return -ENOMEM;
+ /* Allocation may have failed due to pci_alloc_consistent
+ insisting on use of GFP_DMA, which is more restrictive
+ than necessary... */
+ struct dma_desc *rx_ring;
+ dma_addr_t rx_ring_dma;
+
+ rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL);
+ if (!rx_ring)
+ goto out_err;
+
+ rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring,
+ BCM43xx_DMA_RINGMEMSIZE,
+ PCI_DMA_BIDIRECTIONAL);
+
+ if (pci_dma_mapping_error(rx_ring_dma) ||
+ rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+ /* Sigh... */
+ if (!pci_dma_mapping_error(rx_ring_dma))
+ pci_unmap_single(ring->bcm->pci_dev,
+ rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+ PCI_DMA_BIDIRECTIONAL);
+ rx_ring_dma = pci_map_single(ring->bcm->pci_dev,
+ rx_ring, BCM43xx_DMA_RINGMEMSIZE,
+ PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(rx_ring_dma) ||
+ rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
+ assert(0);
+ if (!pci_dma_mapping_error(rx_ring_dma))
+ pci_unmap_single(ring->bcm->pci_dev,
+ rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
+ PCI_DMA_BIDIRECTIONAL);
+ goto out_err;
+ }
+ }
+
+ ring->descbase = rx_ring;
+ ring->dmabase = rx_ring_dma;
}
memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
return 0;
+out_err:
+ printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
+ return -ENOMEM;
}
static void free_ringmemory(struct bcm43xx_dmaring *ring)
@@ -407,6 +441,29 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
if (unlikely(!skb))
return -ENOMEM;
dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+ /* This hardware bug work-around adapted from the b44 driver.
+ The chip may be unable to do PCI DMA to/from anything above 1GB */
+ if (pci_dma_mapping_error(dmaaddr) ||
+ dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+ /* This one has 30-bit addressing... */
+ if (!pci_dma_mapping_error(dmaaddr))
+ pci_unmap_single(ring->bcm->pci_dev,
+ dmaaddr, ring->rx_buffersize,
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb_any(skb);
+ skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA);
+ if (skb == NULL)
+ return -ENOMEM;
+ dmaaddr = pci_map_single(ring->bcm->pci_dev,
+ skb->data, ring->rx_buffersize,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(dmaaddr) ||
+ dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
+ assert(0);
+ dev_kfree_skb_any(skb);
+ return -ENOMEM;
+ }
+ }
meta->skb = skb;
meta->dmaaddr = dmaaddr;
skb->dev = ring->bcm->net_dev;
@@ -636,8 +693,10 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
err = dmacontroller_setup(ring);
if (err)
goto err_free_ringmemory;
+ return ring;
out:
+ printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n");
return ring;
err_free_ringmemory:
@@ -705,30 +764,16 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
struct bcm43xx_dmaring *ring;
int err = -ENOMEM;
int dma64 = 0;
- u64 mask = bcm43xx_get_supported_dma_mask(bcm);
- int nobits;
- if (mask == DMA_64BIT_MASK) {
+ bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm);
+ if (bcm->dma_mask == DMA_64BIT_MASK)
dma64 = 1;
- nobits = 64;
- } else if (mask == DMA_32BIT_MASK)
- nobits = 32;
- else
- nobits = 30;
- err = pci_set_dma_mask(bcm->pci_dev, mask);
- err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask);
- if (err) {
-#ifdef CONFIG_BCM43XX_PIO
- printk(KERN_WARNING PFX "DMA not supported on this device."
- " Falling back to PIO.\n");
- bcm->__using_pio = 1;
- return -ENOSYS;
-#else
- printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
- "Please recompile the driver with PIO support.\n");
- return -ENODEV;
-#endif /* CONFIG_BCM43XX_PIO */
- }
+ err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask);
+ if (err)
+ goto no_dma;
+ err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask);
+ if (err)
+ goto no_dma;
/* setup TX DMA channels. */
ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
@@ -774,7 +819,9 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm)
dma->rx_ring3 = ring;
}
- dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits);
+ dprintk(KERN_INFO PFX "%d-bit DMA initialized\n",
+ (bcm->dma_mask == DMA_64BIT_MASK) ? 64 :
+ (bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30);
err = 0;
out:
return err;
@@ -800,7 +847,17 @@ err_destroy_tx1:
err_destroy_tx0:
bcm43xx_destroy_dmaring(dma->tx_ring0);
dma->tx_ring0 = NULL;
- goto out;
+no_dma:
+#ifdef CONFIG_BCM43XX_PIO
+ printk(KERN_WARNING PFX "DMA not supported on this device."
+ " Falling back to PIO.\n");
+ bcm->__using_pio = 1;
+ return -ENOSYS;
+#else
+ printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
+ "Please recompile the driver with PIO support.\n");
+ return -ENODEV;
+#endif /* CONFIG_BCM43XX_PIO */
}
/* Generate a cookie for the TX header. */
@@ -905,6 +962,7 @@ static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
struct bcm43xx_dmadesc_generic *desc;
struct bcm43xx_dmadesc_meta *meta;
dma_addr_t dmaaddr;
+ struct sk_buff *bounce_skb;
assert(skb_shinfo(skb)->nr_frags == 0);
@@ -924,9 +982,28 @@ static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
skb->len - sizeof(struct bcm43xx_txhdr),
(cur_frag == 0),
generate_cookie(ring, slot));
+ dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+ if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+ /* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */
+ if (!dma_mapping_error(dmaaddr))
+ unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+ bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA);
+ if (!bounce_skb)
+ return;
+ dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1);
+ if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
+ if (!dma_mapping_error(dmaaddr))
+ unmap_descbuffer(ring, dmaaddr, skb->len, 1);
+ dev_kfree_skb_any(bounce_skb);
+ assert(0);
+ return;
+ }
+ memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+ dev_kfree_skb_any(skb);
+ skb = bounce_skb;
+ }
meta->skb = skb;
- dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
meta->dmaaddr = dmaaddr;
fill_descriptor(ring, desc, dmaaddr,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 23aaf1ed854..2e400aacc43 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -95,13 +95,9 @@ static int modparam_noleds;
module_param_named(noleds, modparam_noleds, int, 0444);
MODULE_PARM_DESC(noleds, "Turn off all LED activity");
-#ifdef CONFIG_BCM43XX_DEBUG
static char modparam_fwpostfix[64];
module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
-MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
-#else
-# define modparam_fwpostfix ""
-#endif /* CONFIG_BCM43XX_DEBUG*/
+MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions.");
/* If you want to debug with just a single device, enable this,
@@ -2983,8 +2979,10 @@ static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm)
err = bcm43xx_pctl_set_crystal(bcm, 1);
if (err)
goto out;
- bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
- bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
+ err = bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
+ if (err)
+ goto out;
+ err = bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
out:
return err;
@@ -3796,12 +3794,18 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
}
net_dev->base_addr = (unsigned long)bcm->mmio_addr;
- bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
+ err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
&bcm->board_vendor);
- bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
+ if (err)
+ goto err_iounmap;
+ err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
&bcm->board_type);
- bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
+ if (err)
+ goto err_iounmap;
+ err = bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
&bcm->board_revision);
+ if (err)
+ goto err_iounmap;
err = bcm43xx_chipset_attach(bcm);
if (err)
@@ -3892,6 +3896,7 @@ err_pci_release:
pci_release_regions(pci_dev);
err_pci_disable:
pci_disable_device(pci_dev);
+ printk(KERN_ERR PFX "Unable to attach board\n");
goto out;
}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index d2ca949174f..7b665e2386a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -260,22 +260,22 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
if (phy->type == BCM43xx_PHYTYPE_A ||
phy->type == BCM43xx_PHYTYPE_G) {
range->num_bitrates = 8;
- range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB;
- range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB;
- range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB;
- range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB;
- range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB;
- range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB;
- range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB;
- range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000;
+ range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000;
}
if (phy->type == BCM43xx_PHYTYPE_B ||
phy->type == BCM43xx_PHYTYPE_G) {
range->num_bitrates += 4;
- range->bitrate[i++] = IEEE80211_CCK_RATE_1MB;
- range->bitrate[i++] = IEEE80211_CCK_RATE_2MB;
- range->bitrate[i++] = IEEE80211_CCK_RATE_5MB;
- range->bitrate[i++] = IEEE80211_CCK_RATE_11MB;
+ range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000;
+ range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000;
+ range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000;
+ range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000;
}
geo = ieee80211_get_geo(bcm->ieee);
@@ -285,7 +285,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
if (j == IW_MAX_FREQUENCIES)
break;
range->freq[j].i = j + 1;
- range->freq[j].m = geo->a[i].freq;//FIXME?
+ range->freq[j].m = geo->a[i].freq * 100000;
range->freq[j].e = 1;
j++;
}
@@ -293,7 +293,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
if (j == IW_MAX_FREQUENCIES)
break;
range->freq[j].i = j + 1;
- range->freq[j].m = geo->bg[i].freq;//FIXME?
+ range->freq[j].m = geo->bg[i].freq * 100000;
range->freq[j].e = 1;
j++;
}
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index b85857a8487..d0639a45cd2 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -175,7 +175,7 @@ that only one external action is invoked at a time.
/* Debugging stuff */
#ifdef CONFIG_IPW2100_DEBUG
-#define CONFIG_IPW2100_RX_DEBUG /* Reception debugging */
+#define IPW2100_RX_DEBUG /* Reception debugging */
#endif
MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -2239,7 +2239,7 @@ static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
priv->snapshot[0] = NULL;
}
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
{
int i;
@@ -2314,13 +2314,13 @@ static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
* The size of the constructed ethernet
*
*/
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
#endif
static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
{
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
struct ipw2100_status *status = &priv->status_queue.drv[i];
u32 match, reg;
int j;
@@ -2342,7 +2342,7 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
}
#endif
-#ifdef CONFIG_IPW2100_DEBUG_C3
+#ifdef IPW2100_DEBUG_C3
/* Halt the fimrware so we can get a good image */
write_register(priv->net_dev, IPW_REG_RESET_REG,
IPW_AUX_HOST_RESET_REG_STOP_MASTER);
@@ -2413,7 +2413,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
skb_put(packet->skb, status->frame_size);
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
/* Make a copy of the frame so we can dump it to the logs if
* ieee80211_rx fails */
memcpy(packet_data, packet->skb->data,
@@ -2421,7 +2421,7 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
#endif
if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
-#ifdef CONFIG_IPW2100_RX_DEBUG
+#ifdef IPW2100_RX_DEBUG
IPW_DEBUG_DROP("%s: Non consumed packet:\n",
priv->net_dev->name);
printk_buf(IPW_DL_DROP, packet_data, status->frame_size);
@@ -4912,7 +4912,7 @@ static int ipw2100_set_power_mode(struct ipw2100_priv *priv, int power_level)
else
priv->power_mode = IPW_POWER_ENABLED | power_level;
-#ifdef CONFIG_IPW2100_TX_POWER
+#ifdef IPW2100_TX_POWER
if (priv->port_type == IBSS && priv->adhoc_power != DFTL_IBSS_TX_POWER) {
/* Set beacon interval */
cmd.host_command = TX_POWER_INDEX;
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index a08524191b5..4c5f78eac34 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -156,7 +156,7 @@ void zd_mac_clear(struct zd_mac *mac)
static int reset_mode(struct zd_mac *mac)
{
struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
- struct zd_ioreq32 ioreqs[3] = {
+ struct zd_ioreq32 ioreqs[] = {
{ CR_RX_FILTER, STA_RX_FILTER },
{ CR_SNIFFER_ON, 0U },
};
@@ -164,10 +164,9 @@ static int reset_mode(struct zd_mac *mac)
if (ieee->iw_mode == IW_MODE_MONITOR) {
ioreqs[0].value = 0xffffffff;
ioreqs[1].value = 0x1;
- ioreqs[2].value = ENC_SNIFFER;
}
- return zd_iowrite32a(&mac->chip, ioreqs, 3);
+ return zd_iowrite32a(&mac->chip, ioreqs, ARRAY_SIZE(ioreqs));
}
int zd_mac_open(struct net_device *netdev)
@@ -904,16 +903,21 @@ static int fill_ctrlset(struct zd_mac *mac,
static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri)
{
int i, r;
+ struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
for (i = 0; i < txb->nr_frags; i++) {
struct sk_buff *skb = txb->fragments[i];
r = fill_ctrlset(mac, txb, i);
- if (r)
+ if (r) {
+ ieee->stats.tx_dropped++;
return r;
+ }
r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len);
- if (r)
+ if (r) {
+ ieee->stats.tx_dropped++;
return r;
+ }
}
/* FIXME: shouldn't this be handled by the upper layers? */
@@ -1063,9 +1067,23 @@ static int fill_rx_stats(struct ieee80211_rx_stats *stats,
*pstatus = status = zd_tail(buffer, length, sizeof(struct rx_status));
if (status->frame_status & ZD_RX_ERROR) {
- /* FIXME: update? */
+ struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+ ieee->stats.rx_errors++;
+ if (status->frame_status & ZD_RX_TIMEOUT_ERROR)
+ ieee->stats.rx_missed_errors++;
+ else if (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR)
+ ieee->stats.rx_fifo_errors++;
+ else if (status->frame_status & ZD_RX_DECRYPTION_ERROR)
+ ieee->ieee_stats.rx_discards_undecryptable++;
+ else if (status->frame_status & ZD_RX_CRC32_ERROR) {
+ ieee->stats.rx_crc_errors++;
+ ieee->ieee_stats.rx_fcs_errors++;
+ }
+ else if (status->frame_status & ZD_RX_CRC16_ERROR)
+ ieee->stats.rx_crc_errors++;
return -EINVAL;
}
+
memset(stats, 0, sizeof(struct ieee80211_rx_stats));
stats->len = length - (ZD_PLCP_HEADER_SIZE + IEEE80211_FCS_LEN +
+ sizeof(struct rx_status));
@@ -1094,14 +1112,16 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
IEEE80211_FCS_LEN + sizeof(struct rx_status))
{
- dev_dbg_f(zd_mac_dev(mac), "Packet with length %u to small.\n",
- skb->len);
+ ieee->stats.rx_errors++;
+ ieee->stats.rx_length_errors++;
goto free_skb;
}
r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
if (r) {
- /* Only packets with rx errors are included here. */
+ /* Only packets with rx errors are included here.
+ * The error stats have already been set in fill_rx_stats.
+ */
goto free_skb;
}
@@ -1114,8 +1134,10 @@ static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
r = filter_rx(ieee, skb->data, skb->len, &stats);
if (r <= 0) {
- if (r < 0)
+ if (r < 0) {
+ ieee->stats.rx_errors++;
dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
+ }
goto free_skb;
}
@@ -1146,7 +1168,9 @@ int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
if (!skb) {
+ struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
+ ieee->stats.rx_dropped++;
return -ENOMEM;
}
skb_reserve(skb, sizeof(struct zd_rt_hdr));
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 75ef55624d7..aac8a1c5ba0 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -313,6 +313,12 @@ out:
static inline void handle_retry_failed_int(struct urb *urb)
{
+ struct zd_usb *usb = urb->context;
+ struct zd_mac *mac = zd_usb_to_mac(usb);
+ struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+
+ ieee->stats.tx_errors++;
+ ieee->ieee_stats.tx_retry_limit_exceeded++;
dev_dbg_f(urb_dev(urb), "retry failed interrupt\n");
}
@@ -487,6 +493,9 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
if (length < sizeof(struct rx_length_info)) {
/* It's not a complete packet anyhow. */
+ struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+ ieee->stats.rx_errors++;
+ ieee->stats.rx_length_errors++;
return;
}
length_info = (struct rx_length_info *)
@@ -923,6 +932,8 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
goto error;
}
+ usb_reset_device(interface_to_usbdev(intf));
+
netdev = zd_netdev_alloc(intf);
if (netdev == NULL) {
r = -ENOMEM;
@@ -1024,6 +1035,7 @@ static int __init usb_init(void)
r = usb_register(&driver);
if (r) {
+ destroy_workqueue(zd_workqueue);
printk(KERN_ERR "%s usb_register() failed. Error number %d\n",
driver.name, r);
return r;
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 4438ae1ede4..a3c1755b2f2 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -415,6 +415,7 @@ static struct kobj_type pci_driver_kobj_type = {
* __pci_register_driver - register a new pci driver
* @drv: the driver structure to register
* @owner: owner module of drv
+ * @mod_name: module name string
*
* Adds the driver structure to the list of registered drivers.
* Returns a negative value on error, otherwise 0.
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 7a94076752d..cd913a2a416 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -143,6 +143,14 @@ static ssize_t is_enabled_show(struct device *dev,
return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt));
}
+#ifdef CONFIG_NUMA
+static ssize_t
+numa_node_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf (buf, "%d\n", dev->numa_node);
+}
+#endif
+
static ssize_t
msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -194,6 +202,9 @@ struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(irq),
__ATTR_RO(local_cpus),
__ATTR_RO(modalias),
+#ifdef CONFIG_NUMA
+ __ATTR_RO(numa_node),
+#endif
__ATTR(enable, 0600, is_enabled_show, is_enabled_store),
__ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
broken_parity_status_show,broken_parity_status_store),
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8b44cff2c17..1e74e1ee8bd 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -21,6 +21,12 @@
unsigned int pci_pm_d3_delay = 10;
+#define DEFAULT_CARDBUS_IO_SIZE (256)
+#define DEFAULT_CARDBUS_MEM_SIZE (64*1024*1024)
+/* pci=cbmemsize=nnM,cbiosize=nn can override this */
+unsigned long pci_cardbus_io_size = DEFAULT_CARDBUS_IO_SIZE;
+unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
+
/**
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
* @bus: pointer to PCI bus structure to search
@@ -1300,7 +1306,7 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
/**
* pci_select_bars - Make BAR mask from the type of resource
- * @pdev: the PCI device for which BAR mask is made
+ * @dev: the PCI device for which BAR mask is made
* @flags: resource type mask to be selected
*
* This helper routine makes bar mask from the type of resource.
@@ -1333,6 +1339,10 @@ static int __devinit pci_setup(char *str)
if (*str && (str = pcibios_setup(str)) && *str) {
if (!strcmp(str, "nomsi")) {
pci_no_msi();
+ } else if (!strncmp(str, "cbiosize=", 9)) {
+ pci_cardbus_io_size = memparse(str + 9, &str);
+ } else if (!strncmp(str, "cbmemsize=", 10)) {
+ pci_cardbus_mem_size = memparse(str + 10, &str);
} else {
printk(KERN_ERR "PCI: Unknown option `%s'\n",
str);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 89f3036f0de..3554f394881 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -36,13 +36,6 @@
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
-/*
- * FIXME: IO should be max 256 bytes. However, since we may
- * have a P2P bridge below a cardbus bridge, we need 4K.
- */
-#define CARDBUS_IO_SIZE (256)
-#define CARDBUS_MEM_SIZE (64*1024*1024)
-
static void __devinit
pbus_assign_resources_sorted(struct pci_bus *bus)
{
@@ -415,12 +408,12 @@ pci_bus_size_cardbus(struct pci_bus *bus)
* Reserve some resources for CardBus. We reserve
* a fixed amount of bus space for CardBus bridges.
*/
- b_res[0].start = CARDBUS_IO_SIZE;
- b_res[0].end = b_res[0].start + CARDBUS_IO_SIZE - 1;
+ b_res[0].start = pci_cardbus_io_size;
+ b_res[0].end = b_res[0].start + pci_cardbus_io_size - 1;
b_res[0].flags |= IORESOURCE_IO;
- b_res[1].start = CARDBUS_IO_SIZE;
- b_res[1].end = b_res[1].start + CARDBUS_IO_SIZE - 1;
+ b_res[1].start = pci_cardbus_io_size;
+ b_res[1].end = b_res[1].start + pci_cardbus_io_size - 1;
b_res[1].flags |= IORESOURCE_IO;
/*
@@ -440,16 +433,16 @@ pci_bus_size_cardbus(struct pci_bus *bus)
* twice the size.
*/
if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
- b_res[2].start = CARDBUS_MEM_SIZE;
- b_res[2].end = b_res[2].start + CARDBUS_MEM_SIZE - 1;
+ b_res[2].start = pci_cardbus_mem_size;
+ b_res[2].end = b_res[2].start + pci_cardbus_mem_size - 1;
b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
- b_res[3].start = CARDBUS_MEM_SIZE;
- b_res[3].end = b_res[3].start + CARDBUS_MEM_SIZE - 1;
+ b_res[3].start = pci_cardbus_mem_size;
+ b_res[3].end = b_res[3].start + pci_cardbus_mem_size - 1;
b_res[3].flags |= IORESOURCE_MEM;
} else {
- b_res[3].start = CARDBUS_MEM_SIZE * 2;
- b_res[3].end = b_res[3].start + CARDBUS_MEM_SIZE * 2 - 1;
+ b_res[3].start = pci_cardbus_mem_size * 2;
+ b_res[3].end = b_res[3].start + pci_cardbus_mem_size * 2 - 1;
b_res[3].flags |= IORESOURCE_MEM;
}
}
diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c
index a251289c995..568f1877315 100644
--- a/drivers/pci/setup-irq.c
+++ b/drivers/pci/setup-irq.c
@@ -24,7 +24,7 @@ pdev_fixup_irq(struct pci_dev *dev,
int (*map_irq)(struct pci_dev *, u8, u8))
{
u8 pin, slot;
- int irq;
+ int irq = 0;
/* If this device is not on the primary bus, we need to figure out
which interrupt pin it will come in on. We know which slot it
@@ -33,16 +33,18 @@ pdev_fixup_irq(struct pci_dev *dev,
apply the swizzle function. */
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
- /* Cope with 0 and illegal. */
- if (pin == 0 || pin > 4)
+ /* Cope with illegal. */
+ if (pin > 4)
pin = 1;
- /* Follow the chain of bridges, swizzling as we go. */
- slot = (*swizzle)(dev, &pin);
+ if (pin != 0) {
+ /* Follow the chain of bridges, swizzling as we go. */
+ slot = (*swizzle)(dev, &pin);
- irq = (*map_irq)(dev, slot, pin);
- if (irq == -1)
- irq = 0;
+ irq = (*map_irq)(dev, slot, pin);
+ if (irq == -1)
+ irq = 0;
+ }
dev->irq = irq;
pr_debug("PCI: fixup irq: (%s) got %d\n",
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index b3186283753..99baabc2359 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -277,7 +277,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
board->det_pin, board->irq_pin);
cf->socket.owner = THIS_MODULE;
- cf->socket.dev.dev = &pdev->dev;
+ cf->socket.dev.parent = &pdev->dev;
cf->socket.ops = &at91_cf_ops;
cf->socket.resource_ops = &pccard_static_ops;
cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index d2a3bea55de..aa7779d8975 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -478,7 +478,7 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i
*
* Returns: the number of characters added to the buffer
*/
-static ssize_t show_status(struct device *dev, char *buf)
+static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
{
struct soc_pcmcia_socket *skt =
container_of(dev, struct soc_pcmcia_socket, socket.dev);
@@ -501,7 +501,7 @@ static ssize_t show_status(struct device *dev, char *buf)
return p-buf;
}
-static CLASS_DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
static struct pccard_operations soc_common_pcmcia_operations = {
@@ -660,7 +660,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
skt->socket.ops = &soc_common_pcmcia_operations;
skt->socket.owner = ops->owner;
- skt->socket.dev.dev = dev;
+ skt->socket.dev.parent = dev;
init_timer(&skt->poll_timer);
skt->poll_timer.function = soc_common_pcmcia_poll_event;
@@ -747,7 +747,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
add_timer(&skt->poll_timer);
- device_create_file(&skt->socket.dev, &device_attr_status);
+ device_create_file(&skt->socket.dev, &dev_attr_status);
}
dev_set_drvdata(dev, sinfo);
diff --git a/drivers/pnp/pnpacpi/Kconfig b/drivers/pnp/pnpacpi/Kconfig
index ad27e5e0101..b04767ce273 100644
--- a/drivers/pnp/pnpacpi/Kconfig
+++ b/drivers/pnp/pnpacpi/Kconfig
@@ -2,17 +2,5 @@
# Plug and Play ACPI configuration
#
config PNPACPI
- bool "Plug and Play ACPI support"
- depends on PNP && ACPI
- default y
- ---help---
- Linux uses the PNPACPI to autodetect built-in
- mainboard resources (e.g. parallel port resources).
-
- Some features (e.g. real hotplug) are not currently
- implemented.
-
- If you would like the kernel to detect and allocate resources to
- your mainboard devices (on some systems they are disabled by the
- BIOS) say Y here. Also the PNPACPI can help prevent resource
- conflicts between mainboard devices and other bus devices.
+ bool
+ default (PNP && ACPI)
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile
index 96958c03cf6..e251d1c1171 100644
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_PS3_VUART) += vuart.o
obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
+obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o
diff --git a/drivers/ps3/sys-manager.c b/drivers/ps3/sys-manager.c
new file mode 100644
index 00000000000..0fc30be8b81
--- /dev/null
+++ b/drivers/ps3/sys-manager.c
@@ -0,0 +1,604 @@
+/*
+ * PS3 System Manager.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2007 Sony Corp.
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/reboot.h>
+#include <asm/ps3.h>
+#include "vuart.h"
+
+MODULE_AUTHOR("Sony Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PS3 System Manager");
+
+/**
+ * ps3_sys_manager - PS3 system manager driver.
+ *
+ * The system manager provides an asyncronous system event notification
+ * mechanism for reporting events like thermal alert and button presses to
+ * guests. It also provides support to control system shutdown and startup.
+ *
+ * The actual system manager is implemented as an application running in the
+ * system policy module in lpar_1. Guests communicate with the system manager
+ * through port 2 of the vuart using a simple packet message protocol.
+ * Messages are comprised of a fixed field header followed by a message
+ * specific payload.
+ */
+
+/**
+ * struct ps3_sys_manager_header - System manager message header.
+ * @version: Header version, currently 1.
+ * @size: Header size in bytes, curently 16.
+ * @payload_size: Message payload size in bytes.
+ * @service_id: Message type, one of enum ps3_sys_manager_service_id.
+ */
+
+struct ps3_sys_manager_header {
+ /* version 1 */
+ u8 version;
+ u8 size;
+ u16 reserved_1;
+ u32 payload_size;
+ u16 service_id;
+ u16 reserved_2[3];
+};
+
+/**
+ * @PS3_SM_RX_MSG_LEN - System manager received message length.
+ *
+ * Currently all messages received from the system manager are the same length
+ * (16 bytes header + 16 bytes payload = 32 bytes). This knowlege is used to
+ * simplify the logic.
+ */
+
+enum {
+ PS3_SM_RX_MSG_LEN = 32,
+};
+
+/**
+ * enum ps3_sys_manager_service_id - Message header service_id.
+ * @PS3_SM_SERVICE_ID_REQUEST: guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_COMMAND: guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_RESPONSE: guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_ATTR: guest --> sys_manager.
+ * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager.
+ * @PS3_SM_SERVICE_ID_SET_NEXT_OP: guest --> sys_manager.
+ */
+
+enum ps3_sys_manager_service_id {
+ /* version 1 */
+ PS3_SM_SERVICE_ID_REQUEST = 1,
+ PS3_SM_SERVICE_ID_RESPONSE = 2,
+ PS3_SM_SERVICE_ID_COMMAND = 3,
+ PS3_SM_SERVICE_ID_EXTERN_EVENT = 4,
+ PS3_SM_SERVICE_ID_SET_NEXT_OP = 5,
+ PS3_SM_SERVICE_ID_SET_ATTR = 8,
+};
+
+/**
+ * enum ps3_sys_manager_attr - Notification attribute (bit position mask).
+ * @PS3_SM_ATTR_POWER: Power button.
+ * @PS3_SM_ATTR_RESET: Reset button, not available on retail console.
+ * @PS3_SM_ATTR_THERMAL: Sytem thermal alert.
+ * @PS3_SM_ATTR_CONTROLLER: Remote controller event.
+ * @PS3_SM_ATTR_ALL: Logical OR of all.
+ *
+ * The guest tells the system manager which events it is interested in receiving
+ * notice of by sending the system manager a logical OR of notification
+ * attributes via the ps3_sys_manager_send_attr() routine.
+ */
+
+enum ps3_sys_manager_attr {
+ /* version 1 */
+ PS3_SM_ATTR_POWER = 1,
+ PS3_SM_ATTR_RESET = 2,
+ PS3_SM_ATTR_THERMAL = 4,
+ PS3_SM_ATTR_CONTROLLER = 8, /* bogus? */
+ PS3_SM_ATTR_ALL = 0x0f,
+};
+
+/**
+ * enum ps3_sys_manager_event - External event type, reported by system manager.
+ * @PS3_SM_EVENT_POWER_PRESSED: payload.value not used.
+ * @PS3_SM_EVENT_POWER_RELEASED: payload.value = time pressed in millisec.
+ * @PS3_SM_EVENT_RESET_PRESSED: payload.value not used.
+ * @PS3_SM_EVENT_RESET_RELEASED: payload.value = time pressed in millisec.
+ * @PS3_SM_EVENT_THERMAL_ALERT: payload.value = thermal zone id.
+ * @PS3_SM_EVENT_THERMAL_CLEARED: payload.value = thermal zone id.
+ */
+
+enum ps3_sys_manager_event {
+ /* version 1 */
+ PS3_SM_EVENT_POWER_PRESSED = 3,
+ PS3_SM_EVENT_POWER_RELEASED = 4,
+ PS3_SM_EVENT_RESET_PRESSED = 5,
+ PS3_SM_EVENT_RESET_RELEASED = 6,
+ PS3_SM_EVENT_THERMAL_ALERT = 7,
+ PS3_SM_EVENT_THERMAL_CLEARED = 8,
+ /* no info on controller events */
+};
+
+/**
+ * enum ps3_sys_manager_next_op - Operation to perform after lpar is destroyed.
+ */
+
+enum ps3_sys_manager_next_op {
+ /* version 3 */
+ PS3_SM_NEXT_OP_SYS_SHUTDOWN = 1,
+ PS3_SM_NEXT_OP_SYS_REBOOT = 2,
+ PS3_SM_NEXT_OP_LPAR_REBOOT = 0x82,
+};
+
+/**
+ * enum ps3_sys_manager_wake_source - Next-op wakeup source (bit position mask).
+ * @PS3_SM_WAKE_DEFAULT: Disk insert, power button, eject button, IR
+ * controller, and bluetooth controller.
+ * @PS3_SM_WAKE_RTC:
+ * @PS3_SM_WAKE_RTC_ERROR:
+ * @PS3_SM_WAKE_P_O_R: Power on reset.
+ *
+ * Additional wakeup sources when specifying PS3_SM_NEXT_OP_SYS_SHUTDOWN.
+ * System will always wake from the PS3_SM_WAKE_DEFAULT sources.
+ */
+
+enum ps3_sys_manager_wake_source {
+ /* version 3 */
+ PS3_SM_WAKE_DEFAULT = 0,
+ PS3_SM_WAKE_RTC = 0x00000040,
+ PS3_SM_WAKE_RTC_ERROR = 0x00000080,
+ PS3_SM_WAKE_P_O_R = 0x10000000,
+};
+
+/**
+ * enum ps3_sys_manager_cmd - Command from system manager to guest.
+ *
+ * The guest completes the actions needed, then acks or naks the command via
+ * ps3_sys_manager_send_response(). In the case of @PS3_SM_CMD_SHUTDOWN,
+ * the guest must be fully prepared for a system poweroff prior to acking the
+ * command.
+ */
+
+enum ps3_sys_manager_cmd {
+ /* version 1 */
+ PS3_SM_CMD_SHUTDOWN = 1, /* shutdown guest OS */
+};
+
+/**
+ * ps3_sys_manager_write - Helper to write a two part message to the vuart.
+ *
+ */
+
+static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev,
+ const struct ps3_sys_manager_header *header, const void *payload)
+{
+ int result;
+
+ BUG_ON(header->version != 1);
+ BUG_ON(header->size != 16);
+ BUG_ON(header->payload_size != 8 && header->payload_size != 16);
+ BUG_ON(header->service_id > 8);
+
+ result = ps3_vuart_write(dev, header,
+ sizeof(struct ps3_sys_manager_header));
+
+ if (!result)
+ result = ps3_vuart_write(dev, payload, header->payload_size);
+
+ return result;
+}
+
+/**
+ * ps3_sys_manager_send_attr - Send a 'set attribute' to the system manager.
+ *
+ */
+
+static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev,
+ enum ps3_sys_manager_attr attr)
+{
+ static const struct ps3_sys_manager_header header = {
+ .version = 1,
+ .size = 16,
+ .payload_size = 16,
+ .service_id = PS3_SM_SERVICE_ID_SET_ATTR,
+ };
+ struct {
+ u8 version;
+ u8 reserved_1[3];
+ u32 attribute;
+ } payload;
+
+ BUILD_BUG_ON(sizeof(payload) != 8);
+
+ dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr);
+
+ memset(&payload, 0, sizeof(payload));
+ payload.version = 1;
+ payload.attribute = attr;
+
+ return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_send_next_op - Send a 'set next op' to the system manager.
+ *
+ * Tell the system manager what to do after this lpar is destroyed.
+ */
+
+static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev,
+ enum ps3_sys_manager_next_op op,
+ enum ps3_sys_manager_wake_source wake_source)
+{
+ static const struct ps3_sys_manager_header header = {
+ .version = 1,
+ .size = 16,
+ .payload_size = 16,
+ .service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP,
+ };
+ struct {
+ u8 version;
+ u8 type;
+ u8 gos_id;
+ u8 reserved_1;
+ u32 wake_source;
+ u8 reserved_2[8];
+ } payload;
+
+ BUILD_BUG_ON(sizeof(payload) != 16);
+
+ dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op);
+
+ memset(&payload, 0, sizeof(payload));
+ payload.version = 3;
+ payload.type = op;
+ payload.gos_id = 3; /* other os */
+ payload.wake_source = wake_source;
+
+ return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_send_request_shutdown - Send 'request' to the system manager.
+ *
+ * The guest sends this message to request an operation or action of the system
+ * manager. The reply is a command message from the system manager. In the
+ * command handler the guest performs the requested operation. The result of
+ * the command is then communicated back to the system manager with a response
+ * message.
+ *
+ * Currently, the only supported request it the 'shutdown self' request.
+ */
+
+static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *dev)
+{
+ static const struct ps3_sys_manager_header header = {
+ .version = 1,
+ .size = 16,
+ .payload_size = 16,
+ .service_id = PS3_SM_SERVICE_ID_REQUEST,
+ };
+ struct {
+ u8 version;
+ u8 type;
+ u8 gos_id;
+ u8 reserved_1[13];
+ } static const payload = {
+ .version = 1,
+ .type = 1, /* shutdown */
+ .gos_id = 0, /* self */
+ };
+
+ BUILD_BUG_ON(sizeof(payload) != 16);
+
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+ return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_send_response - Send a 'response' to the system manager.
+ * @status: zero = success, others fail.
+ *
+ * The guest sends this message to the system manager to acnowledge success or
+ * failure of a command sent by the system manager.
+ */
+
+static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev,
+ u64 status)
+{
+ static const struct ps3_sys_manager_header header = {
+ .version = 1,
+ .size = 16,
+ .payload_size = 16,
+ .service_id = PS3_SM_SERVICE_ID_RESPONSE,
+ };
+ struct {
+ u8 version;
+ u8 reserved_1[3];
+ u8 status;
+ u8 reserved_2[11];
+ } payload;
+
+ BUILD_BUG_ON(sizeof(payload) != 16);
+
+ dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
+ (status ? "nak" : "ack"));
+
+ memset(&payload, 0, sizeof(payload));
+ payload.version = 1;
+ payload.status = status;
+
+ return ps3_sys_manager_write(dev, &header, &payload);
+}
+
+/**
+ * ps3_sys_manager_handle_event - Second stage event msg handler.
+ *
+ */
+
+static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev)
+{
+ int result;
+ struct {
+ u8 version;
+ u8 type;
+ u8 reserved_1[2];
+ u32 value;
+ u8 reserved_2[8];
+ } event;
+
+ BUILD_BUG_ON(sizeof(event) != 16);
+
+ result = ps3_vuart_read(dev, &event, sizeof(event));
+ BUG_ON(result);
+
+ if (event.version != 1) {
+ dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
+ __func__, __LINE__, event.version);
+ return -EIO;
+ }
+
+ switch (event.type) {
+ case PS3_SM_EVENT_POWER_PRESSED:
+ dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n",
+ __func__, __LINE__);
+ break;
+ case PS3_SM_EVENT_POWER_RELEASED:
+ dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
+ __func__, __LINE__, event.value);
+ kill_cad_pid(SIGINT, 1);
+ break;
+ case PS3_SM_EVENT_THERMAL_ALERT:
+ dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
+ __func__, __LINE__, event.value);
+ printk(KERN_INFO "PS3 Thermal Alert Zone %u\n", event.value);
+ break;
+ case PS3_SM_EVENT_THERMAL_CLEARED:
+ dev_dbg(&dev->core, "%s:%d: THERMAL_CLEARED (zone %u)\n",
+ __func__, __LINE__, event.value);
+ break;
+ default:
+ dev_dbg(&dev->core, "%s:%d: unknown event (%u)\n",
+ __func__, __LINE__, event.type);
+ return -EIO;
+ }
+
+ return 0;
+}
+/**
+ * ps3_sys_manager_handle_cmd - Second stage command msg handler.
+ *
+ * The system manager sends this in reply to a 'request' message from the guest.
+ */
+
+static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev)
+{
+ int result;
+ struct {
+ u8 version;
+ u8 type;
+ u8 reserved_1[14];
+ } cmd;
+
+ BUILD_BUG_ON(sizeof(cmd) != 16);
+
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+ result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
+
+ if(result)
+ return result;
+
+ if (cmd.version != 1) {
+ dev_dbg(&dev->core, "%s:%d: unsupported cmd version (%u)\n",
+ __func__, __LINE__, cmd.version);
+ return -EIO;
+ }
+
+ if (cmd.type != PS3_SM_CMD_SHUTDOWN) {
+ dev_dbg(&dev->core, "%s:%d: unknown cmd (%u)\n",
+ __func__, __LINE__, cmd.type);
+ return -EIO;
+ }
+
+ ps3_sys_manager_send_response(dev, 0);
+ return 0;
+}
+
+/**
+ * ps3_sys_manager_handle_msg - First stage msg handler.
+ *
+ */
+
+static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev)
+{
+ int result;
+ struct ps3_sys_manager_header header;
+
+ result = ps3_vuart_read(dev, &header,
+ sizeof(struct ps3_sys_manager_header));
+
+ if(result)
+ return result;
+
+ if (header.version != 1) {
+ dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n",
+ __func__, __LINE__, header.version);
+ goto fail_header;
+ }
+
+ BUILD_BUG_ON(sizeof(header) != 16);
+ BUG_ON(header.size != 16);
+ BUG_ON(header.payload_size != 16);
+
+ switch (header.service_id) {
+ case PS3_SM_SERVICE_ID_EXTERN_EVENT:
+ dev_dbg(&dev->core, "%s:%d: EVENT\n", __func__, __LINE__);
+ return ps3_sys_manager_handle_event(dev);
+ case PS3_SM_SERVICE_ID_COMMAND:
+ dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__);
+ return ps3_sys_manager_handle_cmd(dev);
+ default:
+ dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n",
+ __func__, __LINE__, header.service_id);
+ break;
+ }
+ goto fail_id;
+
+fail_header:
+ ps3_vuart_clear_rx_bytes(dev, 0);
+ return -EIO;
+fail_id:
+ ps3_vuart_clear_rx_bytes(dev, header.payload_size);
+ return -EIO;
+}
+
+/**
+ * ps3_sys_manager_work - Asyncronous read handler.
+ *
+ * Signaled when a complete message arrives at the vuart port.
+ */
+
+static void ps3_sys_manager_work(struct work_struct *work)
+{
+ struct ps3_vuart_port_device *dev = ps3_vuart_work_to_port_device(work);
+
+ ps3_sys_manager_handle_msg(dev);
+ ps3_vuart_read_async(dev, ps3_sys_manager_work, PS3_SM_RX_MSG_LEN);
+}
+
+struct {
+ struct ps3_vuart_port_device *dev;
+} static drv_priv;
+
+/**
+ * ps3_sys_manager_restart - The final platform machine_restart routine.
+ *
+ * This routine never returns. The routine disables asyncronous vuart reads
+ * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
+ * the shutdown command sent from the system manager. Soon after the
+ * acknowledgement is sent the lpar is destroyed by the HV. This routine
+ * should only be called from ps3_restart().
+ */
+
+void ps3_sys_manager_restart(void)
+{
+ struct ps3_vuart_port_device *dev = drv_priv.dev;
+
+ BUG_ON(!drv_priv.dev);
+
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+ ps3_vuart_cancel_async(dev);
+
+ ps3_sys_manager_send_attr(dev, 0);
+ ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT,
+ PS3_SM_WAKE_DEFAULT);
+ ps3_sys_manager_send_request_shutdown(dev);
+
+ printk(KERN_EMERG "System Halted, OK to turn off power\n");
+
+ while(1)
+ ps3_sys_manager_handle_msg(dev);
+}
+
+/**
+ * ps3_sys_manager_power_off - The final platform machine_power_off routine.
+ *
+ * This routine never returns. The routine disables asyncronous vuart reads
+ * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
+ * the shutdown command sent from the system manager. Soon after the
+ * acknowledgement is sent the lpar is destroyed by the HV. This routine
+ * should only be called from ps3_power_off().
+ */
+
+void ps3_sys_manager_power_off(void)
+{
+ struct ps3_vuart_port_device *dev = drv_priv.dev;
+
+ BUG_ON(!drv_priv.dev);
+
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+ ps3_vuart_cancel_async(dev);
+
+ ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
+ PS3_SM_WAKE_DEFAULT);
+ ps3_sys_manager_send_request_shutdown(dev);
+
+ printk(KERN_EMERG "System Halted, OK to turn off power\n");
+
+ while(1)
+ ps3_sys_manager_handle_msg(dev);
+}
+
+static int ps3_sys_manager_probe(struct ps3_vuart_port_device *dev)
+{
+ int result;
+
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+ BUG_ON(drv_priv.dev);
+ drv_priv.dev = dev;
+
+ result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL);
+ BUG_ON(result);
+
+ result = ps3_vuart_read_async(dev, ps3_sys_manager_work,
+ PS3_SM_RX_MSG_LEN);
+ BUG_ON(result);
+
+ return result;
+}
+
+static struct ps3_vuart_port_driver ps3_sys_manager = {
+ .match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
+ .core = {
+ .name = "ps3_sys_manager",
+ },
+ .probe = ps3_sys_manager_probe,
+};
+
+static int __init ps3_sys_manager_init(void)
+{
+ return ps3_vuart_port_driver_register(&ps3_sys_manager);
+}
+
+module_init(ps3_sys_manager_init);
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
index ef8fd4c3087..746298107d6 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -21,8 +21,10 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
+#include <linux/workqueue.h>
#include <asm/ps3.h>
+#include <asm/firmware.h>
#include <asm/lv1call.h>
#include <asm/bitops.h>
@@ -30,7 +32,7 @@
MODULE_AUTHOR("Sony Corporation");
MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("ps3 vuart");
+MODULE_DESCRIPTION("PS3 vuart");
/**
* vuart - An inter-partition data link service.
@@ -157,7 +159,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
unsigned long size;
unsigned long val;
- result = lv1_get_virtual_uart_param(dev->port_number,
+ result = lv1_get_virtual_uart_param(dev->priv->port_number,
PARAM_TX_TRIGGER, &trig->tx);
if (result) {
@@ -166,7 +168,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
return result;
}
- result = lv1_get_virtual_uart_param(dev->port_number,
+ result = lv1_get_virtual_uart_param(dev->priv->port_number,
PARAM_RX_BUF_SIZE, &size);
if (result) {
@@ -175,7 +177,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
return result;
}
- result = lv1_get_virtual_uart_param(dev->port_number,
+ result = lv1_get_virtual_uart_param(dev->priv->port_number,
PARAM_RX_TRIGGER, &val);
if (result) {
@@ -198,7 +200,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
int result;
unsigned long size;
- result = lv1_set_virtual_uart_param(dev->port_number,
+ result = lv1_set_virtual_uart_param(dev->priv->port_number,
PARAM_TX_TRIGGER, tx);
if (result) {
@@ -207,7 +209,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
return result;
}
- result = lv1_get_virtual_uart_param(dev->port_number,
+ result = lv1_get_virtual_uart_param(dev->priv->port_number,
PARAM_RX_BUF_SIZE, &size);
if (result) {
@@ -216,7 +218,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
return result;
}
- result = lv1_set_virtual_uart_param(dev->port_number,
+ result = lv1_set_virtual_uart_param(dev->priv->port_number,
PARAM_RX_TRIGGER, size - rx);
if (result) {
@@ -232,9 +234,9 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
}
static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
- unsigned long *bytes_waiting)
+ u64 *bytes_waiting)
{
- int result = lv1_get_virtual_uart_param(dev->port_number,
+ int result = lv1_get_virtual_uart_param(dev->priv->port_number,
PARAM_RX_BYTES, bytes_waiting);
if (result)
@@ -253,10 +255,10 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
- dev->interrupt_mask = mask;
+ dev->priv->interrupt_mask = mask;
- result = lv1_set_virtual_uart_param(dev->port_number,
- PARAM_INTERRUPT_MASK, dev->interrupt_mask);
+ result = lv1_set_virtual_uart_param(dev->priv->port_number,
+ PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask);
if (result)
dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
@@ -265,62 +267,64 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
return result;
}
-static int ps3_vuart_get_interrupt_mask(struct ps3_vuart_port_device *dev,
+static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev,
unsigned long *status)
{
- int result = lv1_get_virtual_uart_param(dev->port_number,
- PARAM_INTERRUPT_STATUS, status);
+ u64 tmp;
+ int result = lv1_get_virtual_uart_param(dev->priv->port_number,
+ PARAM_INTERRUPT_STATUS, &tmp);
if (result)
dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
__func__, __LINE__, ps3_result(result));
+ *status = tmp & dev->priv->interrupt_mask;
+
dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
- __func__, __LINE__, dev->interrupt_mask, *status,
- dev->interrupt_mask & *status);
+ __func__, __LINE__, dev->priv->interrupt_mask, tmp, *status);
return result;
}
int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev)
{
- return (dev->interrupt_mask & INTERRUPT_MASK_TX) ? 0
- : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
+ : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
| INTERRUPT_MASK_TX);
}
int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev)
{
- return (dev->interrupt_mask & INTERRUPT_MASK_RX) ? 0
- : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
+ : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
| INTERRUPT_MASK_RX);
}
int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
{
- return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
- : ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
+ : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
| INTERRUPT_MASK_DISCONNECT);
}
int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev)
{
- return (dev->interrupt_mask & INTERRUPT_MASK_TX)
- ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX)
+ ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
& ~INTERRUPT_MASK_TX) : 0;
}
int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev)
{
- return (dev->interrupt_mask & INTERRUPT_MASK_RX)
- ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX)
+ ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
& ~INTERRUPT_MASK_RX) : 0;
}
int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev)
{
- return (dev->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
- ? ps3_vuart_set_interrupt_mask(dev, dev->interrupt_mask
+ return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
+ ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask
& ~INTERRUPT_MASK_DISCONNECT) : 0;
}
@@ -335,9 +339,7 @@ static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
{
int result;
- dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
-
- result = lv1_write_virtual_uart(dev->port_number,
+ result = lv1_write_virtual_uart(dev->priv->port_number,
ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
if (result) {
@@ -346,10 +348,10 @@ static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
return result;
}
- dev->stats.bytes_written += *bytes_written;
+ dev->priv->stats.bytes_written += *bytes_written;
- dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__,
- __LINE__, *bytes_written, bytes, dev->stats.bytes_written);
+ dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
+ *bytes_written, bytes, dev->priv->stats.bytes_written);
return result;
}
@@ -367,7 +369,7 @@ static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
- result = lv1_read_virtual_uart(dev->port_number,
+ result = lv1_read_virtual_uart(dev->priv->port_number,
ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
if (result) {
@@ -376,15 +378,58 @@ static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
return result;
}
- dev->stats.bytes_read += *bytes_read;
+ dev->priv->stats.bytes_read += *bytes_read;
dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
- *bytes_read, bytes, dev->stats.bytes_read);
+ *bytes_read, bytes, dev->priv->stats.bytes_read);
return result;
}
/**
+ * ps3_vuart_clear_rx_bytes - Discard bytes received.
+ * @bytes: Max byte count to discard, zero = all pending.
+ *
+ * Used to clear pending rx interrupt source. Will not block.
+ */
+
+void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+ unsigned int bytes)
+{
+ int result;
+ u64 bytes_waiting;
+ void* tmp;
+
+ result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes_waiting);
+
+ BUG_ON(result);
+
+ bytes = bytes ? min(bytes, (unsigned int)bytes_waiting) : bytes_waiting;
+
+ dev_dbg(&dev->core, "%s:%d: %u\n", __func__, __LINE__, bytes);
+
+ if (!bytes)
+ return;
+
+ /* Add some extra space for recently arrived data. */
+
+ bytes += 128;
+
+ tmp = kmalloc(bytes, GFP_KERNEL);
+
+ if (!tmp)
+ return;
+
+ ps3_vuart_raw_read(dev, tmp, bytes, &bytes_waiting);
+
+ kfree(tmp);
+
+ /* Don't include these bytes in the stats. */
+
+ dev->priv->stats.bytes_read -= bytes_waiting;
+}
+
+/**
* struct list_buffer - An element for a port device fifo buffer list.
*/
@@ -416,14 +461,14 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
bytes, bytes);
- spin_lock_irqsave(&dev->tx_list.lock, flags);
+ spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
- if (list_empty(&dev->tx_list.head)) {
+ if (list_empty(&dev->priv->tx_list.head)) {
unsigned long bytes_written;
result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
- spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+ spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
if (result) {
dev_dbg(&dev->core,
@@ -441,7 +486,7 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
bytes -= bytes_written;
buf += bytes_written;
} else
- spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+ spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
@@ -454,10 +499,10 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
lb->tail = lb->data + bytes;
lb->dbg_number = ++dbg_number;
- spin_lock_irqsave(&dev->tx_list.lock, flags);
- list_add_tail(&lb->link, &dev->tx_list.head);
+ spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
+ list_add_tail(&lb->link, &dev->priv->tx_list.head);
ps3_vuart_enable_interrupt_tx(dev);
- spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+ spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
__func__, __LINE__, lb->dbg_number, bytes);
@@ -484,47 +529,83 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
bytes, bytes);
- spin_lock_irqsave(&dev->rx_list.lock, flags);
+ spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
- if (dev->rx_list.bytes_held < bytes) {
- spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+ if (dev->priv->rx_list.bytes_held < bytes) {
+ spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
- __func__, __LINE__, bytes - dev->rx_list.bytes_held);
+ __func__, __LINE__,
+ bytes - dev->priv->rx_list.bytes_held);
return -EAGAIN;
}
- list_for_each_entry_safe(lb, n, &dev->rx_list.head, link) {
+ list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) {
bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
memcpy(buf, lb->head, bytes_read);
buf += bytes_read;
bytes -= bytes_read;
- dev->rx_list.bytes_held -= bytes_read;
+ dev->priv->rx_list.bytes_held -= bytes_read;
if (bytes_read < lb->tail - lb->head) {
lb->head += bytes_read;
- spin_unlock_irqrestore(&dev->rx_list.lock, flags);
-
- dev_dbg(&dev->core,
- "%s:%d: dequeued buf_%lu, %lxh bytes\n",
- __func__, __LINE__, lb->dbg_number, bytes_read);
+ dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh "
+ "bytes\n", __func__, __LINE__, lb->dbg_number,
+ bytes_read);
+ spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
return 0;
}
- dev_dbg(&dev->core, "%s:%d free buf_%lu\n", __func__, __LINE__,
- lb->dbg_number);
+ dev_dbg(&dev->core, "%s:%d: buf_%lu: free, dequeued %lxh "
+ "bytes\n", __func__, __LINE__, lb->dbg_number,
+ bytes_read);
list_del(&lb->link);
kfree(lb);
}
- spin_unlock_irqrestore(&dev->rx_list.lock, flags);
- dev_dbg(&dev->core, "%s:%d: dequeued buf_%lu, %xh bytes\n",
- __func__, __LINE__, lb->dbg_number, bytes);
+ spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
+ return 0;
+}
+
+int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
+ unsigned int bytes)
+{
+ unsigned long flags;
+
+ if(dev->priv->work.trigger) {
+ dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n",
+ __func__, __LINE__);
+ return -EAGAIN;
+ }
+
+ BUG_ON(!bytes);
+
+ PREPARE_WORK(&dev->priv->work.work, func);
+
+ spin_lock_irqsave(&dev->priv->work.lock, flags);
+ if(dev->priv->rx_list.bytes_held >= bytes) {
+ dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
+ __func__, __LINE__, bytes);
+ schedule_work(&dev->priv->work.work);
+ spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+ return 0;
+ }
+
+ dev->priv->work.trigger = bytes;
+ spin_unlock_irqrestore(&dev->priv->work.lock, flags);
+
+ dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__,
+ __LINE__, bytes, bytes);
return 0;
}
+void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
+{
+ dev->priv->work.trigger = 0;
+}
+
/**
* ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
*
@@ -542,9 +623,9 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
- spin_lock_irqsave(&dev->tx_list.lock, flags);
+ spin_lock_irqsave(&dev->priv->tx_list.lock, flags);
- list_for_each_entry_safe(lb, n, &dev->tx_list.head, link) {
+ list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) {
unsigned long bytes_written;
@@ -578,7 +659,7 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
ps3_vuart_disable_interrupt_tx(dev);
port_full:
- spin_unlock_irqrestore(&dev->tx_list.lock, flags);
+ spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags);
dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
__func__, __LINE__, bytes_total);
return result;
@@ -609,7 +690,7 @@ static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
BUG_ON(!bytes);
- /* add some extra space for recently arrived data */
+ /* Add some extra space for recently arrived data. */
bytes += 128;
@@ -624,14 +705,23 @@ static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev)
lb->tail = lb->data + bytes;
lb->dbg_number = ++dbg_number;
- spin_lock_irqsave(&dev->rx_list.lock, flags);
- list_add_tail(&lb->link, &dev->rx_list.head);
- dev->rx_list.bytes_held += bytes;
- spin_unlock_irqrestore(&dev->rx_list.lock, flags);
+ spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
+ list_add_tail(&lb->link, &dev->priv->rx_list.head);
+ dev->priv->rx_list.bytes_held += bytes;
+ spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
- dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %lxh bytes\n",
+ dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
__func__, __LINE__, lb->dbg_number, bytes);
+ spin_lock_irqsave(&dev->priv->work.lock, flags);
+ if(dev->priv->work.trigger
+ && dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) {
+ dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
+ __func__, __LINE__, dev->priv->work.trigger);
+ dev->priv->work.trigger = 0;
+ schedule_work(&dev->priv->work.work);
+ }
+ spin_unlock_irqrestore(&dev->priv->work.lock, flags);
return 0;
}
@@ -656,7 +746,7 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
int result;
unsigned long status;
- result = ps3_vuart_get_interrupt_mask(dev, &status);
+ result = ps3_vuart_get_interrupt_status(dev, &status);
if (result)
return result;
@@ -665,21 +755,21 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
status);
if (status & INTERRUPT_MASK_DISCONNECT) {
- dev->stats.disconnect_interrupts++;
+ dev->priv->stats.disconnect_interrupts++;
result = ps3_vuart_handle_interrupt_disconnect(dev);
if (result)
ps3_vuart_disable_interrupt_disconnect(dev);
}
if (status & INTERRUPT_MASK_TX) {
- dev->stats.tx_interrupts++;
+ dev->priv->stats.tx_interrupts++;
result = ps3_vuart_handle_interrupt_tx(dev);
if (result)
ps3_vuart_disable_interrupt_tx(dev);
}
if (status & INTERRUPT_MASK_RX) {
- dev->stats.rx_interrupts++;
+ dev->priv->stats.rx_interrupts++;
result = ps3_vuart_handle_interrupt_rx(dev);
if (result)
ps3_vuart_disable_interrupt_rx(dev);
@@ -688,12 +778,13 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
return 0;
}
-struct vuart_private {
- unsigned int in_use;
+struct vuart_bus_priv {
+ const struct ports_bmp bmp;
unsigned int virq;
+ struct semaphore probe_mutex;
+ int use_count;
struct ps3_vuart_port_device *devices[PORT_COUNT];
- const struct ports_bmp bmp;
-};
+} static vuart_bus_priv;
/**
* ps3_vuart_irq_handler - first stage interrupt handler
@@ -705,25 +796,25 @@ struct vuart_private {
static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
{
- struct vuart_private *private;
+ struct vuart_bus_priv *bus_priv;
BUG_ON(!_private);
- private = (struct vuart_private *)_private;
+ bus_priv = (struct vuart_bus_priv *)_private;
while (1) {
unsigned int port;
- dump_ports_bmp(&private->bmp);
+ dump_ports_bmp(&bus_priv->bmp);
- port = (BITS_PER_LONG - 1) - __ilog2(private->bmp.status);
+ port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status);
if (port == BITS_PER_LONG)
break;
BUG_ON(port >= PORT_COUNT);
- BUG_ON(!private->devices[port]);
+ BUG_ON(!bus_priv->devices[port]);
- ps3_vuart_handle_port_interrupt(private->devices[port]);
+ ps3_vuart_handle_port_interrupt(bus_priv->devices[port]);
}
return IRQ_HANDLED;
@@ -744,12 +835,10 @@ static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv)
return result;
}
-static struct vuart_private vuart_private;
-
static int ps3_vuart_probe(struct device *_dev)
{
int result;
- unsigned long tmp;
+ unsigned int port_number;
struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
struct ps3_vuart_port_driver *drv =
to_ps3_vuart_port_driver(_dev->driver);
@@ -758,7 +847,12 @@ static int ps3_vuart_probe(struct device *_dev)
BUG_ON(!drv);
- result = ps3_vuart_match_id_to_port(dev->match_id, &dev->port_number);
+ down(&vuart_bus_priv.probe_mutex);
+
+ /* Setup vuart_bus_priv.devices[]. */
+
+ result = ps3_vuart_match_id_to_port(dev->match_id,
+ &port_number);
if (result) {
dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n",
@@ -767,24 +861,41 @@ static int ps3_vuart_probe(struct device *_dev)
goto fail_match;
}
- if (vuart_private.devices[dev->port_number]) {
+ if (vuart_bus_priv.devices[port_number]) {
dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
- __LINE__, dev->port_number);
+ __LINE__, port_number);
result = -EBUSY;
goto fail_match;
}
- vuart_private.devices[dev->port_number] = dev;
+ vuart_bus_priv.devices[port_number] = dev;
+
+ /* Setup dev->priv. */
+
+ dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL);
+
+ if (!dev->priv) {
+ result = -ENOMEM;
+ goto fail_alloc;
+ }
- INIT_LIST_HEAD(&dev->tx_list.head);
- spin_lock_init(&dev->tx_list.lock);
- INIT_LIST_HEAD(&dev->rx_list.head);
- spin_lock_init(&dev->rx_list.lock);
+ dev->priv->port_number = port_number;
+
+ INIT_LIST_HEAD(&dev->priv->tx_list.head);
+ spin_lock_init(&dev->priv->tx_list.lock);
+
+ INIT_LIST_HEAD(&dev->priv->rx_list.head);
+ spin_lock_init(&dev->priv->rx_list.lock);
+
+ INIT_WORK(&dev->priv->work.work, NULL);
+ spin_lock_init(&dev->priv->work.lock);
+ dev->priv->work.trigger = 0;
+ dev->priv->work.dev = dev;
+
+ if (++vuart_bus_priv.use_count == 1) {
- vuart_private.in_use++;
- if (vuart_private.in_use == 1) {
result = ps3_alloc_vuart_irq(PS3_BINDING_CPU_ANY,
- (void*)&vuart_private.bmp.status, &vuart_private.virq);
+ (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
if (result) {
dev_dbg(&dev->core,
@@ -794,8 +905,8 @@ static int ps3_vuart_probe(struct device *_dev)
goto fail_alloc_irq;
}
- result = request_irq(vuart_private.virq, ps3_vuart_irq_handler,
- IRQF_DISABLED, "vuart", &vuart_private);
+ result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
+ IRQF_DISABLED, "vuart", &vuart_bus_priv);
if (result) {
dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
@@ -804,10 +915,11 @@ static int ps3_vuart_probe(struct device *_dev)
}
}
- ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX);
-
/* clear stale pending interrupts */
- ps3_vuart_get_interrupt_mask(dev, &tmp);
+
+ ps3_vuart_clear_rx_bytes(dev, 0);
+
+ ps3_vuart_set_interrupt_mask(dev, INTERRUPT_MASK_RX);
ps3_vuart_set_triggers(dev, 1, 1);
@@ -822,20 +934,27 @@ static int ps3_vuart_probe(struct device *_dev)
if (result) {
dev_dbg(&dev->core, "%s:%d: drv->probe failed\n",
__func__, __LINE__);
+ down(&vuart_bus_priv.probe_mutex);
goto fail_probe;
}
+ up(&vuart_bus_priv.probe_mutex);
+
return result;
fail_probe:
+ ps3_vuart_set_interrupt_mask(dev, 0);
fail_request_irq:
- vuart_private.in_use--;
- if (!vuart_private.in_use) {
- ps3_free_vuart_irq(vuart_private.virq);
- vuart_private.virq = NO_IRQ;
- }
+ ps3_free_vuart_irq(vuart_bus_priv.virq);
+ vuart_bus_priv.virq = NO_IRQ;
fail_alloc_irq:
+ --vuart_bus_priv.use_count;
+ kfree(dev->priv);
+ dev->priv = NULL;
+fail_alloc:
+ vuart_bus_priv.devices[port_number] = 0;
fail_match:
+ up(&vuart_bus_priv.probe_mutex);
dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__);
return result;
}
@@ -846,10 +965,12 @@ static int ps3_vuart_remove(struct device *_dev)
struct ps3_vuart_port_driver *drv =
to_ps3_vuart_port_driver(_dev->driver);
+ down(&vuart_bus_priv.probe_mutex);
+
dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
dev->core.bus_id);
- BUG_ON(vuart_private.in_use < 1);
+ BUG_ON(vuart_bus_priv.use_count < 1);
if (drv->remove)
drv->remove(dev);
@@ -857,13 +978,19 @@ static int ps3_vuart_remove(struct device *_dev)
dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
__LINE__, dev->core.bus_id);
- vuart_private.in_use--;
+ vuart_bus_priv.devices[dev->priv->port_number] = 0;
- if (!vuart_private.in_use) {
- free_irq(vuart_private.virq, &vuart_private);
- ps3_free_vuart_irq(vuart_private.virq);
- vuart_private.virq = NO_IRQ;
+ if (--vuart_bus_priv.use_count == 0) {
+ BUG();
+ free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
+ ps3_free_vuart_irq(vuart_bus_priv.virq);
+ vuart_bus_priv.virq = NO_IRQ;
}
+
+ kfree(dev->priv);
+ dev->priv = NULL;
+
+ up(&vuart_bus_priv.probe_mutex);
return 0;
}
@@ -884,12 +1011,12 @@ static void ps3_vuart_shutdown(struct device *_dev)
}
/**
- * ps3_vuart - The vuart instance.
+ * ps3_vuart_bus - The vuart bus instance.
*
* The vuart is managed as a bus that port devices connect to.
*/
-struct bus_type ps3_vuart = {
+struct bus_type ps3_vuart_bus = {
.name = "ps3_vuart",
.match = ps3_vuart_match,
.probe = ps3_vuart_probe,
@@ -897,24 +1024,30 @@ struct bus_type ps3_vuart = {
.shutdown = ps3_vuart_shutdown,
};
-int __init ps3_vuart_init(void)
+int __init ps3_vuart_bus_init(void)
{
int result;
pr_debug("%s:%d:\n", __func__, __LINE__);
- result = bus_register(&ps3_vuart);
+
+ if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+ return 0;
+
+ init_MUTEX(&vuart_bus_priv.probe_mutex);
+ result = bus_register(&ps3_vuart_bus);
BUG_ON(result);
+
return result;
}
-void __exit ps3_vuart_exit(void)
+void __exit ps3_vuart_bus_exit(void)
{
pr_debug("%s:%d:\n", __func__, __LINE__);
- bus_unregister(&ps3_vuart);
+ bus_unregister(&ps3_vuart_bus);
}
-core_initcall(ps3_vuart_init);
-module_exit(ps3_vuart_exit);
+core_initcall(ps3_vuart_bus_init);
+module_exit(ps3_vuart_bus_exit);
/**
* ps3_vuart_port_release_device - Remove a vuart port device.
@@ -922,11 +1055,14 @@ module_exit(ps3_vuart_exit);
static void ps3_vuart_port_release_device(struct device *_dev)
{
- struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
#if defined(DEBUG)
- memset(dev, 0xad, sizeof(struct ps3_vuart_port_device));
+ struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+
+ dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
+
+ BUG_ON(dev->priv && "forgot to free");
+ memset(&dev->core, 0, sizeof(dev->core));
#endif
- kfree(dev);
}
/**
@@ -935,11 +1071,12 @@ static void ps3_vuart_port_release_device(struct device *_dev)
int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
{
- int result;
static unsigned int dev_count = 1;
+ BUG_ON(dev->priv && "forgot to free");
+
dev->core.parent = NULL;
- dev->core.bus = &ps3_vuart;
+ dev->core.bus = &ps3_vuart_bus;
dev->core.release = ps3_vuart_port_release_device;
snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x",
@@ -947,9 +1084,7 @@ int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__);
- result = device_register(&dev->core);
-
- return result;
+ return device_register(&dev->core);
}
EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register);
@@ -963,7 +1098,7 @@ int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv)
int result;
pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
- drv->core.bus = &ps3_vuart;
+ drv->core.bus = &ps3_vuart_bus;
result = driver_register(&drv->core);
return result;
}
@@ -976,6 +1111,7 @@ EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
{
+ pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name);
driver_unregister(&drv->core);
}
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h
index 2cbf728a3a0..1be992d568c 100644
--- a/drivers/ps3/vuart.h
+++ b/drivers/ps3/vuart.h
@@ -21,6 +21,44 @@
#if !defined(_PS3_VUART_H)
#define _PS3_VUART_H
+#include <asm/ps3.h>
+
+struct ps3_vuart_stats {
+ unsigned long bytes_written;
+ unsigned long bytes_read;
+ unsigned long tx_interrupts;
+ unsigned long rx_interrupts;
+ unsigned long disconnect_interrupts;
+};
+
+struct ps3_vuart_work {
+ struct work_struct work;
+ unsigned long trigger;
+ spinlock_t lock;
+ struct ps3_vuart_port_device* dev; /* to convert work to device */
+};
+
+/**
+ * struct ps3_vuart_port_priv - private vuart device data.
+ */
+
+struct ps3_vuart_port_priv {
+ unsigned int port_number;
+ u64 interrupt_mask;
+
+ struct {
+ spinlock_t lock;
+ struct list_head head;
+ } tx_list;
+ struct {
+ unsigned long bytes_held;
+ spinlock_t lock;
+ struct list_head head;
+ } rx_list;
+ struct ps3_vuart_stats stats;
+ struct ps3_vuart_work work;
+};
+
/**
* struct ps3_vuart_port_driver - a driver for a device on a vuart port
*/
@@ -41,10 +79,6 @@ struct ps3_vuart_port_driver {
int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
-int ps3_vuart_write(struct ps3_vuart_port_device *dev,
- const void* buf, unsigned int bytes);
-int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
- unsigned int bytes);
static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver(
struct device_driver *_drv)
{
@@ -55,5 +89,22 @@ static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
{
return container_of(_dev, struct ps3_vuart_port_device, core);
}
+static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
+ struct work_struct *_work)
+{
+ struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work,
+ work);
+ return vw->dev;
+}
+
+int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
+ unsigned int bytes);
+int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
+ unsigned int bytes);
+int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
+ unsigned int bytes);
+void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev);
+void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
+ unsigned int bytes);
#endif
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 8f6b5bf580f..2b5b8a93bc1 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -801,15 +801,10 @@ static int idescsi_ide_open(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ide_scsi_obj *scsi;
- ide_drive_t *drive;
if (!(scsi = ide_scsi_get(disk)))
return -ENXIO;
- drive = scsi->drive;
-
- drive->usage++;
-
return 0;
}
@@ -817,9 +812,6 @@ static int idescsi_ide_release(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ide_scsi_obj *scsi = ide_scsi_g(disk);
- ide_drive_t *drive = scsi->drive;
-
- drive->usage--;
ide_scsi_put(scsi);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 3f048bd6326..5a8f55fea5f 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1269,9 +1269,18 @@ repeat:
/* Some devices return the total number of sectors, not the
* highest sector number. Make the necessary adjustment. */
- if (sdp->fix_capacity)
+ if (sdp->fix_capacity) {
--sdkp->capacity;
+ /* Some devices have version which report the correct sizes
+ * and others which do not. We guess size according to a heuristic
+ * and err on the side of lowering the capacity. */
+ } else {
+ if (sdp->guess_capacity)
+ if (sdkp->capacity & 0x01) /* odd sizes are odd */
+ --sdkp->capacity;
+ }
+
got_data:
if (sector_size == 0) {
sector_size = 512;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index e8dd71df916..ad9f321968e 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -262,7 +262,8 @@ config SERIAL_AMBA_PL010
select SERIAL_CORE
help
This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have
- an Integrator/AP or Integrator/PP2 platform, say Y or M here.
+ an Integrator/AP or Integrator/PP2 platform, or if you have a
+ Cirrus Logic EP93xx CPU, say Y or M here.
If unsure, say N.
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index df45a7ac773..935f48fa501 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -33,12 +33,13 @@
#include <linux/sysrq.h>
#include <linux/tty_flip.h>
#include <linux/platform_device.h>
+#include <linux/atmel_pdc.h>
#include <asm/io.h>
#include <asm/mach/serial_at91.h>
#include <asm/arch/board.h>
-#include <asm/arch/at91_pdc.h>
+
#ifdef CONFIG_ARM
#include <asm/arch/cpu.h>
#include <asm/arch/gpio.h>
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index 787a8f13467..fa455996ad8 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -285,7 +285,7 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
int __init cpm_uart_init_portdesc(void)
{
#if defined(CONFIG_SERIAL_CPM_SMC1) || defined(CONFIG_SERIAL_CPM_SMC2)
- u32 addr;
+ u16 *addr;
#endif
pr_debug("CPM uart[-]:init portdesc\n");
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index e216dcf2937..04cc88cc528 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -154,7 +154,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
{
struct circ_buf *xmit = &sport->port.info->xmit;
- do {
+ while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)) {
/* send xmit->buf[xmit->tail]
* out the port here */
URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail];
@@ -163,7 +163,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
sport->port.icount.tx++;
if (uart_circ_empty(xmit))
break;
- } while (!(UTS((u32)sport->port.membase) & UTS_TXFULL));
+ }
if (uart_circ_empty(xmit))
imx_stop_tx(&sport->port);
@@ -178,8 +178,7 @@ static void imx_start_tx(struct uart_port *port)
UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN;
- if(UTS((u32)sport->port.membase) & UTS_TXEMPTY)
- imx_transmit_buffer(sport);
+ imx_transmit_buffer(sport);
}
static irqreturn_t imx_rtsint(int irq, void *dev_id)
@@ -404,7 +403,8 @@ static int imx_startup(struct uart_port *port)
if (retval) goto error_out2;
retval = request_irq(sport->rtsirq, imx_rtsint,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ (sport->rtsirq < IMX_IRQS) ? 0 :
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
DRIVER_NAME, sport);
if (retval) goto error_out3;
@@ -678,7 +678,7 @@ static struct imx_port imx_ports[] = {
.mapbase = IMX_UART1_BASE, /* FIXME */
.irq = UART1_MINT_RX,
.uartclk = 16000000,
- .fifosize = 8,
+ .fifosize = 32,
.flags = UPF_BOOT_AUTOCONF,
.ops = &imx_pops,
.line = 0,
@@ -694,7 +694,7 @@ static struct imx_port imx_ports[] = {
.mapbase = IMX_UART2_BASE, /* FIXME */
.irq = UART2_MINT_RX,
.uartclk = 16000000,
- .fifosize = 8,
+ .fifosize = 32,
.flags = UPF_BOOT_AUTOCONF,
.ops = &imx_pops,
.line = 1,
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 955bbd653e2..8d24cd52105 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -995,8 +995,10 @@ mpc52xx_uart_of_remove(struct of_device *op)
struct uart_port *port = dev_get_drvdata(&op->dev);
dev_set_drvdata(&op->dev, NULL);
- if (port)
+ if (port) {
uart_remove_one_port(&mpc52xx_uart_driver, port);
+ irq_dispose_mapping(port->irq);
+ }
return 0;
}
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index c2f1012449d..6b76babc7fb 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -248,6 +248,10 @@ static const struct serial_quirk quirks[] = {
.multi = 2,
}, {
.manfid = MANFID_QUATECH,
+ .prodid = PRODID_QUATECH_DUAL_RS232_G,
+ .multi = 2,
+ }, {
+ .manfid = MANFID_QUATECH,
.prodid = PRODID_QUATECH_QUAD_RS232,
.multi = 4,
}, {
@@ -891,6 +895,7 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
+ PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"),
PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"),
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 825bf884537..8b7ff467d26 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_USB_SERIAL) += serial/
obj-$(CONFIG_USB_ADUTUX) += misc/
obj-$(CONFIG_USB_APPLEDISPLAY) += misc/
obj-$(CONFIG_USB_AUERSWALD) += misc/
+obj-$(CONFIG_USB_BERRY_CHARGE) += misc/
obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/
obj-$(CONFIG_USB_CYTHERM) += misc/
obj-$(CONFIG_USB_EMI26) += misc/
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index dae4ef1e8fe..4973e147bc7 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -61,6 +61,7 @@
#include <linux/usb.h>
#include <linux/firmware.h>
#include <linux/ctype.h>
+#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/version.h>
#include <linux/mutex.h>
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 98199628e39..d38a25f36ea 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -326,10 +326,16 @@ static void acm_rx_tasklet(unsigned long _acm)
struct tty_struct *tty = acm->tty;
struct acm_ru *rcv;
unsigned long flags;
- int i = 0;
+ unsigned char throttled;
dbg("Entering acm_rx_tasklet");
- if (!ACM_READY(acm) || acm->throttle)
+ if (!ACM_READY(acm))
+ return;
+
+ spin_lock(&acm->throttle_lock);
+ throttled = acm->throttle;
+ spin_unlock(&acm->throttle_lock);
+ if (throttled)
return;
next_buffer:
@@ -346,22 +352,20 @@ next_buffer:
dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
tty_buffer_request_room(tty, buf->size);
- if (!acm->throttle)
+ spin_lock(&acm->throttle_lock);
+ throttled = acm->throttle;
+ spin_unlock(&acm->throttle_lock);
+ if (!throttled)
tty_insert_flip_string(tty, buf->base, buf->size);
tty_flip_buffer_push(tty);
- spin_lock(&acm->throttle_lock);
- if (acm->throttle) {
- dbg("Throtteling noticed");
- memmove(buf->base, buf->base + i, buf->size - i);
- buf->size -= i;
- spin_unlock(&acm->throttle_lock);
+ if (throttled) {
+ dbg("Throttling noticed");
spin_lock_irqsave(&acm->read_lock, flags);
list_add(&buf->list, &acm->filled_read_bufs);
spin_unlock_irqrestore(&acm->read_lock, flags);
return;
}
- spin_unlock(&acm->throttle_lock);
spin_lock_irqsave(&acm->read_lock, flags);
list_add(&buf->list, &acm->spare_read_bufs);
@@ -467,7 +471,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
goto bail_out;
}
- if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
+ if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
+ (acm->ctrl_caps & USB_CDC_CAP_LINE))
goto full_bailout;
INIT_LIST_HEAD(&acm->spare_read_urbs);
@@ -480,6 +485,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
}
+ acm->throttle = 0;
+
tasklet_schedule(&acm->urb_task);
done:
@@ -1092,6 +1099,10 @@ static struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0x0ace, 0x1611), /* ZyDAS 56K USB MODEM - new version */
.driver_info = SINGLE_RX_URB, /* firmware bug */
},
+ { USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */
+ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+ },
+
/* control interfaces with various AT-command sets */
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
USB_CDC_ACM_PROTO_AT_V25TER) },
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index a47c30b2d76..aefc7987120 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -604,10 +604,6 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
lock_kernel();
if (!st) {
st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
- if (!st) {
- unlock_kernel();
- return POLLIN;
- }
/* we may have dropped BKL - need to check for having lost the race */
if (file->private_data) {
@@ -615,6 +611,11 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
st = file->private_data;
goto lost_race;
}
+ /* we haven't lost - check for allocation failure now */
+ if (!st) {
+ unlock_kernel();
+ return POLLIN;
+ }
/*
* need to prevent the module from being unloaded, since
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 2087766f9e8..274f14f1633 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -857,11 +857,11 @@ static int proc_setintf(struct dev_state *ps, void __user *arg)
static int proc_setconfig(struct dev_state *ps, void __user *arg)
{
- unsigned int u;
+ int u;
int status = 0;
struct usb_host_config *actconfig;
- if (get_user(u, (unsigned int __user *)arg))
+ if (get_user(u, (int __user *)arg))
return -EFAULT;
actconfig = ps->dev->actconfig;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 600d1bc8272..2aded261f42 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -743,6 +743,7 @@ EXPORT_SYMBOL_GPL(usb_deregister_device_driver);
* usb_register_driver - register a USB interface driver
* @new_driver: USB operations for the interface driver
* @owner: module owner of this driver.
+ * @mod_name: module name string
*
* Registers a USB interface driver with the USB core. The list of
* unattached interfaces will be rescanned whenever a new driver is
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 5e628ae3aec..e0ec7045e86 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -229,7 +229,7 @@ static int init_endpoint_class(void)
kref_init(&ep_class->kref);
ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
if (IS_ERR(ep_class->class)) {
- result = IS_ERR(ep_class->class);
+ result = PTR_ERR(ep_class->class);
goto class_create_error;
}
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index b531a4fd30c..9bbcb20e2d9 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -184,7 +184,7 @@ static void generic_disconnect(struct usb_device *udev)
/* if this is only an unbind, not a physical disconnect, then
* unconfigure the device */
if (udev->actconfig)
- usb_set_configuration(udev, 0);
+ usb_set_configuration(udev, -1);
usb_remove_sysfs_dev_files(udev);
}
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 590ec82d051..50c0db15304 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -44,6 +44,7 @@ struct usb_hub {
struct usb_hub_status hub;
struct usb_port_status port;
} *status; /* buffer for status reports */
+ struct mutex status_mutex; /* for the status buffer */
int error; /* last reported error */
int nerrors; /* track consecutive errors */
@@ -535,6 +536,7 @@ static int hub_hub_status(struct usb_hub *hub,
{
int ret;
+ mutex_lock(&hub->status_mutex);
ret = get_hub_status(hub->hdev, &hub->status->hub);
if (ret < 0)
dev_err (hub->intfdev,
@@ -544,6 +546,7 @@ static int hub_hub_status(struct usb_hub *hub,
*change = le16_to_cpu(hub->status->hub.wHubChange);
ret = 0;
}
+ mutex_unlock(&hub->status_mutex);
return ret;
}
@@ -617,6 +620,7 @@ static int hub_configure(struct usb_hub *hub,
ret = -ENOMEM;
goto fail;
}
+ mutex_init(&hub->status_mutex);
hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
if (!hub->descriptor) {
@@ -1396,6 +1400,7 @@ static int hub_port_status(struct usb_hub *hub, int port1,
{
int ret;
+ mutex_lock(&hub->status_mutex);
ret = get_port_status(hub->hdev, port1, &hub->status->port);
if (ret < 4) {
dev_err (hub->intfdev,
@@ -1407,6 +1412,7 @@ static int hub_port_status(struct usb_hub *hub, int port1,
*change = le16_to_cpu(hub->status->port.wPortChange);
ret = 0;
}
+ mutex_unlock(&hub->status_mutex);
return ret;
}
@@ -1904,6 +1910,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev = hub->hdev;
unsigned port1;
+ int status = 0;
/* fail if children aren't already suspended */
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -1927,24 +1934,18 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
+ /* stop khubd and related activity */
+ hub_quiesce(hub);
+
/* "global suspend" of the downstream HC-to-USB interface */
if (!hdev->parent) {
- struct usb_bus *bus = hdev->bus;
- if (bus) {
- int status = hcd_bus_suspend (bus);
-
- if (status != 0) {
- dev_dbg(&hdev->dev, "'global' suspend %d\n",
- status);
- return status;
- }
- } else
- return -EOPNOTSUPP;
+ status = hcd_bus_suspend(hdev->bus);
+ if (status != 0) {
+ dev_dbg(&hdev->dev, "'global' suspend %d\n", status);
+ hub_activate(hub);
+ }
}
-
- /* stop khubd and related activity */
- hub_quiesce(hub);
- return 0;
+ return status;
}
static int hub_resume(struct usb_interface *intf)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 8aca3574c2b..74edaea5665 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1316,6 +1316,14 @@ static void release_interface(struct device *dev)
* use this kind of configurability; many devices only have one
* configuration.
*
+ * @configuration is the value of the configuration to be installed.
+ * According to the USB spec (e.g. section 9.1.1.5), configuration values
+ * must be non-zero; a value of zero indicates that the device in
+ * unconfigured. However some devices erroneously use 0 as one of their
+ * configuration values. To help manage such devices, this routine will
+ * accept @configuration = -1 as indicating the device should be put in
+ * an unconfigured state.
+ *
* USB device configurations may affect Linux interoperability,
* power consumption and the functionality available. For example,
* the default configuration is limited to using 100mA of bus power,
@@ -1347,10 +1355,15 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
struct usb_interface **new_interfaces = NULL;
int n, nintf;
- for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
- if (dev->config[i].desc.bConfigurationValue == configuration) {
- cp = &dev->config[i];
- break;
+ if (configuration == -1)
+ configuration = 0;
+ else {
+ for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+ if (dev->config[i].desc.bConfigurationValue ==
+ configuration) {
+ cp = &dev->config[i];
+ break;
+ }
}
}
if ((!cp && configuration != 0))
@@ -1359,6 +1372,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
/* The USB spec says configuration 0 means unconfigured.
* But if a device includes a configuration numbered 0,
* we will accept it as a correctly configured state.
+ * Use -1 if you really want to unconfigure the device.
*/
if (cp && configuration == 0)
dev_warn(&dev->dev, "config 0 descriptor??\n");
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
index 627a5a2fc9c..7f31a495a25 100644
--- a/drivers/usb/core/otg_whitelist.h
+++ b/drivers/usb/core/otg_whitelist.h
@@ -31,7 +31,7 @@ static struct usb_device_id whitelist_table [] = {
{ USB_DEVICE_INFO(7, 1, 3) },
#endif
-#ifdef CONFIG_USB_CDCETHER
+#ifdef CONFIG_USB_NET_CDCETHER
/* Linux-USB CDC Ethernet gadget */
{ USB_DEVICE(0x0525, 0xa4a1), },
/* Linux-USB CDC Ethernet + RNDIS gadget */
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 4eaa0ee8e72..0edfbafd702 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -63,7 +63,7 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
struct usb_device *udev = to_usb_device(dev);
int config, value;
- if (sscanf(buf, "%u", &config) != 1 || config > 255)
+ if (sscanf(buf, "%d", &config) != 1 || config < -1 || config > 255)
return -EINVAL;
usb_lock_device(udev);
value = usb_set_configuration(udev, config);
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 36b36e0175f..a4677802fb2 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -784,7 +784,7 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value)
return status;
}
-static struct usb_ep_ops at91_ep_ops = {
+static const struct usb_ep_ops at91_ep_ops = {
.enable = at91_ep_enable,
.disable = at91_ep_disable,
.alloc_request = at91_ep_alloc_request,
@@ -912,7 +912,7 @@ static void pullup(struct at91_udc *udc, int is_on)
at91_udp_write(udc, AT91_UDP_TXVC, 0);
if (cpu_is_at91rm9200())
at91_set_gpio_value(udc->board.pullup_pin, 1);
- else if (cpu_is_at91sam9260()) {
+ else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
txvc |= AT91_UDP_TXVC_PUON;
@@ -929,7 +929,7 @@ static void pullup(struct at91_udc *udc, int is_on)
at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
if (cpu_is_at91rm9200())
at91_set_gpio_value(udc->board.pullup_pin, 0);
- else if (cpu_is_at91sam9260()) {
+ else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
txvc &= ~AT91_UDP_TXVC_PUON;
@@ -1651,7 +1651,7 @@ static void at91udc_shutdown(struct platform_device *dev)
pullup(platform_get_drvdata(dev), 0);
}
-static int __devinit at91udc_probe(struct platform_device *pdev)
+static int __init at91udc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct at91_udc *udc;
@@ -1762,7 +1762,7 @@ fail0:
return retval;
}
-static int __devexit at91udc_remove(struct platform_device *pdev)
+static int __exit at91udc_remove(struct platform_device *pdev)
{
struct at91_udc *udc = platform_get_drvdata(pdev);
struct resource *res;
@@ -1836,8 +1836,7 @@ static int at91udc_resume(struct platform_device *pdev)
#endif
static struct platform_driver at91_udc = {
- .probe = at91udc_probe,
- .remove = __devexit_p(at91udc_remove),
+ .remove = __exit_p(at91udc_remove),
.shutdown = at91udc_shutdown,
.suspend = at91udc_suspend,
.resume = at91udc_resume,
@@ -1847,13 +1846,13 @@ static struct platform_driver at91_udc = {
},
};
-static int __devinit udc_init_module(void)
+static int __init udc_init_module(void)
{
- return platform_driver_register(&at91_udc);
+ return platform_driver_probe(&at91_udc, at91udc_probe);
}
module_init(udc_init_module);
-static void __devexit udc_exit_module(void)
+static void __exit udc_exit_module(void)
{
platform_driver_unregister(&at91_udc);
}
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 27904a56494..f01890dc875 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -155,7 +155,7 @@ static int is_vbus_present(void)
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
if (mach->gpio_vbus)
- return pxa_gpio_get(mach->gpio_vbus);
+ return udc_gpio_get(mach->gpio_vbus);
if (mach->udc_is_connected)
return mach->udc_is_connected();
return 1;
@@ -167,7 +167,7 @@ static void pullup_off(void)
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
if (mach->gpio_pullup)
- pxa_gpio_set(mach->gpio_pullup, 0);
+ udc_gpio_set(mach->gpio_pullup, 0);
else if (mach->udc_command)
mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
}
@@ -177,7 +177,7 @@ static void pullup_on(void)
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
if (mach->gpio_pullup)
- pxa_gpio_set(mach->gpio_pullup, 1);
+ udc_gpio_set(mach->gpio_pullup, 1);
else if (mach->udc_command)
mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
}
@@ -1755,7 +1755,7 @@ lubbock_vbus_irq(int irq, void *_dev)
static irqreturn_t udc_vbus_irq(int irq, void *_dev)
{
struct pxa2xx_udc *dev = _dev;
- int vbus = pxa_gpio_get(dev->mach->gpio_vbus);
+ int vbus = udc_gpio_get(dev->mach->gpio_vbus);
pxa2xx_udc_vbus_session(&dev->gadget, vbus);
return IRQ_HANDLED;
@@ -2545,15 +2545,13 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
dev->dev = &pdev->dev;
dev->mach = pdev->dev.platform_data;
if (dev->mach->gpio_vbus) {
- vbus_irq = IRQ_GPIO(dev->mach->gpio_vbus & GPIO_MD_MASK_NR);
- pxa_gpio_mode((dev->mach->gpio_vbus & GPIO_MD_MASK_NR)
- | GPIO_IN);
+ udc_gpio_init_vbus(dev->mach->gpio_vbus);
+ vbus_irq = udc_gpio_to_irq(dev->mach->gpio_vbus);
set_irq_type(vbus_irq, IRQT_BOTHEDGE);
} else
vbus_irq = 0;
if (dev->mach->gpio_pullup)
- pxa_gpio_mode((dev->mach->gpio_pullup & GPIO_MD_MASK_NR)
- | GPIO_OUT | GPIO_DFLT_LOW);
+ udc_gpio_init_pullup(dev->mach->gpio_pullup);
init_timer(&dev->timer);
dev->timer.function = udc_watchdog;
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index 8e598c8bf4e..773e549aff3 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -177,21 +177,6 @@ struct pxa2xx_udc {
static struct pxa2xx_udc *the_controller;
-static inline int pxa_gpio_get(unsigned gpio)
-{
- return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
-}
-
-static inline void pxa_gpio_set(unsigned gpio, int is_on)
-{
- int mask = GPIO_bit(gpio);
-
- if (is_on)
- GPSR(gpio) = mask;
- else
- GPCR(gpio) = mask;
-}
-
/*-------------------------------------------------------------------------*/
/*
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index e6c19aa4bef..e552668d36b 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -1699,6 +1699,7 @@ static int gs_setup_class(struct usb_gadget *gadget,
memcpy(&port->port_line_coding, req->buf, ret);
spin_unlock(&port->port_lock);
}
+ ret = 0;
break;
case USB_CDC_REQ_GET_LINE_CODING:
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 185721dba42..a7405648823 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -42,6 +42,9 @@
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>
+#ifdef CONFIG_PPC_PS3
+#include <asm/firmware.h>
+#endif
/*-------------------------------------------------------------------------*/
@@ -299,6 +302,19 @@ static void ehci_watchdog (unsigned long param)
spin_unlock_irqrestore (&ehci->lock, flags);
}
+/* On some systems, leaving remote wakeup enabled prevents system shutdown.
+ * The firmware seems to think that powering off is a wakeup event!
+ * This routine turns off remote wakeup and everything else, on all ports.
+ */
+static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
+{
+ int port = HCS_N_PORTS(ehci->hcs_params);
+
+ while (port--)
+ ehci_writel(ehci, PORT_RWC_BITS,
+ &ehci->regs->port_status[port]);
+}
+
/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
* This forcibly disables dma and IRQs, helping kexec and other cases
* where the next system software may expect clean state.
@@ -310,9 +326,13 @@ ehci_shutdown (struct usb_hcd *hcd)
ehci = hcd_to_ehci (hcd);
(void) ehci_halt (ehci);
+ ehci_turn_off_all_ports(ehci);
/* make BIOS/etc use companion controller during reboot */
ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+
+ /* unblock posted writes */
+ ehci_readl(ehci, &ehci->regs->configured_flag);
}
static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
@@ -951,15 +971,18 @@ static int __init ehci_hcd_init(void)
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
- retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER);
- if (retval < 0) {
+ if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
+ retval = ps3_system_bus_driver_register(
+ &PS3_SYSTEM_BUS_DRIVER);
+ if (retval < 0) {
#ifdef PLATFORM_DRIVER
- platform_driver_unregister(&PLATFORM_DRIVER);
+ platform_driver_unregister(&PLATFORM_DRIVER);
#endif
#ifdef PCI_DRIVER
- pci_unregister_driver(&PCI_DRIVER);
+ pci_unregister_driver(&PCI_DRIVER);
#endif
- return retval;
+ return retval;
+ }
}
#endif
@@ -976,7 +999,8 @@ static void __exit ehci_hcd_cleanup(void)
pci_unregister_driver(&PCI_DRIVER);
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
- ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+ if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+ ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
#endif
}
module_exit(ehci_hcd_cleanup);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 0d83c6df1a3..9af529d22b3 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -36,6 +36,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
int port;
int mask;
+ ehci_dbg(ehci, "suspend root hub\n");
+
if (time_before (jiffies, ehci->next_statechange))
msleep(5);
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 2718b5dc4ec..46873f2534b 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1577,7 +1577,7 @@ static int isp116x_remove(struct platform_device *pdev)
#define resource_len(r) (((r)->end - (r)->start) + 1)
-static int __init isp116x_probe(struct platform_device *pdev)
+static int __devinit isp116x_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
struct isp116x *isp116x;
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 93034648727..d849c809acb 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -18,19 +18,38 @@
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
#ifndef CONFIG_ARCH_AT91
#error "CONFIG_ARCH_AT91 must be defined."
#endif
-/* interface and function clocks */
-static struct clk *iclk, *fclk;
+/* interface and function clocks; sometimes also an AHB clock */
+static struct clk *iclk, *fclk, *hclk;
static int clocked;
extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
+static void at91_start_clock(void)
+{
+ if (cpu_is_at91sam9261())
+ clk_enable(hclk);
+ clk_enable(iclk);
+ clk_enable(fclk);
+ clocked = 1;
+}
+
+static void at91_stop_clock(void)
+{
+ clk_disable(fclk);
+ clk_disable(iclk);
+ if (cpu_is_at91sam9261())
+ clk_disable(hclk);
+ clocked = 0;
+}
+
static void at91_start_hc(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -41,9 +60,7 @@ static void at91_start_hc(struct platform_device *pdev)
/*
* Start the USB clocks.
*/
- clk_enable(iclk);
- clk_enable(fclk);
- clocked = 1;
+ at91_start_clock();
/*
* The USB host controller must remain in reset.
@@ -66,9 +83,7 @@ static void at91_stop_hc(struct platform_device *pdev)
/*
* Stop the USB clocks.
*/
- clk_disable(fclk);
- clk_disable(iclk);
- clocked = 0;
+ at91_stop_clock();
}
@@ -126,6 +141,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
iclk = clk_get(&pdev->dev, "ohci_clk");
fclk = clk_get(&pdev->dev, "uhpck");
+ if (cpu_is_at91sam9261())
+ hclk = clk_get(&pdev->dev, "hck0");
at91_start_hc(pdev);
ohci_hcd_init(hcd_to_ohci(hcd));
@@ -137,6 +154,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
/* Error handling */
at91_stop_hc(pdev);
+ if (cpu_is_at91sam9261())
+ clk_put(hclk);
clk_put(fclk);
clk_put(iclk);
@@ -171,9 +190,11 @@ static int usb_hcd_at91_remove(struct usb_hcd *hcd,
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ if (cpu_is_at91sam9261())
+ clk_put(hclk);
clk_put(fclk);
clk_put(iclk);
- fclk = iclk = NULL;
+ fclk = iclk = hclk = NULL;
dev_set_drvdata(&pdev->dev, NULL);
return 0;
@@ -280,9 +301,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg)
*/
if (at91_suspend_entering_slow_clock()) {
ohci_usb_reset (ohci);
- clk_disable(fclk);
- clk_disable(iclk);
- clocked = 0;
+ at91_stop_clock();
}
return 0;
@@ -295,11 +314,8 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
if (device_may_wakeup(&pdev->dev))
disable_irq_wake(hcd->irq);
- if (!clocked) {
- clk_enable(iclk);
- clk_enable(fclk);
- clocked = 1;
- }
+ if (!clocked)
+ at91_start_clock();
return 0;
}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index fa6a7ceaa0d..f0d29eda3c6 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -42,6 +42,9 @@
#include <asm/system.h>
#include <asm/unaligned.h>
#include <asm/byteorder.h>
+#ifdef CONFIG_PPC_PS3
+#include <asm/firmware.h>
+#endif
#include "../core/hcd.h"
@@ -944,9 +947,12 @@ static int __init ohci_hcd_mod_init(void)
sizeof (struct ed), sizeof (struct td));
#ifdef PS3_SYSTEM_BUS_DRIVER
- retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER);
- if (retval < 0)
- goto error_ps3;
+ if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
+ retval = ps3_system_bus_driver_register(
+ &PS3_SYSTEM_BUS_DRIVER);
+ if (retval < 0)
+ goto error_ps3;
+ }
#endif
#ifdef PLATFORM_DRIVER
@@ -992,7 +998,8 @@ static int __init ohci_hcd_mod_init(void)
error_platform:
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
- ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+ if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+ ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
error_ps3:
#endif
return retval;
@@ -1014,7 +1021,8 @@ static void __exit ohci_hcd_mod_exit(void)
platform_driver_unregister(&PLATFORM_DRIVER);
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
- ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+ if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+ ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
#endif
}
module_exit(ohci_hcd_mod_exit);
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 4d8ed3d71a1..ef09952f203 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -515,6 +515,7 @@ void usbhid_close(struct hid_device *hid)
#define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
+#define USB_VENDOR_ID_CIDC 0x1677
/*
* Initialize all reports
@@ -548,7 +549,6 @@ void usbhid_init_reports(struct hid_device *hid)
}
#define USB_VENDOR_ID_GTCO 0x078c
-#define USB_VENDOR_ID_GTCO_IPANEL_2 0x5543
#define USB_DEVICE_ID_GTCO_90 0x0090
#define USB_DEVICE_ID_GTCO_100 0x0100
#define USB_DEVICE_ID_GTCO_101 0x0101
@@ -594,8 +594,6 @@ void usbhid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_GTCO_1004 0x1004
#define USB_DEVICE_ID_GTCO_1005 0x1005
#define USB_DEVICE_ID_GTCO_1006 0x1006
-#define USB_DEVICE_ID_GTCO_8 0x0008
-#define USB_DEVICE_ID_GTCO_d 0x000d
#define USB_VENDOR_ID_WACOM 0x056a
@@ -854,8 +852,6 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_8, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_GTCO_IPANEL_2, USB_DEVICE_ID_GTCO_d, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
@@ -953,6 +949,8 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER },
+ { USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE },
+
{ 0, 0 }
};
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index a74bf8617e7..4907e8b8007 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -88,6 +88,17 @@ config USB_LCD
To compile this driver as a module, choose M here: the
module will be called usblcd.
+config USB_BERRY_CHARGE
+ tristate "USB BlackBerry recharge support"
+ depends on USB
+ help
+ Say Y here if you want to connect a BlackBerry device to your
+ computer's USB port and have it automatically switch to "recharge"
+ mode.
+
+ To compile this driver as a module, choose M here: the
+ module will be called berry_charge.
+
config USB_LED
tristate "USB LED driver support"
depends on USB
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 2cba07d3197..dac2d5b7156 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_USB_ADUTUX) += adutux.o
obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o
obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
+obj-$(CONFIG_USB_BERRY_CHARGE) += berry_charge.o
obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
obj-$(CONFIG_USB_CYTHERM) += cytherm.o
obj-$(CONFIG_USB_EMI26) += emi26.o
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 32f0e3a5b02..e573c8ba978 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -281,8 +281,8 @@ static int appledisplay_probe(struct usb_interface *iface,
/* Register backlight device */
snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
atomic_inc_return(&count_displays) - 1);
- pdata->bd = backlight_device_register(bl_name, NULL,
- pdata, &appledisplay_bl_data);
+ pdata->bd = backlight_device_register(bl_name, NULL, pdata,
+ &appledisplay_bl_data);
if (IS_ERR(pdata->bd)) {
err("appledisplay: Backlight registration failed");
goto error;
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c
new file mode 100644
index 00000000000..60893c6c822
--- /dev/null
+++ b/drivers/usb/misc/berry_charge.c
@@ -0,0 +1,140 @@
+/*
+ * USB BlackBerry charging module
+ *
+ * Copyright (C) 2007 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * 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, version 2.
+ *
+ * Information on how to switch configs was taken by the bcharge.cc file
+ * created by the barry.sf.net project.
+ *
+ * bcharge.cc has the following copyright:
+ * Copyright (C) 2006, Net Direct Inc. (http://www.netdirect.ca/)
+ * and is released under the GPLv2.
+ *
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#define RIM_VENDOR 0x0fca
+#define BLACKBERRY 0x0001
+
+static int debug;
+
+#ifdef dbg
+#undef dbg
+#endif
+#define dbg(dev, format, arg...) \
+ if (debug) \
+ dev_printk(KERN_DEBUG , dev , format , ## arg)
+
+static struct usb_device_id id_table [] = {
+ { USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
+ { }, /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static int magic_charge(struct usb_device *udev)
+{
+ char *dummy_buffer = kzalloc(2, GFP_KERNEL);
+ int retval;
+
+ if (!dummy_buffer)
+ return -ENOMEM;
+
+ /* send two magic commands and then set the configuration. The device
+ * will then reset itself with the new power usage and should start
+ * charging. */
+
+ /* Note, with testing, it only seems that the first message is really
+ * needed (at least for the 8700c), but to be safe, we emulate what
+ * other operating systems seem to be sending to their device. We
+ * really need to get some specs for this device to be sure about what
+ * is going on here.
+ */
+ dbg(&udev->dev, "Sending first magic command\n");
+ retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0xa5, 0xc0, 0, 1, dummy_buffer, 2, 100);
+ if (retval != 2) {
+ dev_err(&udev->dev, "First magic command failed: %d.\n",
+ retval);
+ return retval;
+ }
+
+ dbg(&udev->dev, "Sending first magic command\n");
+ retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0xa2, 0x40, 0, 1, dummy_buffer, 0, 100);
+ if (retval != 0) {
+ dev_err(&udev->dev, "Second magic command failed: %d.\n",
+ retval);
+ return retval;
+ }
+
+ dbg(&udev->dev, "Calling set_configuration\n");
+ retval = usb_driver_set_configuration(udev, 1);
+ if (retval)
+ dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
+
+ return retval;
+}
+
+static int berry_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+
+ dbg(&udev->dev, "Power is set to %dmA\n",
+ udev->actconfig->desc.bMaxPower * 2);
+
+ /* check the power usage so we don't try to enable something that is
+ * already enabled */
+ if ((udev->actconfig->desc.bMaxPower * 2) == 500) {
+ dbg(&udev->dev, "device is already charging, power is "
+ "set to %dmA\n", udev->actconfig->desc.bMaxPower * 2);
+ return -ENODEV;
+ }
+
+ /* turn the power on */
+ magic_charge(udev);
+
+ /* we don't really want to bind to the device, userspace programs can
+ * handle the syncing just fine, so get outta here. */
+ return -ENODEV;
+}
+
+static void berry_disconnect(struct usb_interface *intf)
+{
+}
+
+static struct usb_driver berry_driver = {
+ .name = "berry_charge",
+ .probe = berry_probe,
+ .disconnect = berry_disconnect,
+ .id_table = id_table,
+};
+
+static int __init berry_init(void)
+{
+ return usb_register(&berry_driver);
+}
+
+static void __exit berry_exit(void)
+{
+ usb_deregister(&berry_driver);
+}
+
+module_init(berry_init);
+module_exit(berry_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index a2b94ef512b..0f3d7dbb537 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -84,6 +84,7 @@ config USB_PEGASUS
config USB_RTL8150
tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)"
depends on EXPERIMENTAL
+ select MII
help
Say Y here if you have RTL8150 based usb-ethernet adapter.
Send me <petkan@users.sourceforge.net> any comments you may have.
@@ -98,7 +99,7 @@ config USB_USBNET_MII
config USB_USBNET
tristate "Multi-purpose USB Networking Framework"
- select MII if USBNET_MII != n
+ select MII if USB_USBNET_MII != n
---help---
This driver supports several kinds of network links over USB,
with "minidrivers" built around a common network driver core
@@ -239,6 +240,7 @@ config USB_NET_RNDIS_HOST
config USB_NET_CDC_SUBSET
tristate "Simple USB Network Links (CDC Ethernet subset)"
depends on USB_USBNET
+ default y
help
This driver module supports USB network devices that can work
without any device-specific information. Select it if you have
@@ -298,6 +300,13 @@ config USB_EPSON2888
Choose this option to support the usb networking links used
by some sample firmware from Epson.
+config USB_KC2190
+ boolean "KT Technology KC2190 based cables (InstaNet)"
+ depends on USB_NET_CDC_SUBSET && EXPERIMENTAL
+ help
+  Choose this option if you're using a host-to-host cable
+  with one of these chips.
+
config USB_NET_ZAURUS
tristate "Sharp Zaurus (stock ROMs) and compatible"
depends on USB_USBNET
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index bd357e178e5..7ef2e4b5e39 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -351,9 +351,11 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
skb_push(skb, 4);
packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+ cpu_to_le32s(&packet_len);
memcpy(skb->data, &packet_len, sizeof(packet_len));
if ((skb->len % 512) == 0) {
+ cpu_to_le32s(&padbytes);
memcpy( skb->tail, &padbytes, sizeof(padbytes));
skb_put(skb, sizeof(padbytes));
}
diff --git a/drivers/usb/net/cdc_subset.c b/drivers/usb/net/cdc_subset.c
index ae8fb06cf38..bc62b012602 100644
--- a/drivers/usb/net/cdc_subset.c
+++ b/drivers/usb/net/cdc_subset.c
@@ -79,13 +79,19 @@ static int always_connected (struct usbnet *dev)
*
* ALi M5632 driver ... does high speed
*
+ * NOTE that the MS-Windows drivers for this chip use some funky and
+ * (naturally) undocumented 7-byte prefix to each packet, so this is a
+ * case where we don't currently interoperate. Also, once you unplug
+ * one end of the cable, you need to replug the other end too ... since
+ * chip docs are unavailable, there's no way to reset the relevant state
+ * short of a power cycle.
+ *
*-------------------------------------------------------------------------*/
static const struct driver_info ali_m5632_info = {
.description = "ALi M5632",
};
-
#endif
@@ -159,6 +165,11 @@ static const struct driver_info epson2888_info = {
#endif /* CONFIG_USB_EPSON2888 */
+/*-------------------------------------------------------------------------
+ *
+ * info from Jonathan McDowell <noodles@earth.li>
+ *
+ *-------------------------------------------------------------------------*/
#ifdef CONFIG_USB_KC2190
#define HAVE_HARDWARE
static const struct driver_info kc2190_info = {
@@ -223,6 +234,10 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x0402, 0x5632), // ALi defaults
.driver_info = (unsigned long) &ali_m5632_info,
},
+{
+ USB_DEVICE (0x182d,0x207c), // SiteCom CN-124
+ .driver_info = (unsigned long) &ali_m5632_info,
+},
#endif
#ifdef CONFIG_USB_AN2720
@@ -314,13 +329,13 @@ static struct usb_driver cdc_subset_driver = {
static int __init cdc_subset_init(void)
{
- return usb_register(&cdc_subset_driver);
+ return usb_register(&cdc_subset_driver);
}
module_init(cdc_subset_init);
static void __exit cdc_subset_exit(void)
{
- usb_deregister(&cdc_subset_driver);
+ usb_deregister(&cdc_subset_driver);
}
module_exit(cdc_subset_exit);
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 43ba61abfcc..de69b183bd2 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -147,7 +147,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
if (tmp < 0)
return tmp;
}
-
+
dev->in = usb_rcvbulkpipe (dev->udev,
in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
dev->out = usb_sndbulkpipe (dev->udev,
@@ -327,7 +327,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
if (netif_running (dev->net)
&& netif_device_present (dev->net)
&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
- switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
+ switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
case -EPIPE:
usbnet_defer_kevent (dev, EVENT_RX_HALT);
break;
@@ -443,7 +443,7 @@ block:
case -EOVERFLOW:
dev->stats.rx_over_errors++;
// FALLTHROUGH
-
+
default:
entry->state = rx_cleanup;
dev->stats.rx_errors++;
@@ -560,7 +560,7 @@ static int usbnet_stop (struct net_device *net)
if (netif_msg_ifdown (dev))
devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
- dev->stats.rx_packets, dev->stats.tx_packets,
+ dev->stats.rx_packets, dev->stats.tx_packets,
dev->stats.rx_errors, dev->stats.tx_errors
);
@@ -578,7 +578,7 @@ static int usbnet_stop (struct net_device *net)
devdbg (dev, "waited for %d urb completions", temp);
}
dev->wait = NULL;
- remove_wait_queue (&unlink_wakeup, &wait);
+ remove_wait_queue (&unlink_wakeup, &wait);
usb_kill_urb(dev->interrupt);
@@ -834,7 +834,7 @@ kevent (struct work_struct *work)
}
if (test_bit (EVENT_LINK_RESET, &dev->flags)) {
- struct driver_info *info = dev->driver_info;
+ struct driver_info *info = dev->driver_info;
int retval = 0;
clear_bit (EVENT_LINK_RESET, &dev->flags);
@@ -1066,7 +1066,7 @@ static void usbnet_bh (unsigned long param)
* USB Device Driver support
*
*-------------------------------------------------------------------------*/
-
+
// precondition: never called in_interrupt
void usbnet_disconnect (struct usb_interface *intf)
@@ -1087,7 +1087,7 @@ void usbnet_disconnect (struct usb_interface *intf)
intf->dev.driver->name,
xdev->bus->bus_name, xdev->devpath,
dev->driver_info->description);
-
+
net = dev->net;
unregister_netdev (net);
@@ -1111,7 +1111,7 @@ int
usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
{
struct usbnet *dev;
- struct net_device *net;
+ struct net_device *net;
struct usb_host_interface *interface;
struct driver_info *info;
struct usb_device *xdev;
@@ -1181,6 +1181,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
// NOTE net->name still not usable ...
if (info->bind) {
status = info->bind (dev, udev);
+ if (status < 0)
+ goto out1;
+
// heuristic: "usb%d" for links we know are two-host,
// else "eth%d" when there's reasonable doubt. userspace
// can rename the link if it knows better.
@@ -1207,12 +1210,12 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
if (status == 0 && dev->status)
status = init_status (dev, udev);
if (status < 0)
- goto out1;
+ goto out3;
if (!dev->rx_urb_size)
dev->rx_urb_size = dev->hard_mtu;
dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
-
+
SET_NETDEV_DEV(net, &udev->dev);
status = register_netdev (net);
if (status)
@@ -1255,7 +1258,7 @@ EXPORT_SYMBOL_GPL(usbnet_probe);
int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
-
+
/* accelerate emptying of the rx and queues, to avoid
* having everything error out.
*/
@@ -1286,7 +1289,7 @@ static int __init usbnet_init(void)
< sizeof (struct skb_data));
random_ether_addr(node_id);
- return 0;
+ return 0;
}
module_init(usbnet_init);
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 0af42e32fa0..18816bf96a4 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -58,11 +58,6 @@ static void airprime_read_bulk_callback(struct urb *urb)
if (urb->status) {
dbg("%s - nonzero read bulk status received: %d",
__FUNCTION__, urb->status);
- /* something happened, so free up the memory for this urb */
- if (urb->transfer_buffer) {
- kfree (urb->transfer_buffer);
- urb->transfer_buffer = NULL;
- }
return;
}
usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
@@ -146,6 +141,8 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
airprime_read_bulk_callback, port);
result = usb_submit_urb(urb, GFP_KERNEL);
if (result) {
+ usb_free_urb(urb);
+ kfree(buffer);
dev_err(&port->dev,
"%s - failed submitting read urb %d for port %d, error %d\n",
__FUNCTION__, i, port->number, result);
@@ -160,27 +157,12 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
/* some error happened, cancel any submitted urbs and clean up anything that
got allocated successfully */
- for ( ; i >= 0; --i) {
+ while (i-- != 0) {
urb = priv->read_urbp[i];
- if (urb) {
- /* This urb was submitted successfully. So we have to
- cancel it.
- Unlinking the urb will invoke read_bulk_callback()
- with an error status, so its transfer buffer will
- be freed there */
- if (usb_unlink_urb (urb) != -EINPROGRESS) {
- /* comments in drivers/usb/core/urb.c say this
- can only happen if the urb was never submitted,
- or has completed already.
- Either way we may have to free the transfer
- buffer here. */
- if (urb->transfer_buffer) {
- kfree (urb->transfer_buffer);
- urb->transfer_buffer = NULL;
- }
- }
- usb_free_urb (urb);
- }
+ buffer = urb->transfer_buffer;
+ usb_kill_urb (urb);
+ usb_free_urb (urb);
+ kfree (buffer);
}
out:
@@ -194,10 +176,9 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
dbg("%s - port %d", __FUNCTION__, port->number);
- /* killing the urb will invoke read_bulk_callback() with an error status,
- so the transfer buffer will be freed there */
for (i = 0; i < NUM_READ_URBS; ++i) {
usb_kill_urb (priv->read_urbp[i]);
+ kfree (priv->read_urbp[i]->transfer_buffer);
usb_free_urb (priv->read_urbp[i]);
}
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 3ec24870bca..db623e75489 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -69,6 +69,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */
{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
{ } /* Terminating Entry */
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 601e0648dec..53baeec8f26 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -66,6 +66,8 @@ struct usb_serial_driver usb_serial_generic_device = {
.num_bulk_out = NUM_DONT_CARE,
.num_ports = 1,
.shutdown = usb_serial_generic_shutdown,
+ .throttle = usb_serial_generic_throttle,
+ .unthrottle = usb_serial_generic_unthrottle,
};
static int generic_probe(struct usb_interface *interface,
@@ -115,6 +117,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
int result = 0;
+ unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -124,7 +127,13 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
if (port->tty)
port->tty->low_latency = 1;
- /* if we have a bulk interrupt, start reading from it */
+ /* clear the throttle flags */
+ spin_lock_irqsave(&port->lock, flags);
+ port->throttled = 0;
+ port->throttle_req = 0;
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /* if we have a bulk endpoint, start reading from it */
if (serial->num_bulk_in) {
/* Start reading from the device */
usb_fill_bulk_urb (port->read_urb, serial->dev,
@@ -253,31 +262,22 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
return (chars);
}
-void usb_serial_generic_read_bulk_callback (struct urb *urb)
+/* Push data to tty layer and resubmit the bulk read URB */
+static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
{
- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial = port->serial;
- struct tty_struct *tty;
- unsigned char *data = urb->transfer_buffer;
+ struct urb *urb = port->read_urb;
+ struct tty_struct *tty = port->tty;
int result;
- dbg("%s - port %d", __FUNCTION__, port->number);
-
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
- return;
- }
-
- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
-
- tty = port->tty;
+ /* Push data to tty */
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length);
- tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
+ tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length);
+ tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
}
- /* Continue trying to always read */
+ /* Continue reading from device */
usb_fill_bulk_urb (port->read_urb, serial->dev,
usb_rcvbulkpipe (serial->dev,
port->bulk_in_endpointAddress),
@@ -290,6 +290,40 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
if (result)
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
}
+
+void usb_serial_generic_read_bulk_callback (struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ int is_throttled;
+ unsigned long flags;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (urb->status) {
+ dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ return;
+ }
+
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+
+ /* Throttle the device if requested by tty */
+ if (urb->actual_length) {
+ spin_lock_irqsave(&port->lock, flags);
+ is_throttled = port->throttled = port->throttle_req;
+ spin_unlock_irqrestore(&port->lock, flags);
+ if (is_throttled) {
+ /* Let the received data linger in the read URB;
+ * usb_serial_generic_unthrottle() will pick it
+ * up later. */
+ dbg("%s - throttling device", __FUNCTION__);
+ return;
+ }
+ }
+
+ /* Handle data and continue reading from device */
+ flush_and_resubmit_read_urb(port);
+}
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
void usb_serial_generic_write_bulk_callback (struct urb *urb)
@@ -308,6 +342,38 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb)
}
EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
+void usb_serial_generic_throttle (struct usb_serial_port *port)
+{
+ unsigned long flags;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ /* Set the throttle request flag. It will be picked up
+ * by usb_serial_generic_read_bulk_callback(). */
+ spin_lock_irqsave(&port->lock, flags);
+ port->throttle_req = 1;
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+void usb_serial_generic_unthrottle (struct usb_serial_port *port)
+{
+ int was_throttled;
+ unsigned long flags;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ /* Clear the throttle flags */
+ spin_lock_irqsave(&port->lock, flags);
+ was_throttled = port->throttled;
+ port->throttled = port->throttle_req = 0;
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (was_throttled) {
+ /* Handle pending data and resume reading from device */
+ flush_and_resubmit_read_urb(port);
+ }
+}
+
void usb_serial_generic_shutdown (struct usb_serial *serial)
{
int i;
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index ced9f32b29d..9963a8b7584 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -69,7 +69,6 @@ static int option_send_setup(struct usb_serial_port *port);
/* Vendor and product IDs */
#define OPTION_VENDOR_ID 0x0AF0
#define HUAWEI_VENDOR_ID 0x12D1
-#define AUDIOVOX_VENDOR_ID 0x0F3D
#define NOVATELWIRELESS_VENDOR_ID 0x1410
#define ANYDATA_VENDOR_ID 0x16d5
@@ -81,7 +80,6 @@ static int option_send_setup(struct usb_serial_port *port);
#define OPTION_PRODUCT_GTMAX36 0x6701
#define HUAWEI_PRODUCT_E600 0x1001
#define HUAWEI_PRODUCT_E220 0x1003
-#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
#define NOVATELWIRELESS_PRODUCT_U740 0x1400
#define ANYDATA_PRODUCT_ID 0x6501
@@ -94,7 +92,6 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
- { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
{ } /* Terminating entry */
@@ -109,7 +106,6 @@ static struct usb_device_id option_ids1[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTMAX36) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
- { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
{ } /* Terminating entry */
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 6c083d4e2c9..83dfae93a45 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -83,6 +83,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
{ USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
+ { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 65a5039665e..f9a71d0c102 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -97,3 +97,8 @@
/* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */
#define HUAWEI_VENDOR_ID 0x12d1
#define HUAWEI_PRODUCT_ID 0x1001
+
+/* Willcom WS002IN Data Driver (by NetIndex Inc.) */
+#define WS002IN_VENDOR_ID 0x11f6
+#define WS002IN_PRODUCT_ID 0x2001
+
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 70234f5dbee..e227f64d564 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -153,6 +153,12 @@ static int slave_configure(struct scsi_device *sdev)
if (us->flags & US_FL_FIX_CAPACITY)
sdev->fix_capacity = 1;
+ /* A few disks have two indistinguishable version, one of
+ * which reports the correct capacity and the other does not.
+ * The sd driver has to guess which is the case. */
+ if (us->flags & US_FL_CAPACITY_HEURISTICS)
+ sdev->guess_capacity = 1;
+
/* Some devices report a SCSI revision level above 2 but are
* unable to handle the REPORT LUNS command (for which
* support is mandatory at level 3). Since we already have
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index f49a62fc32d..9644a8ea4aa 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1101,6 +1101,15 @@ UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN),
+/* Submitted by Dylan Taft <d13f00l@gmail.com>
+ * US_FL_IGNORE_RESIDUE Needed
+ */
+UNUSUAL_DEV( 0x08ca, 0x3103, 0x0100, 0x0100,
+ "AIPTEK",
+ "Aiptek USB Keychain MP3 Player",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE),
+
/* Entry needed for flags. Moreover, all devices with this ID use
* bulk-only transport, but _some_ falsely report Control/Bulk instead.
* One example is "Trumpion Digital Research MYMP3".
@@ -1311,12 +1320,13 @@ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_NO_WP_DETECT ),
-/* Reported by Jan Mate <mate@fiit.stuba.sk> */
+/* Reported by Jan Mate <mate@fiit.stuba.sk>
+ * and by Soeren Sonnenburg <kernel@nn7.de> */
UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000,
"Sony Ericsson",
"P990i",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_CAPACITY ),
+ US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
/* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */
UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000,
@@ -1385,6 +1395,16 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Thomas Baechler <thomas@archlinux.org>
+ * Fixes I/O errors with Teac HD-35PU devices
+ */
+
+UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
+ "Super Top",
+ "USB 2.0 IDE DEVICE",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE),
+
/* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
* and Renato Perini <rperini@email.it>
*/
@@ -1423,7 +1443,7 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001,
"DataStor",
"USB4500 FW1.04",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_CAPACITY),
+ US_FL_CAPACITY_HEURISTICS),
/* Control/Bulk transport for all SubClass values */
USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 296b091cf16..46929a1b6f2 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -90,13 +90,15 @@ static int skel_open(struct inode *inode, struct file *file)
goto exit;
}
+ /* increment our usage count for the device */
+ kref_get(&dev->kref);
+
/* prevent the device from being autosuspended */
retval = usb_autopm_get_interface(interface);
- if (retval)
+ if (retval) {
+ kref_put(&dev->kref, skel_delete);
goto exit;
-
- /* increment our usage count for the device */
- kref_get(&dev->kref);
+ }
/* save our object in the file's private structure */
file->private_data = dev;
diff --git a/fs/Kconfig b/fs/Kconfig
index a722b5a3f75..3c4886b849f 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1189,32 +1189,6 @@ config EFS_FS
To compile the EFS file system support as a module, choose M here: the
module will be called efs.
-config JFFS_FS
- tristate "Journalling Flash File System (JFFS) support"
- depends on MTD && BLOCK && BROKEN
- help
- JFFS is the Journalling Flash File System developed by Axis
- Communications in Sweden, aimed at providing a crash/powerdown-safe
- file system for disk-less embedded devices. Further information is
- available at (<http://developer.axis.com/software/jffs/>).
-
- NOTE: This filesystem is deprecated and is scheduled for removal in
- 2.6.21. See Documentation/feature-removal-schedule.txt
-
-config JFFS_FS_VERBOSE
- int "JFFS debugging verbosity (0 = quiet, 3 = noisy)"
- depends on JFFS_FS
- default "0"
- help
- Determines the verbosity level of the JFFS debugging messages.
-
-config JFFS_PROC_FS
- bool "JFFS stats available in /proc filesystem"
- depends on JFFS_FS && PROC_FS
- help
- Enabling this option will cause statistics from mounted JFFS file systems
- to be made available to the user in the /proc/fs/jffs/ directory.
-
config JFFS2_FS
tristate "Journalling Flash File System v2 (JFFS2) support"
select CRC32
diff --git a/fs/Makefile b/fs/Makefile
index b9ffa63f77f..9edf4112bee 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -94,7 +94,6 @@ obj-$(CONFIG_HPFS_FS) += hpfs/
obj-$(CONFIG_NTFS_FS) += ntfs/
obj-$(CONFIG_UFS_FS) += ufs/
obj-$(CONFIG_EFS_FS) += efs/
-obj-$(CONFIG_JFFS_FS) += jffs/
obj-$(CONFIG_JFFS2_FS) += jffs2/
obj-$(CONFIG_AFFS_FS) += affs/
obj-$(CONFIG_ROMFS_FS) += romfs/
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 8d130cc8532..682f928b7f4 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
+#include <linux/namei.h>
#include <linux/debugfs.h>
static ssize_t default_read_file(struct file *file, char __user *buf,
@@ -44,6 +45,17 @@ const struct file_operations debugfs_file_operations = {
.open = default_open,
};
+static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ nd_set_link(nd, dentry->d_inode->i_private);
+ return NULL;
+}
+
+const struct inode_operations debugfs_link_operations = {
+ .readlink = generic_readlink,
+ .follow_link = debugfs_follow_link,
+};
+
static void debugfs_u8_set(void *data, u64 val)
{
*(u8 *)data = val;
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index c692487346e..7b324cfebcb 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -25,11 +25,13 @@
#include <linux/namei.h>
#include <linux/debugfs.h>
#include <linux/fsnotify.h>
+#include <linux/string.h>
#define DEBUGFS_MAGIC 0x64626720
/* declared over in file.c */
extern struct file_operations debugfs_file_operations;
+extern struct inode_operations debugfs_link_operations;
static struct vfsmount *debugfs_mount;
static int debugfs_mount_count;
@@ -51,6 +53,9 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
case S_IFREG:
inode->i_fop = &debugfs_file_operations;
break;
+ case S_IFLNK:
+ inode->i_op = &debugfs_link_operations;
+ break;
case S_IFDIR:
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
@@ -96,6 +101,12 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
return res;
}
+static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode)
+{
+ mode = (mode & S_IALLUGO) | S_IFLNK;
+ return debugfs_mknod(dir, dentry, mode, 0);
+}
+
static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
{
int res;
@@ -158,10 +169,17 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
mutex_lock(&parent->d_inode->i_mutex);
*dentry = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(*dentry)) {
- if ((mode & S_IFMT) == S_IFDIR)
+ switch (mode & S_IFMT) {
+ case S_IFDIR:
error = debugfs_mkdir(parent->d_inode, *dentry, mode);
- else
+ break;
+ case S_IFLNK:
+ error = debugfs_link(parent->d_inode, *dentry, mode);
+ break;
+ default:
error = debugfs_create(parent->d_inode, *dentry, mode);
+ break;
+ }
dput(*dentry);
} else
error = PTR_ERR(*dentry);
@@ -194,9 +212,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
* you are responsible here.) If an error occurs, %NULL will be returned.
*
* If debugfs is not enabled in the kernel, the value -%ENODEV will be
- * returned. It is not wise to check for this value, but rather, check for
- * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
- * code.
+ * returned.
*/
struct dentry *debugfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
@@ -246,9 +262,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file);
* you are responsible here.) If an error occurs, %NULL will be returned.
*
* If debugfs is not enabled in the kernel, the value -%ENODEV will be
- * returned. It is not wise to check for this value, but rather, check for
- * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
- * code.
+ * returned.
*/
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
{
@@ -259,6 +273,47 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
EXPORT_SYMBOL_GPL(debugfs_create_dir);
/**
+ * debugfs_create_symlink- create a symbolic link in the debugfs filesystem
+ * @name: a pointer to a string containing the name of the symbolic link to
+ * create.
+ * @parent: a pointer to the parent dentry for this symbolic link. This
+ * should be a directory dentry if set. If this paramater is NULL,
+ * then the symbolic link will be created in the root of the debugfs
+ * filesystem.
+ * @target: a pointer to a string containing the path to the target of the
+ * symbolic link.
+ *
+ * This function creates a symbolic link with the given name in debugfs that
+ * links to the given target path.
+ *
+ * This function will return a pointer to a dentry if it succeeds. This
+ * pointer must be passed to the debugfs_remove() function when the symbolic
+ * link is to be removed (no automatic cleanup happens if your module is
+ * unloaded, you are responsible here.) If an error occurs, %NULL will be
+ * returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
+ const char *target)
+{
+ struct dentry *result;
+ char *link;
+
+ link = kstrdup(target, GFP_KERNEL);
+ if (!link)
+ return NULL;
+
+ result = debugfs_create_file(name, S_IFLNK | S_IRWXUGO, parent, link,
+ NULL);
+ if (!result)
+ kfree(link);
+ return result;
+}
+EXPORT_SYMBOL_GPL(debugfs_create_symlink);
+
+/**
* debugfs_remove - removes a file or directory from the debugfs filesystem
* @dentry: a pointer to a the dentry of the file or directory to be
* removed.
@@ -287,15 +342,22 @@ void debugfs_remove(struct dentry *dentry)
if (debugfs_positive(dentry)) {
if (dentry->d_inode) {
dget(dentry);
- if (S_ISDIR(dentry->d_inode->i_mode)) {
+ switch (dentry->d_inode->i_mode & S_IFMT) {
+ case S_IFDIR:
ret = simple_rmdir(parent->d_inode, dentry);
if (ret)
printk(KERN_ERR
"DebugFS rmdir on %s failed : "
"directory not empty.\n",
dentry->d_name.name);
- } else
+ break;
+ case S_IFLNK:
+ kfree(dentry->d_inode->i_private);
+ /* fall through */
+ default:
simple_unlink(parent->d_inode, dentry);
+ break;
+ }
if (!ret)
d_delete(dentry);
dput(dentry);
diff --git a/fs/jffs/Makefile b/fs/jffs/Makefile
deleted file mode 100644
index 9c1c0bb5969..00000000000
--- a/fs/jffs/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the linux Journalling Flash FileSystem (JFFS) routines.
-#
-# $Id: Makefile,v 1.11 2001/09/25 20:59:41 dwmw2 Exp $
-#
-
-obj-$(CONFIG_JFFS_FS) += jffs.o
-
-jffs-y := jffs_fm.o intrep.o inode-v23.o
-jffs-$(CONFIG_JFFS_PROC_FS) += jffs_proc.o
-jffs-objs := $(jffs-y)
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
deleted file mode 100644
index 9602b925da0..00000000000
--- a/fs/jffs/inode-v23.c
+++ /dev/null
@@ -1,1847 +0,0 @@
-/*
- * JFFS -- Journalling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000 Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * 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.
- *
- * $Id: inode-v23.c,v 1.70 2001/10/02 09:16:02 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- * Copyright 2000, 2001 Red Hat, Inc.
- */
-
-/* inode.c -- Contains the code that is called from the VFS. */
-
-/* TODO-ALEX:
- * uid and gid are just 16 bit.
- * jffs_file_write reads from user-space pointers without xx_from_user
- * maybe other stuff do to.
- */
-
-#include <linux/time.h>
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/jffs.h>
-#include <linux/fs.h>
-#include <linux/smp_lock.h>
-#include <linux/ioctl.h>
-#include <linux/stat.h>
-#include <linux/blkdev.h>
-#include <linux/quotaops.h>
-#include <linux/highmem.h>
-#include <linux/vfs.h>
-#include <linux/mutex.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-#include "jffs_fm.h"
-#include "intrep.h"
-#ifdef CONFIG_JFFS_PROC_FS
-#include "jffs_proc.h"
-#endif
-
-static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
-
-static const struct super_operations jffs_ops;
-static const struct file_operations jffs_file_operations;
-static const struct inode_operations jffs_file_inode_operations;
-static const struct file_operations jffs_dir_operations;
-static const struct inode_operations jffs_dir_inode_operations;
-static const struct address_space_operations jffs_address_operations;
-
-struct kmem_cache *node_cache = NULL;
-struct kmem_cache *fm_cache = NULL;
-
-/* Called by the VFS at mount time to initialize the whole file system. */
-static int jffs_fill_super(struct super_block *sb, void *data, int silent)
-{
- struct inode *root_inode;
- struct jffs_control *c;
-
- sb->s_flags |= MS_NODIRATIME;
-
- D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n",
- sb->s_id));
-
- if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) {
- printk(KERN_WARNING "JFFS: Trying to mount a "
- "non-mtd device.\n");
- return -EINVAL;
- }
-
- sb->s_blocksize = PAGE_CACHE_SIZE;
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
- sb->s_fs_info = (void *) 0;
- sb->s_maxbytes = 0xFFFFFFFF;
-
- /* Build the file system. */
- if (jffs_build_fs(sb) < 0) {
- goto jffs_sb_err1;
- }
-
- /*
- * set up enough so that we can read an inode
- */
- sb->s_magic = JFFS_MAGIC_SB_BITMASK;
- sb->s_op = &jffs_ops;
-
- root_inode = iget(sb, JFFS_MIN_INO);
- if (!root_inode)
- goto jffs_sb_err2;
-
- /* Get the root directory of this file system. */
- if (!(sb->s_root = d_alloc_root(root_inode))) {
- goto jffs_sb_err3;
- }
-
- c = (struct jffs_control *) sb->s_fs_info;
-
-#ifdef CONFIG_JFFS_PROC_FS
- /* Set up the jffs proc file system. */
- if (jffs_register_jffs_proc_dir(MINOR(sb->s_dev), c) < 0) {
- printk(KERN_WARNING "JFFS: Failed to initialize the JFFS "
- "proc file system for device %s.\n",
- sb->s_id);
- }
-#endif
-
- /* Set the Garbage Collection thresholds */
-
- /* GC if free space goes below 5% of the total size */
- c->gc_minfree_threshold = c->fmc->flash_size / 20;
-
- if (c->gc_minfree_threshold < c->fmc->sector_size)
- c->gc_minfree_threshold = c->fmc->sector_size;
-
- /* GC if dirty space exceeds 33% of the total size. */
- c->gc_maxdirty_threshold = c->fmc->flash_size / 3;
-
- if (c->gc_maxdirty_threshold < c->fmc->sector_size)
- c->gc_maxdirty_threshold = c->fmc->sector_size;
-
-
- c->thread_pid = kernel_thread (jffs_garbage_collect_thread,
- (void *) c,
- CLONE_KERNEL);
- D1(printk(KERN_NOTICE "JFFS: GC thread pid=%d.\n", (int) c->thread_pid));
-
- D1(printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n",
- sb->s_id));
- return 0;
-
-jffs_sb_err3:
- iput(root_inode);
-jffs_sb_err2:
- jffs_cleanup_control((struct jffs_control *)sb->s_fs_info);
-jffs_sb_err1:
- printk(KERN_WARNING "JFFS: Failed to mount device %s.\n",
- sb->s_id);
- return -EINVAL;
-}
-
-
-/* This function is called when the file system is umounted. */
-static void
-jffs_put_super(struct super_block *sb)
-{
- struct jffs_control *c = (struct jffs_control *) sb->s_fs_info;
-
- D2(printk("jffs_put_super()\n"));
-
-#ifdef CONFIG_JFFS_PROC_FS
- jffs_unregister_jffs_proc_dir(c);
-#endif
-
- if (c->gc_task) {
- D1(printk (KERN_NOTICE "jffs_put_super(): Telling gc thread to die.\n"));
- send_sig(SIGKILL, c->gc_task, 1);
- }
- wait_for_completion(&c->gc_thread_comp);
-
- D1(printk (KERN_NOTICE "jffs_put_super(): Successfully waited on thread.\n"));
-
- jffs_cleanup_control((struct jffs_control *)sb->s_fs_info);
- D1(printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n",
- sb->s_id));
-}
-
-
-/* This function is called when user commands like chmod, chgrp and
- chown are executed. System calls like trunc() results in a call
- to this function. */
-static int
-jffs_setattr(struct dentry *dentry, struct iattr *iattr)
-{
- struct inode *inode = dentry->d_inode;
- struct jffs_raw_inode raw_inode;
- struct jffs_control *c;
- struct jffs_fmcontrol *fmc;
- struct jffs_file *f;
- struct jffs_node *new_node;
- int update_all;
- int res = 0;
- int recoverable = 0;
-
- lock_kernel();
-
- if ((res = inode_change_ok(inode, iattr)))
- goto out;
-
- c = (struct jffs_control *)inode->i_sb->s_fs_info;
- fmc = c->fmc;
-
- D3(printk (KERN_NOTICE "notify_change(): down biglock\n"));
- mutex_lock(&fmc->biglock);
-
- f = jffs_find_file(c, inode->i_ino);
-
- ASSERT(if (!f) {
- printk("jffs_setattr(): Invalid inode number: %lu\n",
- inode->i_ino);
- D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
- mutex_unlock(&fmc->biglock);
- res = -EINVAL;
- goto out;
- });
-
- D1(printk("***jffs_setattr(): file: \"%s\", ino: %u\n",
- f->name, f->ino));
-
- update_all = iattr->ia_valid & ATTR_FORCE;
-
- if ( (update_all || iattr->ia_valid & ATTR_SIZE)
- && (iattr->ia_size + 128 < f->size) ) {
- /* We're shrinking the file by more than 128 bytes.
- We'll be able to GC and recover this space, so
- allow it to go into the reserved space. */
- recoverable = 1;
- }
-
- if (!(new_node = jffs_alloc_node())) {
- D(printk("jffs_setattr(): Allocation failed!\n"));
- D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
- mutex_unlock(&fmc->biglock);
- res = -ENOMEM;
- goto out;
- }
-
- new_node->data_offset = 0;
- new_node->removed_size = 0;
- raw_inode.magic = JFFS_MAGIC_BITMASK;
- raw_inode.ino = f->ino;
- raw_inode.pino = f->pino;
- raw_inode.mode = f->mode;
- raw_inode.uid = f->uid;
- raw_inode.gid = f->gid;
- raw_inode.atime = f->atime;
- raw_inode.mtime = f->mtime;
- raw_inode.ctime = f->ctime;
- raw_inode.dsize = 0;
- raw_inode.offset = 0;
- raw_inode.rsize = 0;
- raw_inode.dsize = 0;
- raw_inode.nsize = f->nsize;
- raw_inode.nlink = f->nlink;
- raw_inode.spare = 0;
- raw_inode.rename = 0;
- raw_inode.deleted = 0;
-
- if (update_all || iattr->ia_valid & ATTR_MODE) {
- raw_inode.mode = iattr->ia_mode;
- inode->i_mode = iattr->ia_mode;
- }
- if (update_all || iattr->ia_valid & ATTR_UID) {
- raw_inode.uid = iattr->ia_uid;
- inode->i_uid = iattr->ia_uid;
- }
- if (update_all || iattr->ia_valid & ATTR_GID) {
- raw_inode.gid = iattr->ia_gid;
- inode->i_gid = iattr->ia_gid;
- }
- if (update_all || iattr->ia_valid & ATTR_SIZE) {
- int len;
- D1(printk("jffs_notify_change(): Changing size "
- "to %lu bytes!\n", (long)iattr->ia_size));
- raw_inode.offset = iattr->ia_size;
-
- /* Calculate how many bytes need to be removed from
- the end. */
- if (f->size < iattr->ia_size) {
- len = 0;
- }
- else {
- len = f->size - iattr->ia_size;
- }
-
- raw_inode.rsize = len;
-
- /* The updated node will be a removal node, with
- base at the new size and size of the nbr of bytes
- to be removed. */
- new_node->data_offset = iattr->ia_size;
- new_node->removed_size = len;
- inode->i_size = iattr->ia_size;
- inode->i_blocks = (inode->i_size + 511) >> 9;
-
- if (len) {
- invalidate_mapping_pages(inode->i_mapping, 0, -1);
- }
- inode->i_ctime = CURRENT_TIME_SEC;
- inode->i_mtime = inode->i_ctime;
- }
- if (update_all || iattr->ia_valid & ATTR_ATIME) {
- raw_inode.atime = iattr->ia_atime.tv_sec;
- inode->i_atime = iattr->ia_atime;
- }
- if (update_all || iattr->ia_valid & ATTR_MTIME) {
- raw_inode.mtime = iattr->ia_mtime.tv_sec;
- inode->i_mtime = iattr->ia_mtime;
- }
- if (update_all || iattr->ia_valid & ATTR_CTIME) {
- raw_inode.ctime = iattr->ia_ctime.tv_sec;
- inode->i_ctime = iattr->ia_ctime;
- }
-
- /* Write this node to the flash. */
- if ((res = jffs_write_node(c, new_node, &raw_inode, f->name, NULL, recoverable, f)) < 0) {
- D(printk("jffs_notify_change(): The write failed!\n"));
- jffs_free_node(new_node);
- D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- goto out;
- }
-
- jffs_insert_node(c, f, &raw_inode, NULL, new_node);
-
- mark_inode_dirty(inode);
- D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
-out:
- unlock_kernel();
- return res;
-} /* jffs_notify_change() */
-
-
-static struct inode *
-jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
- int * err)
-{
- struct super_block * sb;
- struct inode * inode;
- struct jffs_control *c;
- struct jffs_file *f;
-
- sb = dir->i_sb;
- inode = new_inode(sb);
- if (!inode) {
- *err = -ENOMEM;
- return NULL;
- }
-
- c = (struct jffs_control *)sb->s_fs_info;
-
- inode->i_ino = raw_inode->ino;
- inode->i_mode = raw_inode->mode;
- inode->i_nlink = raw_inode->nlink;
- inode->i_uid = raw_inode->uid;
- inode->i_gid = raw_inode->gid;
- inode->i_size = raw_inode->dsize;
- inode->i_atime.tv_sec = raw_inode->atime;
- inode->i_mtime.tv_sec = raw_inode->mtime;
- inode->i_ctime.tv_sec = raw_inode->ctime;
- inode->i_ctime.tv_nsec = 0;
- inode->i_mtime.tv_nsec = 0;
- inode->i_atime.tv_nsec = 0;
- inode->i_blocks = (inode->i_size + 511) >> 9;
-
- f = jffs_find_file(c, raw_inode->ino);
-
- inode->i_private = (void *)f;
- insert_inode_hash(inode);
-
- return inode;
-}
-
-/* Get statistics of the file system. */
-static int
-jffs_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
- struct jffs_control *c = (struct jffs_control *) dentry->d_sb->s_fs_info;
- struct jffs_fmcontrol *fmc;
-
- lock_kernel();
-
- fmc = c->fmc;
-
- D2(printk("jffs_statfs()\n"));
-
- buf->f_type = JFFS_MAGIC_SB_BITMASK;
- buf->f_bsize = PAGE_CACHE_SIZE;
- buf->f_blocks = (fmc->flash_size / PAGE_CACHE_SIZE)
- - (fmc->min_free_size / PAGE_CACHE_SIZE);
- buf->f_bfree = (jffs_free_size1(fmc) + jffs_free_size2(fmc) +
- fmc->dirty_size - fmc->min_free_size)
- >> PAGE_CACHE_SHIFT;
- buf->f_bavail = buf->f_bfree;
-
- /* Find out how many files there are in the filesystem. */
- buf->f_files = jffs_foreach_file(c, jffs_file_count);
- buf->f_ffree = buf->f_bfree;
- /* buf->f_fsid = 0; */
- buf->f_namelen = JFFS_MAX_NAME_LEN;
-
- unlock_kernel();
-
- return 0;
-}
-
-
-/* Rename a file. */
-static int
-jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
-{
- struct jffs_raw_inode raw_inode;
- struct jffs_control *c;
- struct jffs_file *old_dir_f;
- struct jffs_file *new_dir_f;
- struct jffs_file *del_f;
- struct jffs_file *f;
- struct jffs_node *node;
- struct inode *inode;
- int result = 0;
- __u32 rename_data = 0;
-
- D2(printk("***jffs_rename()\n"));
-
- D(printk("jffs_rename(): old_dir: 0x%p, old name: 0x%p, "
- "new_dir: 0x%p, new name: 0x%p\n",
- old_dir, old_dentry->d_name.name,
- new_dir, new_dentry->d_name.name));
-
- lock_kernel();
- c = (struct jffs_control *)old_dir->i_sb->s_fs_info;
- ASSERT(if (!c) {
- printk(KERN_ERR "jffs_rename(): The old_dir inode "
- "didn't have a reference to a jffs_file struct\n");
- unlock_kernel();
- return -EIO;
- });
-
- result = -ENOTDIR;
- if (!(old_dir_f = old_dir->i_private)) {
- D(printk("jffs_rename(): Old dir invalid.\n"));
- goto jffs_rename_end;
- }
-
- /* Try to find the file to move. */
- result = -ENOENT;
- if (!(f = jffs_find_child(old_dir_f, old_dentry->d_name.name,
- old_dentry->d_name.len))) {
- goto jffs_rename_end;
- }
-
- /* Find the new directory. */
- result = -ENOTDIR;
- if (!(new_dir_f = new_dir->i_private)) {
- D(printk("jffs_rename(): New dir invalid.\n"));
- goto jffs_rename_end;
- }
- D3(printk (KERN_NOTICE "rename(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
- /* Create a node and initialize as much as needed. */
- result = -ENOMEM;
- if (!(node = jffs_alloc_node())) {
- D(printk("jffs_rename(): Allocation failed: node == 0\n"));
- goto jffs_rename_end;
- }
- node->data_offset = 0;
- node->removed_size = 0;
-
- /* Initialize the raw inode. */
- raw_inode.magic = JFFS_MAGIC_BITMASK;
- raw_inode.ino = f->ino;
- raw_inode.pino = new_dir_f->ino;
-/* raw_inode.version = f->highest_version + 1; */
- raw_inode.mode = f->mode;
- raw_inode.uid = current->fsuid;
- raw_inode.gid = current->fsgid;
-#if 0
- raw_inode.uid = f->uid;
- raw_inode.gid = f->gid;
-#endif
- raw_inode.atime = get_seconds();
- raw_inode.mtime = raw_inode.atime;
- raw_inode.ctime = f->ctime;
- raw_inode.offset = 0;
- raw_inode.dsize = 0;
- raw_inode.rsize = 0;
- raw_inode.nsize = new_dentry->d_name.len;
- raw_inode.nlink = f->nlink;
- raw_inode.spare = 0;
- raw_inode.rename = 0;
- raw_inode.deleted = 0;
-
- /* See if there already exists a file with the same name as
- new_name. */
- if ((del_f = jffs_find_child(new_dir_f, new_dentry->d_name.name,
- new_dentry->d_name.len))) {
- raw_inode.rename = 1;
- raw_inode.dsize = sizeof(__u32);
- rename_data = del_f->ino;
- }
-
- /* Write the new node to the flash memory. */
- if ((result = jffs_write_node(c, node, &raw_inode,
- new_dentry->d_name.name,
- (unsigned char*)&rename_data, 0, f)) < 0) {
- D(printk("jffs_rename(): Failed to write node to flash.\n"));
- jffs_free_node(node);
- goto jffs_rename_end;
- }
- raw_inode.dsize = 0;
-
- if (raw_inode.rename) {
- /* The file with the same name must be deleted. */
- //FIXME deadlock down(&c->fmc->gclock);
- if ((result = jffs_remove(new_dir, new_dentry,
- del_f->mode)) < 0) {
- /* This is really bad. */
- printk(KERN_ERR "JFFS: An error occurred in "
- "rename().\n");
- }
- // up(&c->fmc->gclock);
- }
-
- if (old_dir_f != new_dir_f) {
- /* Remove the file from its old position in the
- filesystem tree. */
- jffs_unlink_file_from_tree(f);
- }
-
- /* Insert the new node into the file system. */
- if ((result = jffs_insert_node(c, f, &raw_inode,
- new_dentry->d_name.name, node)) < 0) {
- D(printk(KERN_ERR "jffs_rename(): jffs_insert_node() "
- "failed!\n"));
- }
-
- if (old_dir_f != new_dir_f) {
- /* Insert the file to its new position in the
- file system. */
- jffs_insert_file_into_tree(f);
- }
-
- /* This is a kind of update of the inode we're about to make
- here. This is what they do in ext2fs. Kind of. */
- if ((inode = iget(new_dir->i_sb, f->ino))) {
- inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
- iput(inode);
- }
-
-jffs_rename_end:
- D3(printk (KERN_NOTICE "rename(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return result;
-} /* jffs_rename() */
-
-
-/* Read the contents of a directory. Used by programs like `ls'
- for instance. */
-static int
-jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
-{
- struct jffs_file *f;
- struct dentry *dentry = filp->f_path.dentry;
- struct inode *inode = dentry->d_inode;
- struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
- int j;
- int ddino;
- lock_kernel();
- D3(printk (KERN_NOTICE "readdir(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
-
- D2(printk("jffs_readdir(): inode: 0x%p, filp: 0x%p\n", inode, filp));
- if (filp->f_pos == 0) {
- D3(printk("jffs_readdir(): \".\" %lu\n", inode->i_ino));
- if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) {
- D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return 0;
- }
- filp->f_pos = 1;
- }
- if (filp->f_pos == 1) {
- if (inode->i_ino == JFFS_MIN_INO) {
- ddino = JFFS_MIN_INO;
- }
- else {
- ddino = ((struct jffs_file *)
- inode->i_private)->pino;
- }
- D3(printk("jffs_readdir(): \"..\" %u\n", ddino));
- if (filldir(dirent, "..", 2, filp->f_pos, ddino, DT_DIR) < 0) {
- D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return 0;
- }
- filp->f_pos++;
- }
- f = ((struct jffs_file *)inode->i_private)->children;
-
- j = 2;
- while(f && (f->deleted || j++ < filp->f_pos )) {
- f = f->sibling_next;
- }
-
- while (f) {
- D3(printk("jffs_readdir(): \"%s\" ino: %u\n",
- (f->name ? f->name : ""), f->ino));
- if (filldir(dirent, f->name, f->nsize,
- filp->f_pos , f->ino, DT_UNKNOWN) < 0) {
- D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return 0;
- }
- filp->f_pos++;
- do {
- f = f->sibling_next;
- } while(f && f->deleted);
- }
- D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return filp->f_pos;
-} /* jffs_readdir() */
-
-
-/* Find a file in a directory. If the file exists, return its
- corresponding dentry. */
-static struct dentry *
-jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
- struct jffs_file *d;
- struct jffs_file *f;
- struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
- int len;
- int r = 0;
- const char *name;
- struct inode *inode = NULL;
-
- len = dentry->d_name.len;
- name = dentry->d_name.name;
-
- lock_kernel();
-
- D3({
- char *s = kmalloc(len + 1, GFP_KERNEL);
- memcpy(s, name, len);
- s[len] = '\0';
- printk("jffs_lookup(): dir: 0x%p, name: \"%s\"\n", dir, s);
- kfree(s);
- });
-
- D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
-
- r = -ENAMETOOLONG;
- if (len > JFFS_MAX_NAME_LEN) {
- goto jffs_lookup_end;
- }
-
- r = -EACCES;
- if (!(d = (struct jffs_file *)dir->i_private)) {
- D(printk("jffs_lookup(): No such inode! (%lu)\n",
- dir->i_ino));
- goto jffs_lookup_end;
- }
-
- /* Get the corresponding inode to the file. */
-
- /* iget calls jffs_read_inode, so we need to drop the biglock
- before calling iget. Unfortunately, the GC has a tendency
- to sneak in here, because iget sometimes calls schedule ().
- */
-
- if ((len == 1) && (name[0] == '.')) {
- D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- if (!(inode = iget(dir->i_sb, d->ino))) {
- D(printk("jffs_lookup(): . iget() ==> NULL\n"));
- goto jffs_lookup_end_no_biglock;
- }
- D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
- } else if ((len == 2) && (name[0] == '.') && (name[1] == '.')) {
- D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- if (!(inode = iget(dir->i_sb, d->pino))) {
- D(printk("jffs_lookup(): .. iget() ==> NULL\n"));
- goto jffs_lookup_end_no_biglock;
- }
- D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
- } else if ((f = jffs_find_child(d, name, len))) {
- D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- if (!(inode = iget(dir->i_sb, f->ino))) {
- D(printk("jffs_lookup(): iget() ==> NULL\n"));
- goto jffs_lookup_end_no_biglock;
- }
- D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
- } else {
- D3(printk("jffs_lookup(): Couldn't find the file. "
- "f = 0x%p, name = \"%s\", d = 0x%p, d->ino = %u\n",
- f, name, d, d->ino));
- inode = NULL;
- }
-
- d_add(dentry, inode);
- D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return NULL;
-
-jffs_lookup_end:
- D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
-
-jffs_lookup_end_no_biglock:
- unlock_kernel();
- return ERR_PTR(r);
-} /* jffs_lookup() */
-
-
-/* Try to read a page of data from a file. */
-static int
-jffs_do_readpage_nolock(struct file *file, struct page *page)
-{
- void *buf;
- unsigned long read_len;
- int result;
- struct inode *inode = (struct inode*)page->mapping->host;
- struct jffs_file *f = (struct jffs_file *)inode->i_private;
- struct jffs_control *c = (struct jffs_control *)inode->i_sb->s_fs_info;
- int r;
- loff_t offset;
-
- D2(printk("***jffs_readpage(): file = \"%s\", page->index = %lu\n",
- (f->name ? f->name : ""), (long)page->index));
-
- get_page(page);
- /* Don't SetPageLocked(page), should be locked already */
- ClearPageUptodate(page);
- ClearPageError(page);
-
- D3(printk (KERN_NOTICE "readpage(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
-
- read_len = 0;
- result = 0;
- offset = page_offset(page);
-
- kmap(page);
- buf = page_address(page);
- if (offset < inode->i_size) {
- read_len = min_t(long, inode->i_size - offset, PAGE_SIZE);
- r = jffs_read_data(f, buf, offset, read_len);
- if (r != read_len) {
- result = -EIO;
- D(
- printk("***jffs_readpage(): Read error! "
- "Wanted to read %lu bytes but only "
- "read %d bytes.\n", read_len, r);
- );
- }
-
- }
-
- /* This handles the case of partial or no read in above */
- if(read_len < PAGE_SIZE)
- memset(buf + read_len, 0, PAGE_SIZE - read_len);
- flush_dcache_page(page);
- kunmap(page);
-
- D3(printk (KERN_NOTICE "readpage(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
-
- if (result) {
- SetPageError(page);
- }else {
- SetPageUptodate(page);
- }
-
- page_cache_release(page);
-
- D3(printk("jffs_readpage(): Leaving...\n"));
-
- return result;
-} /* jffs_do_readpage_nolock() */
-
-static int jffs_readpage(struct file *file, struct page *page)
-{
- int ret = jffs_do_readpage_nolock(file, page);
- unlock_page(page);
- return ret;
-}
-
-/* Create a new directory. */
-static int
-jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
- struct jffs_raw_inode raw_inode;
- struct jffs_control *c;
- struct jffs_node *node;
- struct jffs_file *dir_f;
- struct inode *inode;
- int dir_mode;
- int result = 0;
- int err;
-
- D1({
- int len = dentry->d_name.len;
- char *_name = kmalloc(len + 1, GFP_KERNEL);
- memcpy(_name, dentry->d_name.name, len);
- _name[len] = '\0';
- printk("***jffs_mkdir(): dir = 0x%p, name = \"%s\", "
- "len = %d, mode = 0x%08x\n", dir, _name, len, mode);
- kfree(_name);
- });
-
- lock_kernel();
- dir_f = dir->i_private;
-
- ASSERT(if (!dir_f) {
- printk(KERN_ERR "jffs_mkdir(): No reference to a "
- "jffs_file struct in inode.\n");
- unlock_kernel();
- return -EIO;
- });
-
- c = dir_f->c;
- D3(printk (KERN_NOTICE "mkdir(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
-
- dir_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX)
- & ~current->fs->umask);
- if (dir->i_mode & S_ISGID) {
- dir_mode |= S_ISGID;
- }
-
- /* Create a node and initialize it as much as needed. */
- if (!(node = jffs_alloc_node())) {
- D(printk("jffs_mkdir(): Allocation failed: node == 0\n"));
- result = -ENOMEM;
- goto jffs_mkdir_end;
- }
- node->data_offset = 0;
- node->removed_size = 0;
-
- /* Initialize the raw inode. */
- raw_inode.magic = JFFS_MAGIC_BITMASK;
- raw_inode.ino = c->next_ino++;
- raw_inode.pino = dir_f->ino;
- raw_inode.version = 1;
- raw_inode.mode = dir_mode;
- raw_inode.uid = current->fsuid;
- raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
- /* raw_inode.gid = current->fsgid; */
- raw_inode.atime = get_seconds();
- raw_inode.mtime = raw_inode.atime;
- raw_inode.ctime = raw_inode.atime;
- raw_inode.offset = 0;
- raw_inode.dsize = 0;
- raw_inode.rsize = 0;
- raw_inode.nsize = dentry->d_name.len;
- raw_inode.nlink = 1;
- raw_inode.spare = 0;
- raw_inode.rename = 0;
- raw_inode.deleted = 0;
-
- /* Write the new node to the flash. */
- if ((result = jffs_write_node(c, node, &raw_inode,
- dentry->d_name.name, NULL, 0, NULL)) < 0) {
- D(printk("jffs_mkdir(): jffs_write_node() failed.\n"));
- jffs_free_node(node);
- goto jffs_mkdir_end;
- }
-
- /* Insert the new node into the file system. */
- if ((result = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
- node)) < 0) {
- goto jffs_mkdir_end;
- }
-
- inode = jffs_new_inode(dir, &raw_inode, &err);
- if (inode == NULL) {
- result = err;
- goto jffs_mkdir_end;
- }
-
- inode->i_op = &jffs_dir_inode_operations;
- inode->i_fop = &jffs_dir_operations;
-
- mark_inode_dirty(dir);
- d_instantiate(dentry, inode);
-
- result = 0;
-jffs_mkdir_end:
- D3(printk (KERN_NOTICE "mkdir(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return result;
-} /* jffs_mkdir() */
-
-
-/* Remove a directory. */
-static int
-jffs_rmdir(struct inode *dir, struct dentry *dentry)
-{
- struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
- int ret;
- D3(printk("***jffs_rmdir()\n"));
- D3(printk (KERN_NOTICE "rmdir(): down biglock\n"));
- lock_kernel();
- mutex_lock(&c->fmc->biglock);
- ret = jffs_remove(dir, dentry, S_IFDIR);
- D3(printk (KERN_NOTICE "rmdir(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return ret;
-}
-
-
-/* Remove any kind of file except for directories. */
-static int
-jffs_unlink(struct inode *dir, struct dentry *dentry)
-{
- struct jffs_control *c = (struct jffs_control *)dir->i_sb->s_fs_info;
- int ret;
-
- lock_kernel();
- D3(printk("***jffs_unlink()\n"));
- D3(printk (KERN_NOTICE "unlink(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
- ret = jffs_remove(dir, dentry, 0);
- D3(printk (KERN_NOTICE "unlink(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return ret;
-}
-
-
-/* Remove a JFFS entry, i.e. plain files, directories, etc. Here we
- shouldn't test for free space on the device. */
-static int
-jffs_remove(struct inode *dir, struct dentry *dentry, int type)
-{
- struct jffs_raw_inode raw_inode;
- struct jffs_control *c;
- struct jffs_file *dir_f; /* The file-to-remove's parent. */
- struct jffs_file *del_f; /* The file to remove. */
- struct jffs_node *del_node;
- struct inode *inode = NULL;
- int result = 0;
-
- D1({
- int len = dentry->d_name.len;
- const char *name = dentry->d_name.name;
- char *_name = kmalloc(len + 1, GFP_KERNEL);
- memcpy(_name, name, len);
- _name[len] = '\0';
- printk("***jffs_remove(): file = \"%s\", ino = %ld\n", _name, dentry->d_inode->i_ino);
- kfree(_name);
- });
-
- dir_f = dir->i_private;
- c = dir_f->c;
-
- result = -ENOENT;
- if (!(del_f = jffs_find_child(dir_f, dentry->d_name.name,
- dentry->d_name.len))) {
- D(printk("jffs_remove(): jffs_find_child() failed.\n"));
- goto jffs_remove_end;
- }
-
- if (S_ISDIR(type)) {
- struct jffs_file *child = del_f->children;
- while(child) {
- if( !child->deleted ) {
- result = -ENOTEMPTY;
- goto jffs_remove_end;
- }
- child = child->sibling_next;
- }
- }
- else if (S_ISDIR(del_f->mode)) {
- D(printk("jffs_remove(): node is a directory "
- "but it shouldn't be.\n"));
- result = -EPERM;
- goto jffs_remove_end;
- }
-
- inode = dentry->d_inode;
-
- result = -EIO;
- if (del_f->ino != inode->i_ino)
- goto jffs_remove_end;
-
- if (!inode->i_nlink) {
- printk("Deleting nonexistent file inode: %lu, nlink: %d\n",
- inode->i_ino, inode->i_nlink);
- inode->i_nlink=1;
- }
-
- /* Create a node for the deletion. */
- result = -ENOMEM;
- if (!(del_node = jffs_alloc_node())) {
- D(printk("jffs_remove(): Allocation failed!\n"));
- goto jffs_remove_end;
- }
- del_node->data_offset = 0;
- del_node->removed_size = 0;
-
- /* Initialize the raw inode. */
- raw_inode.magic = JFFS_MAGIC_BITMASK;
- raw_inode.ino = del_f->ino;
- raw_inode.pino = del_f->pino;
-/* raw_inode.version = del_f->highest_version + 1; */
- raw_inode.mode = del_f->mode;
- raw_inode.uid = current->fsuid;
- raw_inode.gid = current->fsgid;
- raw_inode.atime = get_seconds();
- raw_inode.mtime = del_f->mtime;
- raw_inode.ctime = raw_inode.atime;
- raw_inode.offset = 0;
- raw_inode.dsize = 0;
- raw_inode.rsize = 0;
- raw_inode.nsize = 0;
- raw_inode.nlink = del_f->nlink;
- raw_inode.spare = 0;
- raw_inode.rename = 0;
- raw_inode.deleted = 1;
-
- /* Write the new node to the flash memory. */
- if (jffs_write_node(c, del_node, &raw_inode, NULL, NULL, 1, del_f) < 0) {
- jffs_free_node(del_node);
- result = -EIO;
- goto jffs_remove_end;
- }
-
- /* Update the file. This operation will make the file disappear
- from the in-memory file system structures. */
- jffs_insert_node(c, del_f, &raw_inode, NULL, del_node);
-
- dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
- mark_inode_dirty(dir);
- inode->i_ctime = dir->i_ctime;
- inode_dec_link_count(inode);
-
- d_delete(dentry); /* This also frees the inode */
-
- result = 0;
-jffs_remove_end:
- return result;
-} /* jffs_remove() */
-
-
-static int
-jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
-{
- struct jffs_raw_inode raw_inode;
- struct jffs_file *dir_f;
- struct jffs_node *node = NULL;
- struct jffs_control *c;
- struct inode *inode;
- int result = 0;
- u16 data = old_encode_dev(rdev);
- int err;
-
- D1(printk("***jffs_mknod()\n"));
-
- if (!old_valid_dev(rdev))
- return -EINVAL;
- lock_kernel();
- dir_f = dir->i_private;
- c = dir_f->c;
-
- D3(printk (KERN_NOTICE "mknod(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
-
- /* Create and initialize a new node. */
- if (!(node = jffs_alloc_node())) {
- D(printk("jffs_mknod(): Allocation failed!\n"));
- result = -ENOMEM;
- goto jffs_mknod_err;
- }
- node->data_offset = 0;
- node->removed_size = 0;
-
- /* Initialize the raw inode. */
- raw_inode.magic = JFFS_MAGIC_BITMASK;
- raw_inode.ino = c->next_ino++;
- raw_inode.pino = dir_f->ino;
- raw_inode.version = 1;
- raw_inode.mode = mode;
- raw_inode.uid = current->fsuid;
- raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
- /* raw_inode.gid = current->fsgid; */
- raw_inode.atime = get_seconds();
- raw_inode.mtime = raw_inode.atime;
- raw_inode.ctime = raw_inode.atime;
- raw_inode.offset = 0;
- raw_inode.dsize = 2;
- raw_inode.rsize = 0;
- raw_inode.nsize = dentry->d_name.len;
- raw_inode.nlink = 1;
- raw_inode.spare = 0;
- raw_inode.rename = 0;
- raw_inode.deleted = 0;
-
- /* Write the new node to the flash. */
- if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
- (unsigned char *)&data, 0, NULL)) < 0) {
- D(printk("jffs_mknod(): jffs_write_node() failed.\n"));
- result = err;
- goto jffs_mknod_err;
- }
-
- /* Insert the new node into the file system. */
- if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
- node)) < 0) {
- result = err;
- goto jffs_mknod_end;
- }
-
- inode = jffs_new_inode(dir, &raw_inode, &err);
- if (inode == NULL) {
- result = err;
- goto jffs_mknod_end;
- }
-
- init_special_inode(inode, mode, rdev);
-
- d_instantiate(dentry, inode);
-
- goto jffs_mknod_end;
-
-jffs_mknod_err:
- if (node) {
- jffs_free_node(node);
- }
-
-jffs_mknod_end:
- D3(printk (KERN_NOTICE "mknod(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return result;
-} /* jffs_mknod() */
-
-
-static int
-jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
-{
- struct jffs_raw_inode raw_inode;
- struct jffs_control *c;
- struct jffs_file *dir_f;
- struct jffs_node *node;
- struct inode *inode;
-
- int symname_len = strlen(symname);
- int err;
-
- lock_kernel();
- D1({
- int len = dentry->d_name.len;
- char *_name = kmalloc(len + 1, GFP_KERNEL);
- char *_symname = kmalloc(symname_len + 1, GFP_KERNEL);
- memcpy(_name, dentry->d_name.name, len);
- _name[len] = '\0';
- memcpy(_symname, symname, symname_len);
- _symname[symname_len] = '\0';
- printk("***jffs_symlink(): dir = 0x%p, "
- "dentry->dname.name = \"%s\", "
- "symname = \"%s\"\n", dir, _name, _symname);
- kfree(_name);
- kfree(_symname);
- });
-
- dir_f = dir->i_private;
- ASSERT(if (!dir_f) {
- printk(KERN_ERR "jffs_symlink(): No reference to a "
- "jffs_file struct in inode.\n");
- unlock_kernel();
- return -EIO;
- });
-
- c = dir_f->c;
-
- /* Create a node and initialize it as much as needed. */
- if (!(node = jffs_alloc_node())) {
- D(printk("jffs_symlink(): Allocation failed: node = NULL\n"));
- unlock_kernel();
- return -ENOMEM;
- }
- D3(printk (KERN_NOTICE "symlink(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
-
- node->data_offset = 0;
- node->removed_size = 0;
-
- /* Initialize the raw inode. */
- raw_inode.magic = JFFS_MAGIC_BITMASK;
- raw_inode.ino = c->next_ino++;
- raw_inode.pino = dir_f->ino;
- raw_inode.version = 1;
- raw_inode.mode = S_IFLNK | S_IRWXUGO;
- raw_inode.uid = current->fsuid;
- raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
- raw_inode.atime = get_seconds();
- raw_inode.mtime = raw_inode.atime;
- raw_inode.ctime = raw_inode.atime;
- raw_inode.offset = 0;
- raw_inode.dsize = symname_len;
- raw_inode.rsize = 0;
- raw_inode.nsize = dentry->d_name.len;
- raw_inode.nlink = 1;
- raw_inode.spare = 0;
- raw_inode.rename = 0;
- raw_inode.deleted = 0;
-
- /* Write the new node to the flash. */
- if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
- (const unsigned char *)symname, 0, NULL)) < 0) {
- D(printk("jffs_symlink(): jffs_write_node() failed.\n"));
- jffs_free_node(node);
- goto jffs_symlink_end;
- }
-
- /* Insert the new node into the file system. */
- if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
- node)) < 0) {
- goto jffs_symlink_end;
- }
-
- inode = jffs_new_inode(dir, &raw_inode, &err);
- if (inode == NULL) {
- goto jffs_symlink_end;
- }
- err = 0;
- inode->i_op = &page_symlink_inode_operations;
- inode->i_mapping->a_ops = &jffs_address_operations;
-
- d_instantiate(dentry, inode);
- jffs_symlink_end:
- D3(printk (KERN_NOTICE "symlink(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return err;
-} /* jffs_symlink() */
-
-
-/* Create an inode inside a JFFS directory (dir) and return it.
- *
- * By the time this is called, we already have created
- * the directory cache entry for the new file, but it
- * is so far negative - it has no inode.
- *
- * If the create succeeds, we fill in the inode information
- * with d_instantiate().
- */
-static int
-jffs_create(struct inode *dir, struct dentry *dentry, int mode,
- struct nameidata *nd)
-{
- struct jffs_raw_inode raw_inode;
- struct jffs_control *c;
- struct jffs_node *node;
- struct jffs_file *dir_f; /* JFFS representation of the directory. */
- struct inode *inode;
- int err;
-
- lock_kernel();
- D1({
- int len = dentry->d_name.len;
- char *s = kmalloc(len + 1, GFP_KERNEL);
- memcpy(s, dentry->d_name.name, len);
- s[len] = '\0';
- printk("jffs_create(): dir: 0x%p, name: \"%s\"\n", dir, s);
- kfree(s);
- });
-
- dir_f = dir->i_private;
- ASSERT(if (!dir_f) {
- printk(KERN_ERR "jffs_create(): No reference to a "
- "jffs_file struct in inode.\n");
- unlock_kernel();
- return -EIO;
- });
-
- c = dir_f->c;
-
- /* Create a node and initialize as much as needed. */
- if (!(node = jffs_alloc_node())) {
- D(printk("jffs_create(): Allocation failed: node == 0\n"));
- unlock_kernel();
- return -ENOMEM;
- }
- D3(printk (KERN_NOTICE "create(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
-
- node->data_offset = 0;
- node->removed_size = 0;
-
- /* Initialize the raw inode. */
- raw_inode.magic = JFFS_MAGIC_BITMASK;
- raw_inode.ino = c->next_ino++;
- raw_inode.pino = dir_f->ino;
- raw_inode.version = 1;
- raw_inode.mode = mode;
- raw_inode.uid = current->fsuid;
- raw_inode.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
- raw_inode.atime = get_seconds();
- raw_inode.mtime = raw_inode.atime;
- raw_inode.ctime = raw_inode.atime;
- raw_inode.offset = 0;
- raw_inode.dsize = 0;
- raw_inode.rsize = 0;
- raw_inode.nsize = dentry->d_name.len;
- raw_inode.nlink = 1;
- raw_inode.spare = 0;
- raw_inode.rename = 0;
- raw_inode.deleted = 0;
-
- /* Write the new node to the flash. */
- if ((err = jffs_write_node(c, node, &raw_inode,
- dentry->d_name.name, NULL, 0, NULL)) < 0) {
- D(printk("jffs_create(): jffs_write_node() failed.\n"));
- jffs_free_node(node);
- goto jffs_create_end;
- }
-
- /* Insert the new node into the file system. */
- if ((err = jffs_insert_node(c, NULL, &raw_inode, dentry->d_name.name,
- node)) < 0) {
- goto jffs_create_end;
- }
-
- /* Initialize an inode. */
- inode = jffs_new_inode(dir, &raw_inode, &err);
- if (inode == NULL) {
- goto jffs_create_end;
- }
- err = 0;
- inode->i_op = &jffs_file_inode_operations;
- inode->i_fop = &jffs_file_operations;
- inode->i_mapping->a_ops = &jffs_address_operations;
- inode->i_mapping->nrpages = 0;
-
- d_instantiate(dentry, inode);
- jffs_create_end:
- D3(printk (KERN_NOTICE "create(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- unlock_kernel();
- return err;
-} /* jffs_create() */
-
-
-/* Write, append or rewrite data to an existing file. */
-static ssize_t
-jffs_file_write(struct file *filp, const char *buf, size_t count,
- loff_t *ppos)
-{
- struct jffs_raw_inode raw_inode;
- struct jffs_control *c;
- struct jffs_file *f;
- struct jffs_node *node;
- struct dentry *dentry = filp->f_path.dentry;
- struct inode *inode = dentry->d_inode;
- int recoverable = 0;
- size_t written = 0;
- __u32 thiscount = count;
- loff_t pos = *ppos;
- int err;
-
- inode = filp->f_path.dentry->d_inode;
-
- D2(printk("***jffs_file_write(): inode: 0x%p (ino: %lu), "
- "filp: 0x%p, buf: 0x%p, count: %d\n",
- inode, inode->i_ino, filp, buf, count));
-
-#if 0
- if (inode->i_sb->s_flags & MS_RDONLY) {
- D(printk("jffs_file_write(): MS_RDONLY\n"));
- err = -EROFS;
- goto out_isem;
- }
-#endif
- err = -EINVAL;
-
- if (!S_ISREG(inode->i_mode)) {
- D(printk("jffs_file_write(): inode->i_mode == 0x%08x\n",
- inode->i_mode));
- goto out_isem;
- }
-
- if (!(f = inode->i_private)) {
- D(printk("jffs_file_write(): inode->i_private = 0x%p\n",
- inode->i_private));
- goto out_isem;
- }
-
- c = f->c;
-
- /*
- * This will never trigger with sane page sizes. leave it in
- * anyway, since I'm thinking about how to merge larger writes
- * (the current idea is to poke a thread that does the actual
- * I/O and starts by doing a mutex_lock(&inode->i_mutex). then we
- * would need to get the page cache pages and have a list of
- * I/O requests and do write-merging here.
- * -- prumpf
- */
- thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
-
- D3(printk (KERN_NOTICE "file_write(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
-
- /* Urgh. POSIX says we can do short writes if we feel like it.
- * In practice, we can't. Nothing will cope. So we loop until
- * we're done.
- *
- * <_Anarchy_> posix and reality are not interconnected on this issue
- */
- while (count) {
- /* Things are going to be written so we could allocate and
- initialize the necessary data structures now. */
- if (!(node = jffs_alloc_node())) {
- D(printk("jffs_file_write(): node == 0\n"));
- err = -ENOMEM;
- goto out;
- }
-
- node->data_offset = pos;
- node->removed_size = 0;
-
- /* Initialize the raw inode. */
- raw_inode.magic = JFFS_MAGIC_BITMASK;
- raw_inode.ino = f->ino;
- raw_inode.pino = f->pino;
-
- raw_inode.mode = f->mode;
-
- raw_inode.uid = f->uid;
- raw_inode.gid = f->gid;
- raw_inode.atime = get_seconds();
- raw_inode.mtime = raw_inode.atime;
- raw_inode.ctime = f->ctime;
- raw_inode.offset = pos;
- raw_inode.dsize = thiscount;
- raw_inode.rsize = 0;
- raw_inode.nsize = f->nsize;
- raw_inode.nlink = f->nlink;
- raw_inode.spare = 0;
- raw_inode.rename = 0;
- raw_inode.deleted = 0;
-
- if (pos < f->size) {
- node->removed_size = raw_inode.rsize = min(thiscount, (__u32)(f->size - pos));
-
- /* If this node is going entirely over the top of old data,
- we can allow it to go into the reserved space, because
- we know that GC can reclaim the space later.
- */
- if (pos + thiscount < f->size) {
- /* If all the data we're overwriting are _real_,
- not just holes, then:
- recoverable = 1;
- */
- }
- }
-
- /* Write the new node to the flash. */
- /* NOTE: We would be quite happy if jffs_write_node() wrote a
- smaller node than we were expecting. There's no need for it
- to waste the space at the end of the flash just because it's
- a little smaller than what we asked for. But that's a whole
- new can of worms which I'm not going to open this week.
- -- dwmw2.
- */
- if ((err = jffs_write_node(c, node, &raw_inode, f->name,
- (const unsigned char *)buf,
- recoverable, f)) < 0) {
- D(printk("jffs_file_write(): jffs_write_node() failed.\n"));
- jffs_free_node(node);
- goto out;
- }
-
- written += err;
- buf += err;
- count -= err;
- pos += err;
-
- /* Insert the new node into the file system. */
- if ((err = jffs_insert_node(c, f, &raw_inode, NULL, node)) < 0) {
- goto out;
- }
-
- D3(printk("jffs_file_write(): new f_pos %ld.\n", (long)pos));
-
- thiscount = min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
- }
- out:
- D3(printk (KERN_NOTICE "file_write(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
-
- /* Fix things in the real inode. */
- if (pos > inode->i_size) {
- inode->i_size = pos;
- inode->i_blocks = (inode->i_size + 511) >> 9;
- }
- inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
- invalidate_mapping_pages(inode->i_mapping, 0, -1);
-
- out_isem:
- return err;
-} /* jffs_file_write() */
-
-static int
-jffs_prepare_write(struct file *filp, struct page *page,
- unsigned from, unsigned to)
-{
- /* FIXME: we should detect some error conditions here */
-
- /* Bugger that. We should make sure the page is uptodate */
- if (!PageUptodate(page) && (from || to < PAGE_CACHE_SIZE))
- return jffs_do_readpage_nolock(filp, page);
-
- return 0;
-} /* jffs_prepare_write() */
-
-static int
-jffs_commit_write(struct file *filp, struct page *page,
- unsigned from, unsigned to)
-{
- void *addr = page_address(page) + from;
- /* XXX: PAGE_CACHE_SHIFT or PAGE_SHIFT */
- loff_t pos = page_offset(page) + from;
-
- return jffs_file_write(filp, addr, to-from, &pos);
-} /* jffs_commit_write() */
-
-/* This is our ioctl() routine. */
-static int
-jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- struct jffs_control *c;
- int ret = 0;
-
- D2(printk("***jffs_ioctl(): cmd = 0x%08x, arg = 0x%08lx\n",
- cmd, arg));
-
- if (!(c = (struct jffs_control *)inode->i_sb->s_fs_info)) {
- printk(KERN_ERR "JFFS: Bad inode in ioctl() call. "
- "(cmd = 0x%08x)\n", cmd);
- return -EIO;
- }
- D3(printk (KERN_NOTICE "ioctl(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
-
- switch (cmd) {
- case JFFS_PRINT_HASH:
- jffs_print_hash_table(c);
- break;
- case JFFS_PRINT_TREE:
- jffs_print_tree(c->root, 0);
- break;
- case JFFS_GET_STATUS:
- {
- struct jffs_flash_status fst;
- struct jffs_fmcontrol *fmc = c->fmc;
- printk("Flash status -- ");
- if (!access_ok(VERIFY_WRITE,
- (struct jffs_flash_status __user *)arg,
- sizeof(struct jffs_flash_status))) {
- D(printk("jffs_ioctl(): Bad arg in "
- "JFFS_GET_STATUS ioctl!\n"));
- ret = -EFAULT;
- break;
- }
- fst.size = fmc->flash_size;
- fst.used = fmc->used_size;
- fst.dirty = fmc->dirty_size;
- fst.begin = fmc->head->offset;
- fst.end = fmc->tail->offset + fmc->tail->size;
- printk("size: %d, used: %d, dirty: %d, "
- "begin: %d, end: %d\n",
- fst.size, fst.used, fst.dirty,
- fst.begin, fst.end);
- if (copy_to_user((struct jffs_flash_status __user *)arg,
- &fst,
- sizeof(struct jffs_flash_status))) {
- ret = -EFAULT;
- }
- }
- break;
- default:
- ret = -ENOTTY;
- }
- D3(printk (KERN_NOTICE "ioctl(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- return ret;
-} /* jffs_ioctl() */
-
-
-static const struct address_space_operations jffs_address_operations = {
- .readpage = jffs_readpage,
- .prepare_write = jffs_prepare_write,
- .commit_write = jffs_commit_write,
-};
-
-static int jffs_fsync(struct file *f, struct dentry *d, int datasync)
-{
- /* We currently have O_SYNC operations at all times.
- Do nothing.
- */
- return 0;
-}
-
-
-static const struct file_operations jffs_file_operations =
-{
- .open = generic_file_open,
- .llseek = generic_file_llseek,
- .read = do_sync_read,
- .aio_read = generic_file_aio_read,
- .write = do_sync_write,
- .aio_write = generic_file_aio_write,
- .ioctl = jffs_ioctl,
- .mmap = generic_file_readonly_mmap,
- .fsync = jffs_fsync,
- .sendfile = generic_file_sendfile,
-};
-
-
-static const struct inode_operations jffs_file_inode_operations =
-{
- .lookup = jffs_lookup, /* lookup */
- .setattr = jffs_setattr,
-};
-
-
-static const struct file_operations jffs_dir_operations =
-{
- .readdir = jffs_readdir,
-};
-
-
-static const struct inode_operations jffs_dir_inode_operations =
-{
- .create = jffs_create,
- .lookup = jffs_lookup,
- .unlink = jffs_unlink,
- .symlink = jffs_symlink,
- .mkdir = jffs_mkdir,
- .rmdir = jffs_rmdir,
- .mknod = jffs_mknod,
- .rename = jffs_rename,
- .setattr = jffs_setattr,
-};
-
-
-/* Initialize an inode for the VFS. */
-static void
-jffs_read_inode(struct inode *inode)
-{
- struct jffs_file *f;
- struct jffs_control *c;
-
- D3(printk("jffs_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
-
- if (!inode->i_sb) {
- D(printk("jffs_read_inode(): !inode->i_sb ==> "
- "No super block!\n"));
- return;
- }
- c = (struct jffs_control *)inode->i_sb->s_fs_info;
- D3(printk (KERN_NOTICE "read_inode(): down biglock\n"));
- mutex_lock(&c->fmc->biglock);
- if (!(f = jffs_find_file(c, inode->i_ino))) {
- D(printk("jffs_read_inode(): No such inode (%lu).\n",
- inode->i_ino));
- D3(printk (KERN_NOTICE "read_inode(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
- return;
- }
- inode->i_private = f;
- inode->i_mode = f->mode;
- inode->i_nlink = f->nlink;
- inode->i_uid = f->uid;
- inode->i_gid = f->gid;
- inode->i_size = f->size;
- inode->i_atime.tv_sec = f->atime;
- inode->i_mtime.tv_sec = f->mtime;
- inode->i_ctime.tv_sec = f->ctime;
- inode->i_atime.tv_nsec =
- inode->i_mtime.tv_nsec =
- inode->i_ctime.tv_nsec = 0;
-
- inode->i_blocks = (inode->i_size + 511) >> 9;
- if (S_ISREG(inode->i_mode)) {
- inode->i_op = &jffs_file_inode_operations;
- inode->i_fop = &jffs_file_operations;
- inode->i_mapping->a_ops = &jffs_address_operations;
- }
- else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &jffs_dir_inode_operations;
- inode->i_fop = &jffs_dir_operations;
- }
- else if (S_ISLNK(inode->i_mode)) {
- inode->i_op = &page_symlink_inode_operations;
- inode->i_mapping->a_ops = &jffs_address_operations;
- }
- else {
- /* If the node is a device of some sort, then the number of
- the device should be read from the flash memory and then
- added to the inode's i_rdev member. */
- u16 val;
- jffs_read_data(f, (char *)&val, 0, 2);
- init_special_inode(inode, inode->i_mode,
- old_decode_dev(val));
- }
-
- D3(printk (KERN_NOTICE "read_inode(): up biglock\n"));
- mutex_unlock(&c->fmc->biglock);
-}
-
-
-static void
-jffs_delete_inode(struct inode *inode)
-{
- struct jffs_file *f;
- struct jffs_control *c;
- D3(printk("jffs_delete_inode(): inode->i_ino == %lu\n",
- inode->i_ino));
-
- truncate_inode_pages(&inode->i_data, 0);
- lock_kernel();
- inode->i_size = 0;
- inode->i_blocks = 0;
- inode->i_private = NULL;
- clear_inode(inode);
- if (inode->i_nlink == 0) {
- c = (struct jffs_control *) inode->i_sb->s_fs_info;
- f = (struct jffs_file *) jffs_find_file (c, inode->i_ino);
- jffs_possibly_delete_file(f);
- }
-
- unlock_kernel();
-}
-
-
-static void
-jffs_write_super(struct super_block *sb)
-{
- struct jffs_control *c = (struct jffs_control *)sb->s_fs_info;
- lock_kernel();
- jffs_garbage_collect_trigger(c);
- unlock_kernel();
-}
-
-static int jffs_remount(struct super_block *sb, int *flags, char *data)
-{
- *flags |= MS_NODIRATIME;
- return 0;
-}
-
-static const struct super_operations jffs_ops =
-{
- .read_inode = jffs_read_inode,
- .delete_inode = jffs_delete_inode,
- .put_super = jffs_put_super,
- .write_super = jffs_write_super,
- .statfs = jffs_statfs,
- .remount_fs = jffs_remount,
-};
-
-static int jffs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data, struct vfsmount *mnt)
-{
- return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super,
- mnt);
-}
-
-static struct file_system_type jffs_fs_type = {
- .owner = THIS_MODULE,
- .name = "jffs",
- .get_sb = jffs_get_sb,
- .kill_sb = kill_block_super,
- .fs_flags = FS_REQUIRES_DEV,
-};
-
-static int __init
-init_jffs_fs(void)
-{
- printk(KERN_INFO "JFFS version " JFFS_VERSION_STRING
- ", (C) 1999, 2000 Axis Communications AB\n");
-
-#ifdef CONFIG_JFFS_PROC_FS
- jffs_proc_root = proc_mkdir("jffs", proc_root_fs);
- if (!jffs_proc_root) {
- printk(KERN_WARNING "cannot create /proc/jffs entry\n");
- }
-#endif
- fm_cache = kmem_cache_create("jffs_fm", sizeof(struct jffs_fm),
- 0,
- SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
- NULL, NULL);
- if (!fm_cache) {
- return -ENOMEM;
- }
-
- node_cache = kmem_cache_create("jffs_node",sizeof(struct jffs_node),
- 0,
- SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
- NULL, NULL);
- if (!node_cache) {
- kmem_cache_destroy(fm_cache);
- return -ENOMEM;
- }
-
- return register_filesystem(&jffs_fs_type);
-}
-
-static void __exit
-exit_jffs_fs(void)
-{
- unregister_filesystem(&jffs_fs_type);
- kmem_cache_destroy(fm_cache);
- kmem_cache_destroy(node_cache);
-}
-
-module_init(init_jffs_fs)
-module_exit(exit_jffs_fs)
-
-MODULE_DESCRIPTION("The Journalling Flash File System");
-MODULE_AUTHOR("Axis Communications AB.");
-MODULE_LICENSE("GPL");
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
deleted file mode 100644
index 6dd18911b44..00000000000
--- a/fs/jffs/intrep.c
+++ /dev/null
@@ -1,3449 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000 Axis Communications, Inc.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * 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.
- *
- * $Id: intrep.c,v 1.102 2001/09/23 23:28:36 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-
-/* This file contains the code for the internal structure of the
- Journaling Flash File System, JFFS. */
-
-/*
- * Todo list:
- *
- * memcpy_to_flash() and memcpy_from_flash() functions.
- *
- * Implementation of hard links.
- *
- * Organize the source code in a better way. Against the VFS we could
- * have jffs_ext.c, and against the block device jffs_int.c.
- * A better file-internal organization too.
- *
- * A better checksum algorithm.
- *
- * Consider endianness stuff. ntohl() etc.
- *
- * Are we handling the atime, mtime, ctime members of the inode right?
- *
- * Remove some duplicated code. Take a look at jffs_write_node() and
- * jffs_rewrite_data() for instance.
- *
- * Implement more meaning of the nlink member in various data structures.
- * nlink could be used in conjunction with hard links for instance.
- *
- * Better memory management. Allocate data structures in larger chunks
- * if possible.
- *
- * If too much meta data is stored, a garbage collect should be issued.
- * We have experienced problems with too much meta data with for instance
- * log files.
- *
- * Improve the calls to jffs_ioctl(). We would like to retrieve more
- * information to be able to debug (or to supervise) JFFS during run-time.
- *
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/jffs.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/pagemap.h>
-#include <linux/mutex.h>
-#include <asm/byteorder.h>
-#include <linux/smp_lock.h>
-#include <linux/time.h>
-#include <linux/ctype.h>
-#include <linux/freezer.h>
-
-#include "intrep.h"
-#include "jffs_fm.h"
-
-long no_jffs_node = 0;
-static long no_jffs_file = 0;
-#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
-long no_jffs_control = 0;
-long no_jffs_raw_inode = 0;
-long no_jffs_node_ref = 0;
-long no_jffs_fm = 0;
-long no_jffs_fmcontrol = 0;
-long no_hash = 0;
-long no_name = 0;
-#endif
-
-static int jffs_scan_flash(struct jffs_control *c);
-static int jffs_update_file(struct jffs_file *f, struct jffs_node *node);
-static int jffs_build_file(struct jffs_file *f);
-static int jffs_free_file(struct jffs_file *f);
-static int jffs_free_node_list(struct jffs_file *f);
-static int jffs_garbage_collect_now(struct jffs_control *c);
-static int jffs_insert_file_into_hash(struct jffs_file *f);
-static int jffs_remove_redundant_nodes(struct jffs_file *f);
-
-/* Is there enough space on the flash? */
-static inline int JFFS_ENOUGH_SPACE(struct jffs_control *c, __u32 space)
-{
- struct jffs_fmcontrol *fmc = c->fmc;
-
- while (1) {
- if ((fmc->flash_size - (fmc->used_size + fmc->dirty_size))
- >= fmc->min_free_size + space) {
- return 1;
- }
- if (fmc->dirty_size < fmc->sector_size)
- return 0;
-
- if (jffs_garbage_collect_now(c)) {
- D1(printk("JFFS_ENOUGH_SPACE: jffs_garbage_collect_now() failed.\n"));
- return 0;
- }
- }
-}
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-static __u8
-flash_read_u8(struct mtd_info *mtd, loff_t from)
-{
- size_t retlen;
- __u8 ret;
- int res;
-
- res = MTD_READ(mtd, from, 1, &retlen, &ret);
- if (retlen != 1) {
- printk("Didn't read a byte in flash_read_u8(). Returned %d\n", res);
- return 0;
- }
-
- return ret;
-}
-
-static void
-jffs_hexdump(struct mtd_info *mtd, loff_t pos, int size)
-{
- char line[16];
- int j = 0;
-
- while (size > 0) {
- int i;
-
- printk("%ld:", (long) pos);
- for (j = 0; j < 16; j++) {
- line[j] = flash_read_u8(mtd, pos++);
- }
- for (i = 0; i < j; i++) {
- if (!(i & 1)) {
- printk(" %.2x", line[i] & 0xff);
- }
- else {
- printk("%.2x", line[i] & 0xff);
- }
- }
-
- /* Print empty space */
- for (; i < 16; i++) {
- if (!(i & 1)) {
- printk(" ");
- }
- else {
- printk(" ");
- }
- }
- printk(" ");
-
- for (i = 0; i < j; i++) {
- if (isgraph(line[i])) {
- printk("%c", line[i]);
- }
- else {
- printk(".");
- }
- }
- printk("\n");
- size -= 16;
- }
-}
-
-/* Print the contents of a node. */
-static void
-jffs_print_node(struct jffs_node *n)
-{
- D(printk("jffs_node: 0x%p\n", n));
- D(printk("{\n"));
- D(printk(" 0x%08x, /* version */\n", n->version));
- D(printk(" 0x%08x, /* data_offset */\n", n->data_offset));
- D(printk(" 0x%08x, /* data_size */\n", n->data_size));
- D(printk(" 0x%08x, /* removed_size */\n", n->removed_size));
- D(printk(" 0x%08x, /* fm_offset */\n", n->fm_offset));
- D(printk(" 0x%02x, /* name_size */\n", n->name_size));
- D(printk(" 0x%p, /* fm, fm->offset: %u */\n",
- n->fm, (n->fm ? n->fm->offset : 0)));
- D(printk(" 0x%p, /* version_prev */\n", n->version_prev));
- D(printk(" 0x%p, /* version_next */\n", n->version_next));
- D(printk(" 0x%p, /* range_prev */\n", n->range_prev));
- D(printk(" 0x%p, /* range_next */\n", n->range_next));
- D(printk("}\n"));
-}
-
-#endif
-
-/* Print the contents of a raw inode. */
-static void
-jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
-{
- D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino));
- D(printk("{\n"));
- D(printk(" 0x%08x, /* magic */\n", raw_inode->magic));
- D(printk(" 0x%08x, /* ino */\n", raw_inode->ino));
- D(printk(" 0x%08x, /* pino */\n", raw_inode->pino));
- D(printk(" 0x%08x, /* version */\n", raw_inode->version));
- D(printk(" 0x%08x, /* mode */\n", raw_inode->mode));
- D(printk(" 0x%04x, /* uid */\n", raw_inode->uid));
- D(printk(" 0x%04x, /* gid */\n", raw_inode->gid));
- D(printk(" 0x%08x, /* atime */\n", raw_inode->atime));
- D(printk(" 0x%08x, /* mtime */\n", raw_inode->mtime));
- D(printk(" 0x%08x, /* ctime */\n", raw_inode->ctime));
- D(printk(" 0x%08x, /* offset */\n", raw_inode->offset));
- D(printk(" 0x%08x, /* dsize */\n", raw_inode->dsize));
- D(printk(" 0x%08x, /* rsize */\n", raw_inode->rsize));
- D(printk(" 0x%02x, /* nsize */\n", raw_inode->nsize));
- D(printk(" 0x%02x, /* nlink */\n", raw_inode->nlink));
- D(printk(" 0x%02x, /* spare */\n",
- raw_inode->spare));
- D(printk(" %u, /* rename */\n",
- raw_inode->rename));
- D(printk(" %u, /* deleted */\n",
- raw_inode->deleted));
- D(printk(" 0x%02x, /* accurate */\n",
- raw_inode->accurate));
- D(printk(" 0x%08x, /* dchksum */\n", raw_inode->dchksum));
- D(printk(" 0x%04x, /* nchksum */\n", raw_inode->nchksum));
- D(printk(" 0x%04x, /* chksum */\n", raw_inode->chksum));
- D(printk("}\n"));
-}
-
-#define flash_safe_acquire(arg)
-#define flash_safe_release(arg)
-
-
-static int
-flash_safe_read(struct mtd_info *mtd, loff_t from,
- u_char *buf, size_t count)
-{
- size_t retlen;
- int res;
-
- D3(printk(KERN_NOTICE "flash_safe_read(%p, %08x, %p, %08x)\n",
- mtd, (unsigned int) from, buf, count));
-
- res = mtd->read(mtd, from, count, &retlen, buf);
- if (retlen != count) {
- panic("Didn't read all bytes in flash_safe_read(). Returned %d\n", res);
- }
- return res?res:retlen;
-}
-
-
-static __u32
-flash_read_u32(struct mtd_info *mtd, loff_t from)
-{
- size_t retlen;
- __u32 ret;
- int res;
-
- res = mtd->read(mtd, from, 4, &retlen, (unsigned char *)&ret);
- if (retlen != 4) {
- printk("Didn't read all bytes in flash_read_u32(). Returned %d\n", res);
- return 0;
- }
-
- return ret;
-}
-
-
-static int
-flash_safe_write(struct mtd_info *mtd, loff_t to,
- const u_char *buf, size_t count)
-{
- size_t retlen;
- int res;
-
- D3(printk(KERN_NOTICE "flash_safe_write(%p, %08x, %p, %08x)\n",
- mtd, (unsigned int) to, buf, count));
-
- res = mtd->write(mtd, to, count, &retlen, buf);
- if (retlen != count) {
- printk("Didn't write all bytes in flash_safe_write(). Returned %d\n", res);
- }
- return res?res:retlen;
-}
-
-
-static int
-flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs,
- unsigned long iovec_cnt, loff_t to)
-{
- size_t retlen, retlen_a;
- int i;
- int res;
-
- D3(printk(KERN_NOTICE "flash_safe_writev(%p, %08x, %p)\n",
- mtd, (unsigned int) to, vecs));
-
- if (mtd->writev) {
- res = mtd->writev(mtd, vecs, iovec_cnt, to, &retlen);
- return res ? res : retlen;
- }
- /* Not implemented writev. Repeatedly use write - on the not so
- unreasonable assumption that the mtd driver doesn't care how
- many write cycles we use. */
- res=0;
- retlen=0;
-
- for (i=0; !res && i<iovec_cnt; i++) {
- res = mtd->write(mtd, to, vecs[i].iov_len, &retlen_a,
- vecs[i].iov_base);
- if (retlen_a != vecs[i].iov_len) {
- printk("Didn't write all bytes in flash_safe_writev(). Returned %d\n", res);
- if (i != iovec_cnt-1)
- return -EIO;
- }
- /* If res is non-zero, retlen_a is undefined, but we don't
- care because in that case it's not going to be
- returned anyway.
- */
- to += retlen_a;
- retlen += retlen_a;
- }
- return res?res:retlen;
-}
-
-
-static int
-flash_memset(struct mtd_info *mtd, loff_t to,
- const u_char c, size_t size)
-{
- static unsigned char pattern[64];
- int i;
-
- /* fill up pattern */
-
- for(i = 0; i < 64; i++)
- pattern[i] = c;
-
- /* write as many 64-byte chunks as we can */
-
- while (size >= 64) {
- flash_safe_write(mtd, to, pattern, 64);
- size -= 64;
- to += 64;
- }
-
- /* and the rest */
-
- if(size)
- flash_safe_write(mtd, to, pattern, size);
-
- return size;
-}
-
-
-static void
-intrep_erase_callback(struct erase_info *done)
-{
- wait_queue_head_t *wait_q;
-
- wait_q = (wait_queue_head_t *)done->priv;
-
- wake_up(wait_q);
-}
-
-
-static int
-flash_erase_region(struct mtd_info *mtd, loff_t start,
- size_t size)
-{
- struct erase_info *erase;
- DECLARE_WAITQUEUE(wait, current);
- wait_queue_head_t wait_q;
-
- erase = kmalloc(sizeof(struct erase_info), GFP_KERNEL);
- if (!erase)
- return -ENOMEM;
-
- init_waitqueue_head(&wait_q);
-
- erase->mtd = mtd;
- erase->callback = intrep_erase_callback;
- erase->addr = start;
- erase->len = size;
- erase->priv = (u_long)&wait_q;
-
- /* FIXME: Use TASK_INTERRUPTIBLE and deal with being interrupted */
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&wait_q, &wait);
-
- if (mtd->erase(mtd, erase) < 0) {
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&wait_q, &wait);
- kfree(erase);
-
- printk(KERN_WARNING "flash: erase of region [0x%lx, 0x%lx] "
- "totally failed\n", (long)start, (long)start + size);
-
- return -1;
- }
-
- schedule(); /* Wait for flash to finish. */
- remove_wait_queue(&wait_q, &wait);
-
- kfree(erase);
-
- return 0;
-}
-
-/* This routine calculates checksums in JFFS. */
-static __u32
-jffs_checksum(const void *data, int size)
-{
- __u32 sum = 0;
- __u8 *ptr = (__u8 *)data;
- while (size-- > 0) {
- sum += *ptr++;
- }
- D3(printk(", result: 0x%08x\n", sum));
- return sum;
-}
-
-
-static int
-jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size, __u32 *result)
-{
- __u32 sum = 0;
- loff_t ptr = start;
- __u8 *read_buf;
- int i, length;
-
- /* Allocate read buffer */
- read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
- if (!read_buf) {
- printk(KERN_NOTICE "kmalloc failed in jffs_checksum_flash()\n");
- return -ENOMEM;
- }
- /* Loop until checksum done */
- while (size) {
- /* Get amount of data to read */
- if (size < 4096)
- length = size;
- else
- length = 4096;
-
- /* Perform flash read */
- D3(printk(KERN_NOTICE "jffs_checksum_flash\n"));
- flash_safe_read(mtd, ptr, &read_buf[0], length);
-
- /* Compute checksum */
- for (i=0; i < length ; i++)
- sum += read_buf[i];
-
- /* Update pointer and size */
- size -= length;
- ptr += length;
- }
-
- /* Free read buffer */
- kfree(read_buf);
-
- /* Return result */
- D3(printk("checksum result: 0x%08x\n", sum));
- *result = sum;
- return 0;
-}
-
-static __inline__ void jffs_fm_write_lock(struct jffs_fmcontrol *fmc)
-{
- // down(&fmc->wlock);
-}
-
-static __inline__ void jffs_fm_write_unlock(struct jffs_fmcontrol *fmc)
-{
- // up(&fmc->wlock);
-}
-
-
-/* Create and initialize a new struct jffs_file. */
-static struct jffs_file *
-jffs_create_file(struct jffs_control *c,
- const struct jffs_raw_inode *raw_inode)
-{
- struct jffs_file *f;
-
- if (!(f = kzalloc(sizeof(*f), GFP_KERNEL))) {
- D(printk("jffs_create_file(): Failed!\n"));
- return NULL;
- }
- no_jffs_file++;
- f->ino = raw_inode->ino;
- f->pino = raw_inode->pino;
- f->nlink = raw_inode->nlink;
- f->deleted = raw_inode->deleted;
- f->c = c;
-
- return f;
-}
-
-
-/* Build a control block for the file system. */
-static struct jffs_control *
-jffs_create_control(struct super_block *sb)
-{
- struct jffs_control *c;
- register int s = sizeof(struct jffs_control);
- int i;
- D(char *t = 0);
-
- D2(printk("jffs_create_control()\n"));
-
- if (!(c = kmalloc(s, GFP_KERNEL))) {
- goto fail_control;
- }
- DJM(no_jffs_control++);
- c->root = NULL;
- c->gc_task = NULL;
- c->hash_len = JFFS_HASH_SIZE;
- s = sizeof(struct list_head) * c->hash_len;
- if (!(c->hash = kmalloc(s, GFP_KERNEL))) {
- goto fail_hash;
- }
- DJM(no_hash++);
- for (i = 0; i < c->hash_len; i++)
- INIT_LIST_HEAD(&c->hash[i]);
- if (!(c->fmc = jffs_build_begin(c, MINOR(sb->s_dev)))) {
- goto fail_fminit;
- }
- c->next_ino = JFFS_MIN_INO + 1;
- c->delete_list = (struct jffs_delete_list *) 0;
- return c;
-
-fail_fminit:
- D(t = "c->fmc");
-fail_hash:
- kfree(c);
- DJM(no_jffs_control--);
- D(t = t ? t : "c->hash");
-fail_control:
- D(t = t ? t : "control");
- D(printk("jffs_create_control(): Allocation failed: (%s)\n", t));
- return (struct jffs_control *)0;
-}
-
-
-/* Clean up all data structures associated with the file system. */
-void
-jffs_cleanup_control(struct jffs_control *c)
-{
- D2(printk("jffs_cleanup_control()\n"));
-
- if (!c) {
- D(printk("jffs_cleanup_control(): c == NULL !!!\n"));
- return;
- }
-
- while (c->delete_list) {
- struct jffs_delete_list *delete_list_element;
- delete_list_element = c->delete_list;
- c->delete_list = c->delete_list->next;
- kfree(delete_list_element);
- }
-
- /* Free all files and nodes. */
- if (c->hash) {
- jffs_foreach_file(c, jffs_free_node_list);
- jffs_foreach_file(c, jffs_free_file);
- kfree(c->hash);
- DJM(no_hash--);
- }
- jffs_cleanup_fmcontrol(c->fmc);
- kfree(c);
- DJM(no_jffs_control--);
- D3(printk("jffs_cleanup_control(): Leaving...\n"));
-}
-
-
-/* This function adds a virtual root node to the in-RAM representation.
- Called by jffs_build_fs(). */
-static int
-jffs_add_virtual_root(struct jffs_control *c)
-{
- struct jffs_file *root;
- struct jffs_node *node;
-
- D2(printk("jffs_add_virtual_root(): "
- "Creating a virtual root directory.\n"));
-
- if (!(root = kzalloc(sizeof(struct jffs_file), GFP_KERNEL))) {
- return -ENOMEM;
- }
- no_jffs_file++;
- if (!(node = jffs_alloc_node())) {
- kfree(root);
- no_jffs_file--;
- return -ENOMEM;
- }
- DJM(no_jffs_node++);
- memset(node, 0, sizeof(struct jffs_node));
- node->ino = JFFS_MIN_INO;
- root->ino = JFFS_MIN_INO;
- root->mode = S_IFDIR | S_IRWXU | S_IRGRP
- | S_IXGRP | S_IROTH | S_IXOTH;
- root->atime = root->mtime = root->ctime = get_seconds();
- root->nlink = 1;
- root->c = c;
- root->version_head = root->version_tail = node;
- jffs_insert_file_into_hash(root);
- return 0;
-}
-
-
-/* This is where the file system is built and initialized. */
-int
-jffs_build_fs(struct super_block *sb)
-{
- struct jffs_control *c;
- int err = 0;
-
- D2(printk("jffs_build_fs()\n"));
-
- if (!(c = jffs_create_control(sb))) {
- return -ENOMEM;
- }
- c->building_fs = 1;
- c->sb = sb;
- if ((err = jffs_scan_flash(c)) < 0) {
- if(err == -EAGAIN){
- /* scan_flash() wants us to try once more. A flipping
- bits sector was detect in the middle of the scan flash.
- Clean up old allocated memory before going in.
- */
- D1(printk("jffs_build_fs: Cleaning up all control structures,"
- " reallocating them and trying mount again.\n"));
- jffs_cleanup_control(c);
- if (!(c = jffs_create_control(sb))) {
- return -ENOMEM;
- }
- c->building_fs = 1;
- c->sb = sb;
-
- if ((err = jffs_scan_flash(c)) < 0) {
- goto jffs_build_fs_fail;
- }
- }else{
- goto jffs_build_fs_fail;
- }
- }
-
- /* Add a virtual root node if no one exists. */
- if (!jffs_find_file(c, JFFS_MIN_INO)) {
- if ((err = jffs_add_virtual_root(c)) < 0) {
- goto jffs_build_fs_fail;
- }
- }
-
- while (c->delete_list) {
- struct jffs_file *f;
- struct jffs_delete_list *delete_list_element;
-
- if ((f = jffs_find_file(c, c->delete_list->ino))) {
- f->deleted = 1;
- }
- delete_list_element = c->delete_list;
- c->delete_list = c->delete_list->next;
- kfree(delete_list_element);
- }
-
- /* Remove deleted nodes. */
- if ((err = jffs_foreach_file(c, jffs_possibly_delete_file)) < 0) {
- printk(KERN_ERR "JFFS: Failed to remove deleted nodes.\n");
- goto jffs_build_fs_fail;
- }
- /* Remove redundant nodes. (We are not interested in the
- return value in this case.) */
- jffs_foreach_file(c, jffs_remove_redundant_nodes);
- /* Try to build a tree from all the nodes. */
- if ((err = jffs_foreach_file(c, jffs_insert_file_into_tree)) < 0) {
- printk("JFFS: Failed to build tree.\n");
- goto jffs_build_fs_fail;
- }
- /* Compute the sizes of all files in the filesystem. Adjust if
- necessary. */
- if ((err = jffs_foreach_file(c, jffs_build_file)) < 0) {
- printk("JFFS: Failed to build file system.\n");
- goto jffs_build_fs_fail;
- }
- sb->s_fs_info = (void *)c;
- c->building_fs = 0;
-
- D1(jffs_print_hash_table(c));
- D1(jffs_print_tree(c->root, 0));
-
- return 0;
-
-jffs_build_fs_fail:
- jffs_cleanup_control(c);
- return err;
-} /* jffs_build_fs() */
-
-
-/*
- This checks for sectors that were being erased in their previous
- lifetimes and for some reason or the other (power fail etc.),
- the erase cycles never completed.
- As the flash array would have reverted back to read status,
- these sectors are detected by the symptom of the "flipping bits",
- i.e. bits being read back differently from the same location in
- flash if read multiple times.
- The only solution to this is to re-erase the entire
- sector.
- Unfortunately detecting "flipping bits" is not a simple exercise
- as a bit may be read back at 1 or 0 depending on the alignment
- of the stars in the universe.
- The level of confidence is in direct proportion to the number of
- scans done. By power fail testing I (Vipin) have been able to
- proove that reading twice is not enough.
- Maybe 4 times? Change NUM_REREADS to a higher number if you want
- a (even) higher degree of confidence in your mount process.
- A higher number would of course slow down your mount.
-*/
-static int check_partly_erased_sectors(struct jffs_fmcontrol *fmc){
-
-#define NUM_REREADS 4 /* see note above */
-#define READ_AHEAD_BYTES 4096 /* must be a multiple of 4,
- usually set to kernel page size */
-
- __u8 *read_buf1;
- __u8 *read_buf2;
-
- int err = 0;
- int retlen;
- int i;
- int cnt;
- __u32 offset;
- loff_t pos = 0;
- loff_t end = fmc->flash_size;
-
-
- /* Allocate read buffers */
- read_buf1 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
- if (!read_buf1)
- return -ENOMEM;
-
- read_buf2 = kmalloc(sizeof(__u8) * READ_AHEAD_BYTES, GFP_KERNEL);
- if (!read_buf2) {
- kfree(read_buf1);
- return -ENOMEM;
- }
-
- CHECK_NEXT:
- while(pos < end){
-
- D1(printk("check_partly_erased_sector():checking sector which contains"
- " offset 0x%x for flipping bits..\n", (__u32)pos));
-
- retlen = flash_safe_read(fmc->mtd, pos,
- &read_buf1[0], READ_AHEAD_BYTES);
- retlen &= ~3;
-
- for(cnt = 0; cnt < NUM_REREADS; cnt++){
- (void)flash_safe_read(fmc->mtd, pos,
- &read_buf2[0], READ_AHEAD_BYTES);
-
- for (i=0 ; i < retlen ; i+=4) {
- /* buffers MUST match, double word for word! */
- if(*((__u32 *) &read_buf1[i]) !=
- *((__u32 *) &read_buf2[i])
- ){
- /* flipping bits detected, time to erase sector */
- /* This will help us log some statistics etc. */
- D1(printk("Flipping bits detected in re-read round:%i of %i\n",
- cnt, NUM_REREADS));
- D1(printk("check_partly_erased_sectors:flipping bits detected"
- " @offset:0x%x(0x%x!=0x%x)\n",
- (__u32)pos+i, *((__u32 *) &read_buf1[i]),
- *((__u32 *) &read_buf2[i])));
-
- /* calculate start of present sector */
- offset = (((__u32)pos+i)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size;
-
- D1(printk("check_partly_erased_sector():erasing sector starting 0x%x.\n",
- offset));
-
- if (flash_erase_region(fmc->mtd,
- offset, fmc->sector_size) < 0) {
- printk(KERN_ERR "JFFS: Erase of flash failed. "
- "offset = %u, erase_size = %d\n",
- offset , fmc->sector_size);
-
- err = -EIO;
- goto returnBack;
-
- }else{
- D1(printk("JFFS: Erase of flash sector @0x%x successful.\n",
- offset));
- /* skip ahead to the next sector */
- pos = (((__u32)pos+i)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size;
- pos += fmc->sector_size;
- goto CHECK_NEXT;
- }
- }
- }
- }
- pos += READ_AHEAD_BYTES;
- }
-
- returnBack:
- kfree(read_buf1);
- kfree(read_buf2);
-
- D2(printk("check_partly_erased_sector():Done checking all sectors till offset 0x%x for flipping bits.\n",
- (__u32)pos));
-
- return err;
-
-}/* end check_partly_erased_sectors() */
-
-
-
-/* Scan the whole flash memory in order to find all nodes in the
- file systems. */
-static int
-jffs_scan_flash(struct jffs_control *c)
-{
- char name[JFFS_MAX_NAME_LEN + 2];
- struct jffs_raw_inode raw_inode;
- struct jffs_node *node = NULL;
- struct jffs_fmcontrol *fmc = c->fmc;
- __u32 checksum;
- __u8 tmp_accurate;
- __u16 tmp_chksum;
- __u32 deleted_file;
- loff_t pos = 0;
- loff_t start;
- loff_t test_start;
- loff_t end = fmc->flash_size;
- __u8 *read_buf;
- int i, len, retlen;
- __u32 offset;
-
- __u32 free_chunk_size1;
- __u32 free_chunk_size2;
-
-
-#define NUMFREEALLOWED 2 /* 2 chunks of at least erase size space allowed */
- int num_free_space = 0; /* Flag err if more than TWO
- free blocks found. This is NOT allowed
- by the current jffs design.
- */
- int num_free_spc_not_accp = 0; /* For debugging purposed keep count
- of how much free space was rejected and
- marked dirty
- */
-
- D1(printk("jffs_scan_flash(): start pos = 0x%lx, end = 0x%lx\n",
- (long)pos, (long)end));
-
- flash_safe_acquire(fmc->mtd);
-
- /*
- check and make sure that any sector does not suffer
- from the "partly erased, bit flipping syndrome" (TM Vipin :)
- If so, offending sectors will be erased.
- */
- if(check_partly_erased_sectors(fmc) < 0){
-
- flash_safe_release(fmc->mtd);
- return -EIO; /* bad, bad, bad error. Cannot continue.*/
- }
-
- /* Allocate read buffer */
- read_buf = kmalloc(sizeof(__u8) * 4096, GFP_KERNEL);
- if (!read_buf) {
- flash_safe_release(fmc->mtd);
- return -ENOMEM;
- }
-
- /* Start the scan. */
- while (pos < end) {
- deleted_file = 0;
-
- /* Remember the position from where we started this scan. */
- start = pos;
-
- switch (flash_read_u32(fmc->mtd, pos)) {
- case JFFS_EMPTY_BITMASK:
- /* We have found 0xffffffff at this position. We have to
- scan the rest of the flash till the end or till
- something else than 0xffffffff is found.
- Keep going till we do not find JFFS_EMPTY_BITMASK
- anymore */
-
- D1(printk("jffs_scan_flash(): 0xffffffff at pos 0x%lx.\n",
- (long)pos));
-
- while(pos < end){
-
- len = end - pos < 4096 ? end - pos : 4096;
-
- retlen = flash_safe_read(fmc->mtd, pos,
- &read_buf[0], len);
-
- retlen &= ~3;
-
- for (i=0 ; i < retlen ; i+=4, pos += 4) {
- if(*((__u32 *) &read_buf[i]) !=
- JFFS_EMPTY_BITMASK)
- break;
- }
- if (i == retlen)
- continue;
- else
- break;
- }
-
- D1(printk("jffs_scan_flash():0xffffffff ended at pos 0x%lx.\n",
- (long)pos));
-
- /* If some free space ends in the middle of a sector,
- treat it as dirty rather than clean.
- This is to handle the case where one thread
- allocated space for a node, but didn't get to
- actually _write_ it before power was lost, leaving
- a gap in the log. Shifting all node writes into
- a single kernel thread will fix the original problem.
- */
- if ((__u32) pos % fmc->sector_size) {
- /* If there was free space in previous
- sectors, don't mark that dirty too -
- only from the beginning of this sector
- (or from start)
- */
-
- test_start = pos & ~(fmc->sector_size-1); /* end of last sector */
-
- if (start < test_start) {
-
- /* free space started in the previous sector! */
-
- if((num_free_space < NUMFREEALLOWED) &&
- ((unsigned int)(test_start - start) >= fmc->sector_size)){
-
- /*
- Count it in if we are still under NUMFREEALLOWED *and* it is
- at least 1 erase sector in length. This will keep us from
- picking any little ole' space as "free".
- */
-
- D1(printk("Reducing end of free space to 0x%x from 0x%x\n",
- (unsigned int)test_start, (unsigned int)pos));
-
- D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n",
- (unsigned int) start,
- (unsigned int)(test_start - start)));
-
- /* below, space from "start" to "pos" will be marked dirty. */
- start = test_start;
-
- /* Being in here means that we have found at least an entire
- erase sector size of free space ending on a sector boundary.
- Keep track of free spaces accepted.
- */
- num_free_space++;
- }else{
- num_free_spc_not_accp++;
- D1(printk("Free space (#%i) found but *Not* accepted: Starting"
- " 0x%x for 0x%x bytes\n",
- num_free_spc_not_accp, (unsigned int)start,
- (unsigned int)((unsigned int)(pos & ~(fmc->sector_size-1)) - (unsigned int)start)));
-
- }
-
- }
- if((((__u32)(pos - start)) != 0)){
-
- D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n",
- (unsigned int) start, (unsigned int) (pos - start)));
- jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), NULL);
- }else{
- /* "Flipping bits" detected. This means that our scan for them
- did not catch this offset. See check_partly_erased_sectors() for
- more info.
- */
-
- D1(printk("jffs_scan_flash():wants to allocate dirty flash "
- "space for 0 bytes.\n"));
- D1(printk("jffs_scan_flash(): Flipping bits! We will free "
- "all allocated memory, erase this sector and remount\n"));
-
- /* calculate start of present sector */
- offset = (((__u32)pos)/(__u32)fmc->sector_size) * (__u32)fmc->sector_size;
-
- D1(printk("jffs_scan_flash():erasing sector starting 0x%x.\n",
- offset));
-
- if (flash_erase_region(fmc->mtd,
- offset, fmc->sector_size) < 0) {
- printk(KERN_ERR "JFFS: Erase of flash failed. "
- "offset = %u, erase_size = %d\n",
- offset , fmc->sector_size);
-
- flash_safe_release(fmc->mtd);
- kfree(read_buf);
- return -1; /* bad, bad, bad! */
-
- }
- flash_safe_release(fmc->mtd);
- kfree(read_buf);
-
- return -EAGAIN; /* erased offending sector. Try mount one more time please. */
- }
- }else{
- /* Being in here means that we have found free space that ends on an erase sector
- boundary.
- Count it in if we are still under NUMFREEALLOWED *and* it is at least 1 erase
- sector in length. This will keep us from picking any little ole' space as "free".
- */
- if((num_free_space < NUMFREEALLOWED) &&
- ((unsigned int)(pos - start) >= fmc->sector_size)){
- /* We really don't do anything to mark space as free, except *not*
- mark it dirty and just advance the "pos" location pointer.
- It will automatically be picked up as free space.
- */
- num_free_space++;
- D1(printk("Free space accepted: Starting 0x%x for 0x%x bytes\n",
- (unsigned int) start, (unsigned int) (pos - start)));
- }else{
- num_free_spc_not_accp++;
- D1(printk("Free space (#%i) found but *Not* accepted: Starting "
- "0x%x for 0x%x bytes\n", num_free_spc_not_accp,
- (unsigned int) start,
- (unsigned int) (pos - start)));
-
- /* Mark this space as dirty. We already have our free space. */
- D1(printk("Dirty space: Starting 0x%x for 0x%x bytes\n",
- (unsigned int) start, (unsigned int) (pos - start)));
- jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), NULL);
- }
-
- }
- if(num_free_space > NUMFREEALLOWED){
- printk(KERN_WARNING "jffs_scan_flash(): Found free space "
- "number %i. Only %i free space is allowed.\n",
- num_free_space, NUMFREEALLOWED);
- }
- continue;
-
- case JFFS_DIRTY_BITMASK:
- /* We have found 0x00000000 at this position. Scan as far
- as possible to find out how much is dirty. */
- D1(printk("jffs_scan_flash(): 0x00000000 at pos 0x%lx.\n",
- (long)pos));
- for (; pos < end
- && JFFS_DIRTY_BITMASK == flash_read_u32(fmc->mtd, pos);
- pos += 4);
- D1(printk("jffs_scan_flash(): 0x00 ended at "
- "pos 0x%lx.\n", (long)pos));
- jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), NULL);
- continue;
-
- case JFFS_MAGIC_BITMASK:
- /* We have probably found a new raw inode. */
- break;
-
- default:
- bad_inode:
- /* We're f*cked. This is not solved yet. We have
- to scan for the magic pattern. */
- D1(printk("*************** Dirty flash memory or "
- "bad inode: "
- "hexdump(pos = 0x%lx, len = 128):\n",
- (long)pos));
- D1(jffs_hexdump(fmc->mtd, pos, 128));
-
- for (pos += 4; pos < end; pos += 4) {
- switch (flash_read_u32(fmc->mtd, pos)) {
- case JFFS_MAGIC_BITMASK:
- case JFFS_EMPTY_BITMASK:
- /* handle these in the main switch() loop */
- goto cont_scan;
-
- default:
- break;
- }
- }
-
- cont_scan:
- /* First, mark as dirty the region
- which really does contain crap. */
- jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start),
- NULL);
-
- continue;
- }/* switch */
-
- /* We have found the beginning of an inode. Create a
- node for it unless there already is one available. */
- if (!node) {
- if (!(node = jffs_alloc_node())) {
- /* Free read buffer */
- kfree(read_buf);
-
- /* Release the flash device */
- flash_safe_release(fmc->mtd);
-
- return -ENOMEM;
- }
- DJM(no_jffs_node++);
- }
-
- /* Read the next raw inode. */
-
- flash_safe_read(fmc->mtd, pos, (u_char *) &raw_inode,
- sizeof(struct jffs_raw_inode));
-
- /* When we compute the checksum for the inode, we never
- count the 'accurate' or the 'checksum' fields. */
- tmp_accurate = raw_inode.accurate;
- tmp_chksum = raw_inode.chksum;
- raw_inode.accurate = 0;
- raw_inode.chksum = 0;
- checksum = jffs_checksum(&raw_inode,
- sizeof(struct jffs_raw_inode));
- raw_inode.accurate = tmp_accurate;
- raw_inode.chksum = tmp_chksum;
-
- D3(printk("*** We have found this raw inode at pos 0x%lx "
- "on the flash:\n", (long)pos));
- D3(jffs_print_raw_inode(&raw_inode));
-
- if (checksum != raw_inode.chksum) {
- D1(printk("jffs_scan_flash(): Bad checksum: "
- "checksum = %u, "
- "raw_inode.chksum = %u\n",
- checksum, raw_inode.chksum));
- pos += sizeof(struct jffs_raw_inode);
- jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), NULL);
- /* Reuse this unused struct jffs_node. */
- continue;
- }
-
- /* Check the raw inode read so far. Start with the
- maximum length of the filename. */
- if (raw_inode.nsize > JFFS_MAX_NAME_LEN) {
- printk(KERN_WARNING "jffs_scan_flash: Found a "
- "JFFS node with name too large\n");
- goto bad_inode;
- }
-
- if (raw_inode.rename && raw_inode.dsize != sizeof(__u32)) {
- printk(KERN_WARNING "jffs_scan_flash: Found a "
- "rename node with dsize %u.\n",
- raw_inode.dsize);
- jffs_print_raw_inode(&raw_inode);
- goto bad_inode;
- }
-
- /* The node's data segment should not exceed a
- certain length. */
- if (raw_inode.dsize > fmc->max_chunk_size) {
- printk(KERN_WARNING "jffs_scan_flash: Found a "
- "JFFS node with dsize (0x%x) > max_chunk_size (0x%x)\n",
- raw_inode.dsize, fmc->max_chunk_size);
- goto bad_inode;
- }
-
- pos += sizeof(struct jffs_raw_inode);
-
- /* This shouldn't be necessary because a node that
- violates the flash boundaries shouldn't be written
- in the first place. */
- if (pos >= end) {
- goto check_node;
- }
-
- /* Read the name. */
- *name = 0;
- if (raw_inode.nsize) {
- flash_safe_read(fmc->mtd, pos, name, raw_inode.nsize);
- name[raw_inode.nsize] = '\0';
- pos += raw_inode.nsize
- + JFFS_GET_PAD_BYTES(raw_inode.nsize);
- D3(printk("name == \"%s\"\n", name));
- checksum = jffs_checksum(name, raw_inode.nsize);
- if (checksum != raw_inode.nchksum) {
- D1(printk("jffs_scan_flash(): Bad checksum: "
- "checksum = %u, "
- "raw_inode.nchksum = %u\n",
- checksum, raw_inode.nchksum));
- jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), NULL);
- /* Reuse this unused struct jffs_node. */
- continue;
- }
- if (pos >= end) {
- goto check_node;
- }
- }
-
- /* Read the data, if it exists, in order to be sure it
- matches the checksum. */
- if (raw_inode.dsize) {
- if (raw_inode.rename) {
- deleted_file = flash_read_u32(fmc->mtd, pos);
- }
- if (jffs_checksum_flash(fmc->mtd, pos, raw_inode.dsize, &checksum)) {
- printk("jffs_checksum_flash() failed to calculate a checksum\n");
- jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), NULL);
- /* Reuse this unused struct jffs_node. */
- continue;
- }
- pos += raw_inode.dsize
- + JFFS_GET_PAD_BYTES(raw_inode.dsize);
-
- if (checksum != raw_inode.dchksum) {
- D1(printk("jffs_scan_flash(): Bad checksum: "
- "checksum = %u, "
- "raw_inode.dchksum = %u\n",
- checksum, raw_inode.dchksum));
- jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), NULL);
- /* Reuse this unused struct jffs_node. */
- continue;
- }
- }
-
- check_node:
-
- /* Remember the highest inode number in the whole file
- system. This information will be used when assigning
- new files new inode numbers. */
- if (c->next_ino <= raw_inode.ino) {
- c->next_ino = raw_inode.ino + 1;
- }
-
- if (raw_inode.accurate) {
- int err;
- node->data_offset = raw_inode.offset;
- node->data_size = raw_inode.dsize;
- node->removed_size = raw_inode.rsize;
- /* Compute the offset to the actual data in the
- on-flash node. */
- node->fm_offset
- = sizeof(struct jffs_raw_inode)
- + raw_inode.nsize
- + JFFS_GET_PAD_BYTES(raw_inode.nsize);
- node->fm = jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start),
- node);
- if (!node->fm) {
- D(printk("jffs_scan_flash(): !node->fm\n"));
- jffs_free_node(node);
- DJM(no_jffs_node--);
-
- /* Free read buffer */
- kfree(read_buf);
-
- /* Release the flash device */
- flash_safe_release(fmc->mtd);
-
- return -ENOMEM;
- }
- if ((err = jffs_insert_node(c, NULL, &raw_inode,
- name, node)) < 0) {
- printk("JFFS: Failed to handle raw inode. "
- "(err = %d)\n", err);
- break;
- }
- if (raw_inode.rename) {
- struct jffs_delete_list *dl
- = (struct jffs_delete_list *)
- kmalloc(sizeof(struct jffs_delete_list),
- GFP_KERNEL);
- if (!dl) {
- D(printk("jffs_scan_flash: !dl\n"));
- jffs_free_node(node);
- DJM(no_jffs_node--);
-
- /* Release the flash device */
- flash_safe_release(fmc->flash_part);
-
- /* Free read buffer */
- kfree(read_buf);
-
- return -ENOMEM;
- }
- dl->ino = deleted_file;
- dl->next = c->delete_list;
- c->delete_list = dl;
- node->data_size = 0;
- }
- D3(jffs_print_node(node));
- node = NULL; /* Don't free the node! */
- }
- else {
- jffs_fmalloced(fmc, (__u32) start,
- (__u32) (pos - start), NULL);
- D3(printk("jffs_scan_flash(): Just found an obsolete "
- "raw_inode. Continuing the scan...\n"));
- /* Reuse this unused struct jffs_node. */
- }
- }
-
- if (node) {
- jffs_free_node(node);
- DJM(no_jffs_node--);
- }
- jffs_build_end(fmc);
-
- /* Free read buffer */
- kfree(read_buf);
-
- if(!num_free_space){
- printk(KERN_WARNING "jffs_scan_flash(): Did not find even a single "
- "chunk of free space. This is BAD!\n");
- }
-
- /* Return happy */
- D3(printk("jffs_scan_flash(): Leaving...\n"));
- flash_safe_release(fmc->mtd);
-
- /* This is to trap the "free size accounting screwed error. */
- free_chunk_size1 = jffs_free_size1(fmc);
- free_chunk_size2 = jffs_free_size2(fmc);
-
- if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) {
-
- printk(KERN_WARNING "jffs_scan_falsh():Free size accounting screwed\n");
- printk(KERN_WARNING "jfffs_scan_flash():free_chunk_size1 == 0x%x, "
- "free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n",
- free_chunk_size1, free_chunk_size2, fmc->free_size);
-
- return -1; /* Do NOT mount f/s so that we can inspect what happened.
- Mounting this screwed up f/s will screw us up anyway.
- */
- }
-
- return 0; /* as far as we are concerned, we are happy! */
-} /* jffs_scan_flash() */
-
-
-/* Insert any kind of node into the file system. Take care of data
- insertions and deletions. Also remove redundant information. The
- memory allocated for the `name' is regarded as "given away" in the
- caller's perspective. */
-int
-jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
- const struct jffs_raw_inode *raw_inode,
- const char *name, struct jffs_node *node)
-{
- int update_name = 0;
- int insert_into_tree = 0;
-
- D2(printk("jffs_insert_node(): ino = %u, version = %u, "
- "name = \"%s\", deleted = %d\n",
- raw_inode->ino, raw_inode->version,
- ((name && *name) ? name : ""), raw_inode->deleted));
-
- /* If there doesn't exist an associated jffs_file, then
- create, initialize and insert one into the file system. */
- if (!f && !(f = jffs_find_file(c, raw_inode->ino))) {
- if (!(f = jffs_create_file(c, raw_inode))) {
- return -ENOMEM;
- }
- jffs_insert_file_into_hash(f);
- insert_into_tree = 1;
- }
- node->ino = raw_inode->ino;
- node->version = raw_inode->version;
- node->data_size = raw_inode->dsize;
- node->fm_offset = sizeof(struct jffs_raw_inode) + raw_inode->nsize
- + JFFS_GET_PAD_BYTES(raw_inode->nsize);
- node->name_size = raw_inode->nsize;
-
- /* Now insert the node at the correct position into the file's
- version list. */
- if (!f->version_head) {
- /* This is the first node. */
- f->version_head = node;
- f->version_tail = node;
- node->version_prev = NULL;
- node->version_next = NULL;
- f->highest_version = node->version;
- update_name = 1;
- f->mode = raw_inode->mode;
- f->uid = raw_inode->uid;
- f->gid = raw_inode->gid;
- f->atime = raw_inode->atime;
- f->mtime = raw_inode->mtime;
- f->ctime = raw_inode->ctime;
- }
- else if ((f->highest_version < node->version)
- || (node->version == 0)) {
- /* Insert at the end of the list. I.e. this node is the
- newest one so far. */
- node->version_prev = f->version_tail;
- node->version_next = NULL;
- f->version_tail->version_next = node;
- f->version_tail = node;
- f->highest_version = node->version;
- update_name = 1;
- f->pino = raw_inode->pino;
- f->mode = raw_inode->mode;
- f->uid = raw_inode->uid;
- f->gid = raw_inode->gid;
- f->atime = raw_inode->atime;
- f->mtime = raw_inode->mtime;
- f->ctime = raw_inode->ctime;
- }
- else if (f->version_head->version > node->version) {
- /* Insert at the bottom of the list. */
- node->version_prev = NULL;
- node->version_next = f->version_head;
- f->version_head->version_prev = node;
- f->version_head = node;
- if (!f->name) {
- update_name = 1;
- }
- }
- else {
- struct jffs_node *n;
- int newer_name = 0;
- /* Search for the insertion position starting from
- the tail (newest node). */
- for (n = f->version_tail; n; n = n->version_prev) {
- if (n->version < node->version) {
- node->version_prev = n;
- node->version_next = n->version_next;
- node->version_next->version_prev = node;
- n->version_next = node;
- if (!newer_name) {
- update_name = 1;
- }
- break;
- }
- if (n->name_size) {
- newer_name = 1;
- }
- }
- }
-
- /* Deletion is irreversible. If any 'deleted' node is ever
- written, the file is deleted */
- if (raw_inode->deleted)
- f->deleted = raw_inode->deleted;
-
- /* Perhaps update the name. */
- if (raw_inode->nsize && update_name && name && *name && (name != f->name)) {
- if (f->name) {
- kfree(f->name);
- DJM(no_name--);
- }
- if (!(f->name = kmalloc(raw_inode->nsize + 1,
- GFP_KERNEL))) {
- return -ENOMEM;
- }
- DJM(no_name++);
- memcpy(f->name, name, raw_inode->nsize);
- f->name[raw_inode->nsize] = '\0';
- f->nsize = raw_inode->nsize;
- D3(printk("jffs_insert_node(): Updated the name of "
- "the file to \"%s\".\n", name));
- }
-
- if (!c->building_fs) {
- D3(printk("jffs_insert_node(): ---------------------------"
- "------------------------------------------- 1\n"));
- if (insert_into_tree) {
- jffs_insert_file_into_tree(f);
- }
- /* Once upon a time, we would call jffs_possibly_delete_file()
- here. That causes an oops if someone's still got the file
- open, so now we only do it in jffs_delete_inode()
- -- dwmw2
- */
- if (node->data_size || node->removed_size) {
- jffs_update_file(f, node);
- }
- jffs_remove_redundant_nodes(f);
-
- jffs_garbage_collect_trigger(c);
-
- D3(printk("jffs_insert_node(): ---------------------------"
- "------------------------------------------- 2\n"));
- }
-
- return 0;
-} /* jffs_insert_node() */
-
-
-/* Unlink a jffs_node from the version list it is in. */
-static inline void
-jffs_unlink_node_from_version_list(struct jffs_file *f,
- struct jffs_node *node)
-{
- if (node->version_prev) {
- node->version_prev->version_next = node->version_next;
- } else {
- f->version_head = node->version_next;
- }
- if (node->version_next) {
- node->version_next->version_prev = node->version_prev;
- } else {
- f->version_tail = node->version_prev;
- }
-}
-
-
-/* Unlink a jffs_node from the range list it is in. */
-static inline void
-jffs_unlink_node_from_range_list(struct jffs_file *f, struct jffs_node *node)
-{
- if (node->range_prev) {
- node->range_prev->range_next = node->range_next;
- }
- else {
- f->range_head = node->range_next;
- }
- if (node->range_next) {
- node->range_next->range_prev = node->range_prev;
- }
- else {
- f->range_tail = node->range_prev;
- }
-}
-
-
-/* Function used by jffs_remove_redundant_nodes() below. This function
- classifies what kind of information a node adds to a file. */
-static inline __u8
-jffs_classify_node(struct jffs_node *node)
-{
- __u8 mod_type = JFFS_MODIFY_INODE;
-
- if (node->name_size) {
- mod_type |= JFFS_MODIFY_NAME;
- }
- if (node->data_size || node->removed_size) {
- mod_type |= JFFS_MODIFY_DATA;
- }
- return mod_type;
-}
-
-
-/* Remove redundant nodes from a file. Mark the on-flash memory
- as dirty. */
-static int
-jffs_remove_redundant_nodes(struct jffs_file *f)
-{
- struct jffs_node *newest_node;
- struct jffs_node *cur;
- struct jffs_node *prev;
- __u8 newest_type;
- __u8 mod_type;
- __u8 node_with_name_later = 0;
-
- if (!(newest_node = f->version_tail)) {
- return 0;
- }
-
- /* What does the `newest_node' modify? */
- newest_type = jffs_classify_node(newest_node);
- node_with_name_later = newest_type & JFFS_MODIFY_NAME;
-
- D3(printk("jffs_remove_redundant_nodes(): ino: %u, name: \"%s\", "
- "newest_type: %u\n", f->ino, (f->name ? f->name : ""),
- newest_type));
-
- /* Traverse the file's nodes and determine which of them that are
- superfluous. Yeah, this might look very complex at first
- glance but it is actually very simple. */
- for (cur = newest_node->version_prev; cur; cur = prev) {
- prev = cur->version_prev;
- mod_type = jffs_classify_node(cur);
- if ((mod_type <= JFFS_MODIFY_INODE)
- || ((newest_type & JFFS_MODIFY_NAME)
- && (mod_type
- <= (JFFS_MODIFY_INODE + JFFS_MODIFY_NAME)))
- || (cur->data_size == 0 && cur->removed_size
- && !cur->version_prev && node_with_name_later)) {
- /* Yes, this node is redundant. Remove it. */
- D2(printk("jffs_remove_redundant_nodes(): "
- "Removing node: ino: %u, version: %u, "
- "mod_type: %u\n", cur->ino, cur->version,
- mod_type));
- jffs_unlink_node_from_version_list(f, cur);
- jffs_fmfree(f->c->fmc, cur->fm, cur);
- jffs_free_node(cur);
- DJM(no_jffs_node--);
- }
- else {
- node_with_name_later |= (mod_type & JFFS_MODIFY_NAME);
- }
- }
-
- return 0;
-}
-
-
-/* Insert a file into the hash table. */
-static int
-jffs_insert_file_into_hash(struct jffs_file *f)
-{
- int i = f->ino % f->c->hash_len;
-
- D3(printk("jffs_insert_file_into_hash(): f->ino: %u\n", f->ino));
-
- list_add(&f->hash, &f->c->hash[i]);
- return 0;
-}
-
-
-/* Insert a file into the file system tree. */
-int
-jffs_insert_file_into_tree(struct jffs_file *f)
-{
- struct jffs_file *parent;
-
- D3(printk("jffs_insert_file_into_tree(): name: \"%s\"\n",
- (f->name ? f->name : "")));
-
- if (!(parent = jffs_find_file(f->c, f->pino))) {
- if (f->pino == 0) {
- f->c->root = f;
- f->parent = NULL;
- f->sibling_prev = NULL;
- f->sibling_next = NULL;
- return 0;
- }
- else {
- D1(printk("jffs_insert_file_into_tree(): Found "
- "inode with no parent and pino == %u\n",
- f->pino));
- return -1;
- }
- }
- f->parent = parent;
- f->sibling_next = parent->children;
- if (f->sibling_next) {
- f->sibling_next->sibling_prev = f;
- }
- f->sibling_prev = NULL;
- parent->children = f;
- return 0;
-}
-
-
-/* Remove a file from the hash table. */
-static int
-jffs_unlink_file_from_hash(struct jffs_file *f)
-{
- D3(printk("jffs_unlink_file_from_hash(): f: 0x%p, "
- "ino %u\n", f, f->ino));
-
- list_del(&f->hash);
- return 0;
-}
-
-
-/* Just remove the file from the parent's children. Don't free
- any memory. */
-int
-jffs_unlink_file_from_tree(struct jffs_file *f)
-{
- D3(printk("jffs_unlink_file_from_tree(): ino: %d, pino: %d, name: "
- "\"%s\"\n", f->ino, f->pino, (f->name ? f->name : "")));
-
- if (f->sibling_prev) {
- f->sibling_prev->sibling_next = f->sibling_next;
- }
- else if (f->parent) {
- D3(printk("f->parent=%p\n", f->parent));
- f->parent->children = f->sibling_next;
- }
- if (f->sibling_next) {
- f->sibling_next->sibling_prev = f->sibling_prev;
- }
- return 0;
-}
-
-
-/* Find a file with its inode number. */
-struct jffs_file *
-jffs_find_file(struct jffs_control *c, __u32 ino)
-{
- struct jffs_file *f;
- int i = ino % c->hash_len;
-
- D3(printk("jffs_find_file(): ino: %u\n", ino));
-
- list_for_each_entry(f, &c->hash[i], hash) {
- if (ino != f->ino)
- continue;
- D3(printk("jffs_find_file(): Found file with ino "
- "%u. (name: \"%s\")\n",
- ino, (f->name ? f->name : ""));
- );
- return f;
- }
- D3(printk("jffs_find_file(): Didn't find file "
- "with ino %u.\n", ino);
- );
- return NULL;
-}
-
-
-/* Find a file in a directory. We are comparing the names. */
-struct jffs_file *
-jffs_find_child(struct jffs_file *dir, const char *name, int len)
-{
- struct jffs_file *f;
-
- D3(printk("jffs_find_child()\n"));
-
- for (f = dir->children; f; f = f->sibling_next) {
- if (!f->deleted && f->name
- && !strncmp(f->name, name, len)
- && f->name[len] == '\0') {
- break;
- }
- }
-
- D3(if (f) {
- printk("jffs_find_child(): Found \"%s\".\n", f->name);
- }
- else {
- char *copy = kmalloc(len + 1, GFP_KERNEL);
- if (copy) {
- memcpy(copy, name, len);
- copy[len] = '\0';
- }
- printk("jffs_find_child(): Didn't find the file \"%s\".\n",
- (copy ? copy : ""));
- kfree(copy);
- });
-
- return f;
-}
-
-
-/* Write a raw inode that takes up a certain amount of space in the flash
- memory. At the end of the flash device, there is often space that is
- impossible to use. At these times we want to mark this space as not
- used. In the cases when the amount of space is greater or equal than
- a struct jffs_raw_inode, we write a "dummy node" that takes up this
- space. The space after the raw inode, if it exists, is left as it is.
- Since this space after the raw inode contains JFFS_EMPTY_BITMASK bytes,
- we can compute the checksum of it; we don't have to manipulate it any
- further.
-
- If the space left on the device is less than the size of a struct
- jffs_raw_inode, this space is filled with JFFS_DIRTY_BITMASK bytes.
- No raw inode is written this time. */
-static int
-jffs_write_dummy_node(struct jffs_control *c, struct jffs_fm *dirty_fm)
-{
- struct jffs_fmcontrol *fmc = c->fmc;
- int err;
-
- D1(printk("jffs_write_dummy_node(): dirty_fm->offset = 0x%08x, "
- "dirty_fm->size = %u\n",
- dirty_fm->offset, dirty_fm->size));
-
- if (dirty_fm->size >= sizeof(struct jffs_raw_inode)) {
- struct jffs_raw_inode raw_inode;
- memset(&raw_inode, 0, sizeof(struct jffs_raw_inode));
- raw_inode.magic = JFFS_MAGIC_BITMASK;
- raw_inode.dsize = dirty_fm->size
- - sizeof(struct jffs_raw_inode);
- raw_inode.dchksum = raw_inode.dsize * 0xff;
- raw_inode.chksum
- = jffs_checksum(&raw_inode, sizeof(struct jffs_raw_inode));
-
- if ((err = flash_safe_write(fmc->mtd,
- dirty_fm->offset,
- (u_char *)&raw_inode,
- sizeof(struct jffs_raw_inode)))
- < 0) {
- printk(KERN_ERR "JFFS: jffs_write_dummy_node: "
- "flash_safe_write failed!\n");
- return err;
- }
- }
- else {
- flash_safe_acquire(fmc->mtd);
- flash_memset(fmc->mtd, dirty_fm->offset, 0, dirty_fm->size);
- flash_safe_release(fmc->mtd);
- }
-
- D3(printk("jffs_write_dummy_node(): Leaving...\n"));
- return 0;
-}
-
-
-/* Write a raw inode, possibly its name and possibly some data. */
-int
-jffs_write_node(struct jffs_control *c, struct jffs_node *node,
- struct jffs_raw_inode *raw_inode,
- const char *name, const unsigned char *data,
- int recoverable,
- struct jffs_file *f)
-{
- struct jffs_fmcontrol *fmc = c->fmc;
- struct jffs_fm *fm;
- struct kvec node_iovec[4];
- unsigned long iovec_cnt;
-
- __u32 pos;
- int err;
- __u32 slack = 0;
-
- __u32 total_name_size = raw_inode->nsize
- + JFFS_GET_PAD_BYTES(raw_inode->nsize);
- __u32 total_data_size = raw_inode->dsize
- + JFFS_GET_PAD_BYTES(raw_inode->dsize);
- __u32 total_size = sizeof(struct jffs_raw_inode)
- + total_name_size + total_data_size;
-
- /* If this node isn't something that will eventually let
- GC free even more space, then don't allow it unless
- there's at least max_chunk_size space still available
- */
- if (!recoverable)
- slack = fmc->max_chunk_size;
-
-
- /* Fire the retrorockets and shoot the fruiton torpedoes, sir! */
-
- ASSERT(if (!node) {
- printk("jffs_write_node(): node == NULL\n");
- return -EINVAL;
- });
- ASSERT(if (raw_inode && raw_inode->nsize && !name) {
- printk("*** jffs_write_node(): nsize = %u but name == NULL\n",
- raw_inode->nsize);
- return -EINVAL;
- });
-
- D1(printk("jffs_write_node(): filename = \"%s\", ino = %u, "
- "total_size = %u\n",
- (name ? name : ""), raw_inode->ino,
- total_size));
-
- jffs_fm_write_lock(fmc);
-
-retry:
- fm = NULL;
- err = 0;
- while (!fm) {
-
- /* Deadlocks suck. */
- while(fmc->free_size < fmc->min_free_size + total_size + slack) {
- jffs_fm_write_unlock(fmc);
- if (!JFFS_ENOUGH_SPACE(c, total_size + slack))
- return -ENOSPC;
- jffs_fm_write_lock(fmc);
- }
-
- /* First try to allocate some flash memory. */
- err = jffs_fmalloc(fmc, total_size, node, &fm);
-
- if (err == -ENOSPC) {
- /* Just out of space. GC and try again */
- if (fmc->dirty_size < fmc->sector_size) {
- D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "
- "failed, no dirty space to GC\n", fmc,
- total_size));
- return err;
- }
-
- D1(printk(KERN_INFO "jffs_write_node(): Calling jffs_garbage_collect_now()\n"));
- jffs_fm_write_unlock(fmc);
- if ((err = jffs_garbage_collect_now(c))) {
- D(printk("jffs_write_node(): jffs_garbage_collect_now() failed\n"));
- return err;
- }
- jffs_fm_write_lock(fmc);
- continue;
- }
-
- if (err < 0) {
- jffs_fm_write_unlock(fmc);
-
- D(printk("jffs_write_node(): jffs_fmalloc(0x%p, %u) "
- "failed!\n", fmc, total_size));
- return err;
- }
-
- if (!fm->nodes) {
- /* The jffs_fm struct that we got is not good enough.
- Make that space dirty and try again */
- if ((err = jffs_write_dummy_node(c, fm)) < 0) {
- kfree(fm);
- DJM(no_jffs_fm--);
- jffs_fm_write_unlock(fmc);
- D(printk("jffs_write_node(): "
- "jffs_write_dummy_node(): Failed!\n"));
- return err;
- }
- fm = NULL;
- }
- } /* while(!fm) */
- node->fm = fm;
-
- ASSERT(if (fm->nodes == 0) {
- printk(KERN_ERR "jffs_write_node(): fm->nodes == 0\n");
- });
-
- pos = node->fm->offset;
-
- /* Increment the version number here. We can't let the caller
- set it beforehand, because we might have had to do GC on a node
- of this file - and we'd end up reusing version numbers.
- */
- if (f) {
- raw_inode->version = f->highest_version + 1;
- D1(printk (KERN_NOTICE "jffs_write_node(): setting version of %s to %d\n", f->name, raw_inode->version));
-
- /* if the file was deleted, set the deleted bit in the raw inode */
- if (f->deleted)
- raw_inode->deleted = 1;
- }
-
- /* Compute the checksum for the data and name chunks. */
- raw_inode->dchksum = jffs_checksum(data, raw_inode->dsize);
- raw_inode->nchksum = jffs_checksum(name, raw_inode->nsize);
-
- /* The checksum is calculated without the chksum and accurate
- fields so set them to zero first. */
- raw_inode->accurate = 0;
- raw_inode->chksum = 0;
- raw_inode->chksum = jffs_checksum(raw_inode,
- sizeof(struct jffs_raw_inode));
- raw_inode->accurate = 0xff;
-
- D3(printk("jffs_write_node(): About to write this raw inode to the "
- "flash at pos 0x%lx:\n", (long)pos));
- D3(jffs_print_raw_inode(raw_inode));
-
- /* The actual raw JFFS node */
- node_iovec[0].iov_base = (void *) raw_inode;
- node_iovec[0].iov_len = (size_t) sizeof(struct jffs_raw_inode);
- iovec_cnt = 1;
-
- /* Get name and size if there is one */
- if (raw_inode->nsize) {
- node_iovec[iovec_cnt].iov_base = (void *) name;
- node_iovec[iovec_cnt].iov_len = (size_t) raw_inode->nsize;
- iovec_cnt++;
-
- if (JFFS_GET_PAD_BYTES(raw_inode->nsize)) {
- static unsigned char allff[3]={255,255,255};
- /* Add some extra padding if necessary */
- node_iovec[iovec_cnt].iov_base = allff;
- node_iovec[iovec_cnt].iov_len =
- JFFS_GET_PAD_BYTES(raw_inode->nsize);
- iovec_cnt++;
- }
- }
-
- /* Get data and size if there is any */
- if (raw_inode->dsize) {
- node_iovec[iovec_cnt].iov_base = (void *) data;
- node_iovec[iovec_cnt].iov_len = (size_t) raw_inode->dsize;
- iovec_cnt++;
- /* No need to pad this because we're not actually putting
- anything after it.
- */
- }
-
- if ((err = flash_safe_writev(fmc->mtd, node_iovec, iovec_cnt,
- pos)) < 0) {
- jffs_fmfree_partly(fmc, fm, 0);
- jffs_fm_write_unlock(fmc);
- printk(KERN_ERR "JFFS: jffs_write_node: Failed to write, "
- "requested %i, wrote %i\n", total_size, err);
- goto retry;
- }
- if (raw_inode->deleted)
- f->deleted = 1;
-
- jffs_fm_write_unlock(fmc);
- D3(printk("jffs_write_node(): Leaving...\n"));
- return raw_inode->dsize;
-} /* jffs_write_node() */
-
-
-/* Read data from the node and write it to the buffer. 'node_offset'
- is how much we have read from this particular node before and which
- shouldn't be read again. 'max_size' is how much space there is in
- the buffer. */
-static int
-jffs_get_node_data(struct jffs_file *f, struct jffs_node *node,
- unsigned char *buf,__u32 node_offset, __u32 max_size)
-{
- struct jffs_fmcontrol *fmc = f->c->fmc;
- __u32 pos = node->fm->offset + node->fm_offset + node_offset;
- __u32 avail = node->data_size - node_offset;
- __u32 r;
-
- D2(printk(" jffs_get_node_data(): file: \"%s\", ino: %u, "
- "version: %u, node_offset: %u\n",
- f->name, node->ino, node->version, node_offset));
-
- r = min(avail, max_size);
- D3(printk(KERN_NOTICE "jffs_get_node_data\n"));
- flash_safe_read(fmc->mtd, pos, buf, r);
-
- D3(printk(" jffs_get_node_data(): Read %u byte%s.\n",
- r, (r == 1 ? "" : "s")));
-
- return r;
-}
-
-
-/* Read data from the file's nodes. Write the data to the buffer
- 'buf'. 'read_offset' tells how much data we should skip. */
-int
-jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset,
- __u32 size)
-{
- struct jffs_node *node;
- __u32 read_data = 0; /* Total amount of read data. */
- __u32 node_offset = 0;
- __u32 pos = 0; /* Number of bytes traversed. */
-
- D2(printk("jffs_read_data(): file = \"%s\", read_offset = %d, "
- "size = %u\n",
- (f->name ? f->name : ""), read_offset, size));
-
- if (read_offset >= f->size) {
- D(printk(" f->size: %d\n", f->size));
- return 0;
- }
-
- /* First find the node to read data from. */
- node = f->range_head;
- while (pos <= read_offset) {
- node_offset = read_offset - pos;
- if (node_offset >= node->data_size) {
- pos += node->data_size;
- node = node->range_next;
- }
- else {
- break;
- }
- }
-
- /* "Cats are living proof that not everything in nature
- has to be useful."
- - Garrison Keilor ('97) */
-
- /* Fill the buffer. */
- while (node && (read_data < size)) {
- int r;
- if (!node->fm) {
- /* This node does not refer to real data. */
- r = min(size - read_data,
- node->data_size - node_offset);
- memset(&buf[read_data], 0, r);
- }
- else if ((r = jffs_get_node_data(f, node, &buf[read_data],
- node_offset,
- size - read_data)) < 0) {
- return r;
- }
- read_data += r;
- node_offset = 0;
- node = node->range_next;
- }
- D3(printk(" jffs_read_data(): Read %u bytes.\n", read_data));
- return read_data;
-}
-
-
-/* Used for traversing all nodes in the hash table. */
-int
-jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *))
-{
- int pos;
- int r;
- int result = 0;
-
- for (pos = 0; pos < c->hash_len; pos++) {
- struct jffs_file *f, *next;
-
- /* We must do _safe, because 'func' might remove the
- current file 'f' from the list. */
- list_for_each_entry_safe(f, next, &c->hash[pos], hash) {
- r = func(f);
- if (r < 0)
- return r;
- result += r;
- }
- }
-
- return result;
-}
-
-
-/* Free all nodes associated with a file. */
-static int
-jffs_free_node_list(struct jffs_file *f)
-{
- struct jffs_node *node;
- struct jffs_node *p;
-
- D3(printk("jffs_free_node_list(): f #%u, \"%s\"\n",
- f->ino, (f->name ? f->name : "")));
- node = f->version_head;
- while (node) {
- p = node;
- node = node->version_next;
- jffs_free_node(p);
- DJM(no_jffs_node--);
- }
- return 0;
-}
-
-
-/* Free a file and its name. */
-static int
-jffs_free_file(struct jffs_file *f)
-{
- D3(printk("jffs_free_file: f #%u, \"%s\"\n",
- f->ino, (f->name ? f->name : "")));
-
- if (f->name) {
- kfree(f->name);
- DJM(no_name--);
- }
- kfree(f);
- no_jffs_file--;
- return 0;
-}
-
-static long
-jffs_get_file_count(void)
-{
- return no_jffs_file;
-}
-
-/* See if a file is deleted. If so, mark that file's nodes as obsolete. */
-int
-jffs_possibly_delete_file(struct jffs_file *f)
-{
- struct jffs_node *n;
-
- D3(printk("jffs_possibly_delete_file(): ino: %u\n",
- f->ino));
-
- ASSERT(if (!f) {
- printk(KERN_ERR "jffs_possibly_delete_file(): f == NULL\n");
- return -1;
- });
-
- if (f->deleted) {
- /* First try to remove all older versions. Commence with
- the oldest node. */
- for (n = f->version_head; n; n = n->version_next) {
- if (!n->fm) {
- continue;
- }
- if (jffs_fmfree(f->c->fmc, n->fm, n) < 0) {
- break;
- }
- }
- /* Unlink the file from the filesystem. */
- if (!f->c->building_fs) {
- jffs_unlink_file_from_tree(f);
- }
- jffs_unlink_file_from_hash(f);
- jffs_free_node_list(f);
- jffs_free_file(f);
- }
- return 0;
-}
-
-
-/* Used in conjunction with jffs_foreach_file() to count the number
- of files in the file system. */
-int
-jffs_file_count(struct jffs_file *f)
-{
- return 1;
-}
-
-
-/* Build up a file's range list from scratch by going through the
- version list. */
-static int
-jffs_build_file(struct jffs_file *f)
-{
- struct jffs_node *n;
-
- D3(printk("jffs_build_file(): ino: %u, name: \"%s\"\n",
- f->ino, (f->name ? f->name : "")));
-
- for (n = f->version_head; n; n = n->version_next) {
- jffs_update_file(f, n);
- }
- return 0;
-}
-
-
-/* Remove an amount of data from a file. If this amount of data is
- zero, that could mean that a node should be split in two parts.
- We remove or change the appropriate nodes in the lists.
-
- Starting offset of area to be removed is node->data_offset,
- and the length of the area is in node->removed_size. */
-static int
-jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
-{
- struct jffs_node *n;
- __u32 offset = node->data_offset;
- __u32 remove_size = node->removed_size;
-
- D3(printk("jffs_delete_data(): offset = %u, remove_size = %u\n",
- offset, remove_size));
-
- if (remove_size == 0
- && f->range_tail
- && f->range_tail->data_offset + f->range_tail->data_size
- == offset) {
- /* A simple append; nothing to remove or no node to split. */
- return 0;
- }
-
- /* Find the node where we should begin the removal. */
- for (n = f->range_head; n; n = n->range_next) {
- if (n->data_offset + n->data_size > offset) {
- break;
- }
- }
- if (!n) {
- /* If there's no data in the file there's no data to
- remove either. */
- return 0;
- }
-
- if (n->data_offset > offset) {
- /* XXX: Not implemented yet. */
- printk(KERN_WARNING "JFFS: An unexpected situation "
- "occurred in jffs_delete_data.\n");
- }
- else if (n->data_offset < offset) {
- /* See if the node has to be split into two parts. */
- if (n->data_offset + n->data_size > offset + remove_size) {
- /* Do the split. */
- struct jffs_node *new_node;
- D3(printk("jffs_delete_data(): Split node with "
- "version number %u.\n", n->version));
-
- if (!(new_node = jffs_alloc_node())) {
- D(printk("jffs_delete_data(): -ENOMEM\n"));
- return -ENOMEM;
- }
- DJM(no_jffs_node++);
-
- new_node->ino = n->ino;
- new_node->version = n->version;
- new_node->data_offset = offset;
- new_node->data_size = n->data_size - (remove_size + (offset - n->data_offset));
- new_node->fm_offset = n->fm_offset + (remove_size + (offset - n->data_offset));
- new_node->name_size = n->name_size;
- new_node->fm = n->fm;
- new_node->version_prev = n;
- new_node->version_next = n->version_next;
- if (new_node->version_next) {
- new_node->version_next->version_prev
- = new_node;
- }
- else {
- f->version_tail = new_node;
- }
- n->version_next = new_node;
- new_node->range_prev = n;
- new_node->range_next = n->range_next;
- if (new_node->range_next) {
- new_node->range_next->range_prev = new_node;
- }
- else {
- f->range_tail = new_node;
- }
- /* A very interesting can of worms. */
- n->range_next = new_node;
- n->data_size = offset - n->data_offset;
- if (new_node->fm)
- jffs_add_node(new_node);
- else {
- D1(printk(KERN_WARNING "jffs_delete_data(): Splitting an empty node (file hold).\n!"));
- D1(printk(KERN_WARNING "FIXME: Did dwmw2 do the right thing here?\n"));
- }
- n = new_node->range_next;
- remove_size = 0;
- }
- else {
- /* No. No need to split the node. Just remove
- the end of the node. */
- int r = min(n->data_offset + n->data_size
- - offset, remove_size);
- n->data_size -= r;
- remove_size -= r;
- n = n->range_next;
- }
- }
-
- /* Remove as many nodes as necessary. */
- while (n && remove_size) {
- if (n->data_size <= remove_size) {
- struct jffs_node *p = n;
- remove_size -= n->data_size;
- n = n->range_next;
- D3(printk("jffs_delete_data(): Removing node: "
- "ino: %u, version: %u%s\n",
- p->ino, p->version,
- (p->fm ? "" : " (virtual)")));
- if (p->fm) {
- jffs_fmfree(f->c->fmc, p->fm, p);
- }
- jffs_unlink_node_from_range_list(f, p);
- jffs_unlink_node_from_version_list(f, p);
- jffs_free_node(p);
- DJM(no_jffs_node--);
- }
- else {
- n->data_size -= remove_size;
- n->fm_offset += remove_size;
- n->data_offset -= (node->removed_size - remove_size);
- n = n->range_next;
- break;
- }
- }
-
- /* Adjust the following nodes' information about offsets etc. */
- while (n && node->removed_size) {
- n->data_offset -= node->removed_size;
- n = n->range_next;
- }
-
- if (node->removed_size > (f->size - node->data_offset)) {
- /* It's possible that the removed_size is in fact
- * greater than the amount of data we actually thought
- * were present in the first place - some of the nodes
- * which this node originally obsoleted may already have
- * been deleted from the flash by subsequent garbage
- * collection.
- *
- * If this is the case, don't let f->size go negative.
- * Bad things would happen :)
- */
- f->size = node->data_offset;
- } else {
- f->size -= node->removed_size;
- }
- D3(printk("jffs_delete_data(): f->size = %d\n", f->size));
- return 0;
-} /* jffs_delete_data() */
-
-
-/* Insert some data into a file. Prior to the call to this function,
- jffs_delete_data should be called. */
-static int
-jffs_insert_data(struct jffs_file *f, struct jffs_node *node)
-{
- D3(printk("jffs_insert_data(): node->data_offset = %u, "
- "node->data_size = %u, f->size = %u\n",
- node->data_offset, node->data_size, f->size));
-
- /* Find the position where we should insert data. */
- retry:
- if (node->data_offset == f->size) {
- /* A simple append. This is the most common operation. */
- node->range_next = NULL;
- node->range_prev = f->range_tail;
- if (node->range_prev) {
- node->range_prev->range_next = node;
- }
- f->range_tail = node;
- f->size += node->data_size;
- if (!f->range_head) {
- f->range_head = node;
- }
- }
- else if (node->data_offset < f->size) {
- /* Trying to insert data into the middle of the file. This
- means no problem because jffs_delete_data() has already
- prepared the range list for us. */
- struct jffs_node *n;
-
- /* Find the correct place for the insertion and then insert
- the node. */
- for (n = f->range_head; n; n = n->range_next) {
- D2(printk("Cool stuff's happening!\n"));
-
- if (n->data_offset == node->data_offset) {
- node->range_prev = n->range_prev;
- if (node->range_prev) {
- node->range_prev->range_next = node;
- }
- else {
- f->range_head = node;
- }
- node->range_next = n;
- n->range_prev = node;
- break;
- }
- ASSERT(else if (n->data_offset + n->data_size >
- node->data_offset) {
- printk(KERN_ERR "jffs_insert_data(): "
- "Couldn't find a place to insert "
- "the data!\n");
- return -1;
- });
- }
-
- /* Adjust later nodes' offsets etc. */
- n = node->range_next;
- while (n) {
- n->data_offset += node->data_size;
- n = n->range_next;
- }
- f->size += node->data_size;
- }
- else if (node->data_offset > f->size) {
- /* Okay. This is tricky. This means that we want to insert
- data at a place that is beyond the limits of the file as
- it is constructed right now. This is actually a common
- event that for instance could occur during the mounting
- of the file system if a large file have been truncated,
- rewritten and then only partially garbage collected. */
-
- struct jffs_node *n;
-
- /* We need a place holder for the data that is missing in
- front of this insertion. This "virtual node" will not
- be associated with any space on the flash device. */
- struct jffs_node *virtual_node;
- if (!(virtual_node = jffs_alloc_node())) {
- return -ENOMEM;
- }
-
- D(printk("jffs_insert_data: Inserting a virtual node.\n"));
- D(printk(" node->data_offset = %u\n", node->data_offset));
- D(printk(" f->size = %u\n", f->size));
-
- virtual_node->ino = node->ino;
- virtual_node->version = node->version;
- virtual_node->removed_size = 0;
- virtual_node->fm_offset = 0;
- virtual_node->name_size = 0;
- virtual_node->fm = NULL; /* This is a virtual data holder. */
- virtual_node->version_prev = NULL;
- virtual_node->version_next = NULL;
- virtual_node->range_next = NULL;
-
- /* Are there any data at all in the file yet? */
- if (f->range_head) {
- virtual_node->data_offset
- = f->range_tail->data_offset
- + f->range_tail->data_size;
- virtual_node->data_size
- = node->data_offset - virtual_node->data_offset;
- virtual_node->range_prev = f->range_tail;
- f->range_tail->range_next = virtual_node;
- }
- else {
- virtual_node->data_offset = 0;
- virtual_node->data_size = node->data_offset;
- virtual_node->range_prev = NULL;
- f->range_head = virtual_node;
- }
-
- f->range_tail = virtual_node;
- f->size += virtual_node->data_size;
-
- /* Insert this virtual node in the version list as well. */
- for (n = f->version_head; n ; n = n->version_next) {
- if (n->version == virtual_node->version) {
- virtual_node->version_prev = n->version_prev;
- n->version_prev = virtual_node;
- if (virtual_node->version_prev) {
- virtual_node->version_prev
- ->version_next = virtual_node;
- }
- else {
- f->version_head = virtual_node;
- }
- virtual_node->version_next = n;
- break;
- }
- }
-
- D(jffs_print_node(virtual_node));
-
- /* Make a new try to insert the node. */
- goto retry;
- }
-
- D3(printk("jffs_insert_data(): f->size = %d\n", f->size));
- return 0;
-}
-
-
-/* A new node (with data) has been added to the file and now the range
- list has to be modified. */
-static int
-jffs_update_file(struct jffs_file *f, struct jffs_node *node)
-{
- int err;
-
- D3(printk("jffs_update_file(): ino: %u, version: %u\n",
- f->ino, node->version));
-
- if (node->data_size == 0) {
- if (node->removed_size == 0) {
- /* data_offset == X */
- /* data_size == 0 */
- /* remove_size == 0 */
- }
- else {
- /* data_offset == X */
- /* data_size == 0 */
- /* remove_size != 0 */
- if ((err = jffs_delete_data(f, node)) < 0) {
- return err;
- }
- }
- }
- else {
- /* data_offset == X */
- /* data_size != 0 */
- /* remove_size == Y */
- if ((err = jffs_delete_data(f, node)) < 0) {
- return err;
- }
- if ((err = jffs_insert_data(f, node)) < 0) {
- return err;
- }
- }
- return 0;
-}
-
-/* Print the contents of a file. */
-#if 0
-int
-jffs_print_file(struct jffs_file *f)
-{
- D(int i);
- D(printk("jffs_file: 0x%p\n", f));
- D(printk("{\n"));
- D(printk(" 0x%08x, /* ino */\n", f->ino));
- D(printk(" 0x%08x, /* pino */\n", f->pino));
- D(printk(" 0x%08x, /* mode */\n", f->mode));
- D(printk(" 0x%04x, /* uid */\n", f->uid));
- D(printk(" 0x%04x, /* gid */\n", f->gid));
- D(printk(" 0x%08x, /* atime */\n", f->atime));
- D(printk(" 0x%08x, /* mtime */\n", f->mtime));
- D(printk(" 0x%08x, /* ctime */\n", f->ctime));
- D(printk(" 0x%02x, /* nsize */\n", f->nsize));
- D(printk(" 0x%02x, /* nlink */\n", f->nlink));
- D(printk(" 0x%02x, /* deleted */\n", f->deleted));
- D(printk(" \"%s\", ", (f->name ? f->name : "")));
- D(for (i = strlen(f->name ? f->name : ""); i < 8; ++i) {
- printk(" ");
- });
- D(printk("/* name */\n"));
- D(printk(" 0x%08x, /* size */\n", f->size));
- D(printk(" 0x%08x, /* highest_version */\n",
- f->highest_version));
- D(printk(" 0x%p, /* c */\n", f->c));
- D(printk(" 0x%p, /* parent */\n", f->parent));
- D(printk(" 0x%p, /* children */\n", f->children));
- D(printk(" 0x%p, /* sibling_prev */\n", f->sibling_prev));
- D(printk(" 0x%p, /* sibling_next */\n", f->sibling_next));
- D(printk(" 0x%p, /* hash_prev */\n", f->hash.prev));
- D(printk(" 0x%p, /* hash_next */\n", f->hash.next));
- D(printk(" 0x%p, /* range_head */\n", f->range_head));
- D(printk(" 0x%p, /* range_tail */\n", f->range_tail));
- D(printk(" 0x%p, /* version_head */\n", f->version_head));
- D(printk(" 0x%p, /* version_tail */\n", f->version_tail));
- D(printk("}\n"));
- return 0;
-}
-#endif /* 0 */
-
-void
-jffs_print_hash_table(struct jffs_control *c)
-{
- int i;
-
- printk("JFFS: Dumping the file system's hash table...\n");
- for (i = 0; i < c->hash_len; i++) {
- struct jffs_file *f;
- list_for_each_entry(f, &c->hash[i], hash) {
- printk("*** c->hash[%u]: \"%s\" "
- "(ino: %u, pino: %u)\n",
- i, (f->name ? f->name : ""),
- f->ino, f->pino);
- }
- }
-}
-
-
-void
-jffs_print_tree(struct jffs_file *first_file, int indent)
-{
- struct jffs_file *f;
- char *space;
- int dir;
-
- if (!first_file) {
- return;
- }
-
- if (!(space = kmalloc(indent + 1, GFP_KERNEL))) {
- printk("jffs_print_tree(): Out of memory!\n");
- return;
- }
-
- memset(space, ' ', indent);
- space[indent] = '\0';
-
- for (f = first_file; f; f = f->sibling_next) {
- dir = S_ISDIR(f->mode);
- printk("%s%s%s (ino: %u, highest_version: %u, size: %u)\n",
- space, (f->name ? f->name : ""), (dir ? "/" : ""),
- f->ino, f->highest_version, f->size);
- if (dir) {
- jffs_print_tree(f->children, indent + 2);
- }
- }
-
- kfree(space);
-}
-
-
-#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
-void
-jffs_print_memory_allocation_statistics(void)
-{
- static long printout;
- printk("________ Memory printout #%ld ________\n", ++printout);
- printk("no_jffs_file = %ld\n", no_jffs_file);
- printk("no_jffs_node = %ld\n", no_jffs_node);
- printk("no_jffs_control = %ld\n", no_jffs_control);
- printk("no_jffs_raw_inode = %ld\n", no_jffs_raw_inode);
- printk("no_jffs_node_ref = %ld\n", no_jffs_node_ref);
- printk("no_jffs_fm = %ld\n", no_jffs_fm);
- printk("no_jffs_fmcontrol = %ld\n", no_jffs_fmcontrol);
- printk("no_hash = %ld\n", no_hash);
- printk("no_name = %ld\n", no_name);
- printk("\n");
-}
-#endif
-
-
-/* Rewrite `size' bytes, and begin at `node'. */
-static int
-jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, __u32 size)
-{
- struct jffs_control *c = f->c;
- struct jffs_fmcontrol *fmc = c->fmc;
- struct jffs_raw_inode raw_inode;
- struct jffs_node *new_node;
- struct jffs_fm *fm;
- __u32 pos;
- __u32 pos_dchksum;
- __u32 total_name_size;
- __u32 total_data_size;
- __u32 total_size;
- int err;
-
- D1(printk("***jffs_rewrite_data(): node: %u, name: \"%s\", size: %u\n",
- f->ino, (f->name ? f->name : "(null)"), size));
-
- /* Create and initialize the new node. */
- if (!(new_node = jffs_alloc_node())) {
- D(printk("jffs_rewrite_data(): "
- "Failed to allocate node.\n"));
- return -ENOMEM;
- }
- DJM(no_jffs_node++);
- new_node->data_offset = node->data_offset;
- new_node->removed_size = size;
- total_name_size = JFFS_PAD(f->nsize);
- total_data_size = JFFS_PAD(size);
- total_size = sizeof(struct jffs_raw_inode)
- + total_name_size + total_data_size;
- new_node->fm_offset = sizeof(struct jffs_raw_inode)
- + total_name_size;
-
-retry:
- jffs_fm_write_lock(fmc);
- err = 0;
-
- if ((err = jffs_fmalloc(fmc, total_size, new_node, &fm)) < 0) {
- DJM(no_jffs_node--);
- jffs_fm_write_unlock(fmc);
- D(printk("jffs_rewrite_data(): Failed to allocate fm.\n"));
- jffs_free_node(new_node);
- return err;
- }
- else if (!fm->nodes) {
- /* The jffs_fm struct that we got is not big enough. */
- /* This should never happen, because we deal with this case
- in jffs_garbage_collect_next().*/
- printk(KERN_WARNING "jffs_rewrite_data(): Allocated node is too small (%d bytes of %d)\n", fm->size, total_size);
- if ((err = jffs_write_dummy_node(c, fm)) < 0) {
- D(printk("jffs_rewrite_data(): "
- "jffs_write_dummy_node() Failed!\n"));
- } else {
- err = -ENOSPC;
- }
- DJM(no_jffs_fm--);
- jffs_fm_write_unlock(fmc);
- kfree(fm);
-
- return err;
- }
- new_node->fm = fm;
-
- /* Initialize the raw inode. */
- raw_inode.magic = JFFS_MAGIC_BITMASK;
- raw_inode.ino = f->ino;
- raw_inode.pino = f->pino;
- raw_inode.version = f->highest_version + 1;
- raw_inode.mode = f->mode;
- raw_inode.uid = f->uid;
- raw_inode.gid = f->gid;
- raw_inode.atime = f->atime;
- raw_inode.mtime = f->mtime;
- raw_inode.ctime = f->ctime;
- raw_inode.offset = node->data_offset;
- raw_inode.dsize = size;
- raw_inode.rsize = size;
- raw_inode.nsize = f->nsize;
- raw_inode.nlink = f->nlink;
- raw_inode.spare = 0;
- raw_inode.rename = 0;
- raw_inode.deleted = f->deleted;
- raw_inode.accurate = 0xff;
- raw_inode.dchksum = 0;
- raw_inode.nchksum = 0;
-
- pos = new_node->fm->offset;
- pos_dchksum = pos +JFFS_RAW_INODE_DCHKSUM_OFFSET;
-
- D3(printk("jffs_rewrite_data(): Writing this raw inode "
- "to pos 0x%ul.\n", pos));
- D3(jffs_print_raw_inode(&raw_inode));
-
- if ((err = flash_safe_write(fmc->mtd, pos,
- (u_char *) &raw_inode,
- sizeof(struct jffs_raw_inode)
- - sizeof(__u32)
- - sizeof(__u16) - sizeof(__u16))) < 0) {
- jffs_fmfree_partly(fmc, fm,
- total_name_size + total_data_size);
- jffs_fm_write_unlock(fmc);
- printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
- "rewrite. (raw inode)\n");
- printk(KERN_ERR "JFFS: jffs_rewrite_data: Now retrying "
- "rewrite. (raw inode)\n");
- goto retry;
- }
- pos += sizeof(struct jffs_raw_inode);
-
- /* Write the name to the flash memory. */
- if (f->nsize) {
- D3(printk("jffs_rewrite_data(): Writing name \"%s\" to "
- "pos 0x%ul.\n", f->name, (unsigned int) pos));
- if ((err = flash_safe_write(fmc->mtd, pos,
- (u_char *)f->name,
- f->nsize)) < 0) {
- jffs_fmfree_partly(fmc, fm, total_data_size);
- jffs_fm_write_unlock(fmc);
- printk(KERN_ERR "JFFS: jffs_rewrite_data: Write "
- "error during rewrite. (name)\n");
- printk(KERN_ERR "JFFS: jffs_rewrite_data: Now retrying "
- "rewrite. (name)\n");
- goto retry;
- }
- pos += total_name_size;
- raw_inode.nchksum = jffs_checksum(f->name, f->nsize);
- }
-
- /* Write the data. */
- if (size) {
- int r;
- unsigned char *page;
- __u32 offset = node->data_offset;
-
- if (!(page = (unsigned char *)__get_free_page(GFP_KERNEL))) {
- jffs_fmfree_partly(fmc, fm, 0);
- return -1;
- }
-
- while (size) {
- __u32 s = min(size, (__u32)PAGE_SIZE);
- if ((r = jffs_read_data(f, (char *)page,
- offset, s)) < s) {
- free_page((unsigned long)page);
- jffs_fmfree_partly(fmc, fm, 0);
- jffs_fm_write_unlock(fmc);
- printk(KERN_ERR "JFFS: jffs_rewrite_data: "
- "jffs_read_data() "
- "failed! (r = %d)\n", r);
- return -1;
- }
- if ((err = flash_safe_write(fmc->mtd,
- pos, page, r)) < 0) {
- free_page((unsigned long)page);
- jffs_fmfree_partly(fmc, fm, 0);
- jffs_fm_write_unlock(fmc);
- printk(KERN_ERR "JFFS: jffs_rewrite_data: "
- "Write error during rewrite. "
- "(data)\n");
- goto retry;
- }
- pos += r;
- size -= r;
- offset += r;
- raw_inode.dchksum += jffs_checksum(page, r);
- }
-
- free_page((unsigned long)page);
- }
-
- raw_inode.accurate = 0;
- raw_inode.chksum = jffs_checksum(&raw_inode,
- sizeof(struct jffs_raw_inode)
- - sizeof(__u16));
-
- /* Add the checksum. */
- if ((err
- = flash_safe_write(fmc->mtd, pos_dchksum,
- &((u_char *)
- &raw_inode)[JFFS_RAW_INODE_DCHKSUM_OFFSET],
- sizeof(__u32) + sizeof(__u16)
- + sizeof(__u16))) < 0) {
- jffs_fmfree_partly(fmc, fm, 0);
- jffs_fm_write_unlock(fmc);
- printk(KERN_ERR "JFFS: jffs_rewrite_data: Write error during "
- "rewrite. (checksum)\n");
- goto retry;
- }
-
- /* Now make the file system aware of the newly written node. */
- jffs_insert_node(c, f, &raw_inode, f->name, new_node);
- jffs_fm_write_unlock(fmc);
-
- D3(printk("jffs_rewrite_data(): Leaving...\n"));
- return 0;
-} /* jffs_rewrite_data() */
-
-
-/* jffs_garbage_collect_next implements one step in the garbage collect
- process and is often called multiple times at each occasion of a
- garbage collect. */
-
-static int
-jffs_garbage_collect_next(struct jffs_control *c)
-{
- struct jffs_fmcontrol *fmc = c->fmc;
- struct jffs_node *node;
- struct jffs_file *f;
- int err = 0;
- __u32 size;
- __u32 data_size;
- __u32 total_name_size;
- __u32 extra_available;
- __u32 space_needed;
- __u32 free_chunk_size1 = jffs_free_size1(fmc);
- D2(__u32 free_chunk_size2 = jffs_free_size2(fmc));
-
- /* Get the oldest node in the flash. */
- node = jffs_get_oldest_node(fmc);
- ASSERT(if (!node) {
- printk(KERN_ERR "JFFS: jffs_garbage_collect_next: "
- "No oldest node found!\n");
- err = -1;
- goto jffs_garbage_collect_next_end;
-
-
- });
-
- /* Find its corresponding file too. */
- f = jffs_find_file(c, node->ino);
-
- if (!f) {
- printk (KERN_ERR "JFFS: jffs_garbage_collect_next: "
- "No file to garbage collect! "
- "(ino = 0x%08x)\n", node->ino);
- /* FIXME: Free the offending node and recover. */
- err = -1;
- goto jffs_garbage_collect_next_end;
- }
-
- /* We always write out the name. Theoretically, we don't need
- to, but for now it's easier - because otherwise we'd have
- to keep track of how many times the current name exists on
- the flash and make sure it never reaches zero.
-
- The current approach means that would be possible to cause
- the GC to end up eating its tail by writing lots of nodes
- with no name for it to garbage-collect. Hence the change in
- inode.c to write names with _every_ node.
-
- It sucks, but it _should_ work.
- */
- total_name_size = JFFS_PAD(f->nsize);
-
- D1(printk("jffs_garbage_collect_next(): \"%s\", "
- "ino: %u, version: %u, location 0x%x, dsize %u\n",
- (f->name ? f->name : ""), node->ino, node->version,
- node->fm->offset, node->data_size));
-
- /* Compute how many data it's possible to rewrite at the moment. */
- data_size = f->size - node->data_offset;
-
- /* And from that, the total size of the chunk we want to write */
- size = sizeof(struct jffs_raw_inode) + total_name_size
- + data_size + JFFS_GET_PAD_BYTES(data_size);
-
- /* If that's more than max_chunk_size, reduce it accordingly */
- if (size > fmc->max_chunk_size) {
- size = fmc->max_chunk_size;
- data_size = size - sizeof(struct jffs_raw_inode)
- - total_name_size;
- }
-
- /* If we're asking to take up more space than free_chunk_size1
- but we _could_ fit in it, shrink accordingly.
- */
- if (size > free_chunk_size1) {
-
- if (free_chunk_size1 <
- (sizeof(struct jffs_raw_inode) + total_name_size + BLOCK_SIZE)){
- /* The space left is too small to be of any
- use really. */
- struct jffs_fm *dirty_fm
- = jffs_fmalloced(fmc,
- fmc->tail->offset + fmc->tail->size,
- free_chunk_size1, NULL);
- if (!dirty_fm) {
- printk(KERN_ERR "JFFS: "
- "jffs_garbage_collect_next: "
- "Failed to allocate `dirty' "
- "flash memory!\n");
- err = -1;
- goto jffs_garbage_collect_next_end;
- }
- D1(printk("Dirtying end of flash - too small\n"));
- jffs_write_dummy_node(c, dirty_fm);
- err = 0;
- goto jffs_garbage_collect_next_end;
- }
- D1(printk("Reducing size of new node from %d to %d to avoid "
- " exceeding free_chunk_size1\n",
- size, free_chunk_size1));
-
- size = free_chunk_size1;
- data_size = size - sizeof(struct jffs_raw_inode)
- - total_name_size;
- }
-
-
- /* Calculate the amount of space needed to hold the nodes
- which are remaining in the tail */
- space_needed = fmc->min_free_size - (node->fm->offset % fmc->sector_size);
-
- /* From that, calculate how much 'extra' space we can use to
- increase the size of the node we're writing from the size
- of the node we're obsoleting
- */
- if (space_needed > fmc->free_size) {
- /* If we've gone below min_free_size for some reason,
- don't fuck up. This is why we have
- min_free_size > sector_size. Whinge about it though,
- just so I can convince myself my maths is right.
- */
- D1(printk(KERN_WARNING "jffs_garbage_collect_next(): "
- "space_needed %d exceeded free_size %d\n",
- space_needed, fmc->free_size));
- extra_available = 0;
- } else {
- extra_available = fmc->free_size - space_needed;
- }
-
- /* Check that we don't use up any more 'extra' space than
- what's available */
- if (size > JFFS_PAD(node->data_size) + total_name_size +
- sizeof(struct jffs_raw_inode) + extra_available) {
- D1(printk("Reducing size of new node from %d to %ld to avoid "
- "catching our tail\n", size,
- (long) (JFFS_PAD(node->data_size) + JFFS_PAD(node->name_size) +
- sizeof(struct jffs_raw_inode) + extra_available)));
- D1(printk("space_needed = %d, extra_available = %d\n",
- space_needed, extra_available));
-
- size = JFFS_PAD(node->data_size) + total_name_size +
- sizeof(struct jffs_raw_inode) + extra_available;
- data_size = size - sizeof(struct jffs_raw_inode)
- - total_name_size;
- };
-
- D2(printk(" total_name_size: %u\n", total_name_size));
- D2(printk(" data_size: %u\n", data_size));
- D2(printk(" size: %u\n", size));
- D2(printk(" f->nsize: %u\n", f->nsize));
- D2(printk(" f->size: %u\n", f->size));
- D2(printk(" node->data_offset: %u\n", node->data_offset));
- D2(printk(" free_chunk_size1: %u\n", free_chunk_size1));
- D2(printk(" free_chunk_size2: %u\n", free_chunk_size2));
- D2(printk(" node->fm->offset: 0x%08x\n", node->fm->offset));
-
- if ((err = jffs_rewrite_data(f, node, data_size))) {
- printk(KERN_WARNING "jffs_rewrite_data() failed: %d\n", err);
- return err;
- }
-
-jffs_garbage_collect_next_end:
- D3(printk("jffs_garbage_collect_next: Leaving...\n"));
- return err;
-} /* jffs_garbage_collect_next */
-
-
-/* If an obsolete node is partly going to be erased due to garbage
- collection, the part that isn't going to be erased must be filled
- with zeroes so that the scan of the flash will work smoothly next
- time. (The data in the file could for instance be a JFFS image
- which could cause enormous confusion during a scan of the flash
- device if we didn't do this.)
- There are two phases in this procedure: First, the clearing of
- the name and data parts of the node. Second, possibly also clearing
- a part of the raw inode as well. If the box is power cycled during
- the first phase, only the checksum of this node-to-be-cleared-at-
- the-end will be wrong. If the box is power cycled during, or after,
- the clearing of the raw inode, the information like the length of
- the name and data parts are zeroed. The next time the box is
- powered up, the scanning algorithm manages this faulty data too
- because:
-
- - The checksum is invalid and thus the raw inode must be discarded
- in any case.
- - If the lengths of the data part or the name part are zeroed, the
- scanning just continues after the raw inode. But after the inode
- the scanning procedure just finds zeroes which is the same as
- dirt.
-
- So, in the end, this could never fail. :-) Even if it does fail,
- the scanning algorithm should manage that too. */
-
-static int
-jffs_clear_end_of_node(struct jffs_control *c, __u32 erase_size)
-{
- struct jffs_fm *fm;
- struct jffs_fmcontrol *fmc = c->fmc;
- __u32 zero_offset;
- __u32 zero_size;
- __u32 zero_offset_data;
- __u32 zero_size_data;
- __u32 cutting_raw_inode = 0;
-
- if (!(fm = jffs_cut_node(fmc, erase_size))) {
- D3(printk("jffs_clear_end_of_node(): fm == NULL\n"));
- return 0;
- }
-
- /* Where and how much shall we clear? */
- zero_offset = fmc->head->offset + erase_size;
- zero_size = fm->offset + fm->size - zero_offset;
-
- /* Do we have to clear the raw_inode explicitly? */
- if (fm->size - zero_size < sizeof(struct jffs_raw_inode)) {
- cutting_raw_inode = sizeof(struct jffs_raw_inode)
- - (fm->size - zero_size);
- }
-
- /* First, clear the name and data fields. */
- zero_offset_data = zero_offset + cutting_raw_inode;
- zero_size_data = zero_size - cutting_raw_inode;
- flash_safe_acquire(fmc->mtd);
- flash_memset(fmc->mtd, zero_offset_data, 0, zero_size_data);
- flash_safe_release(fmc->mtd);
-
- /* Should we clear a part of the raw inode? */
- if (cutting_raw_inode) {
- /* I guess it is ok to clear the raw inode in this order. */
- flash_safe_acquire(fmc->mtd);
- flash_memset(fmc->mtd, zero_offset, 0,
- cutting_raw_inode);
- flash_safe_release(fmc->mtd);
- }
-
- return 0;
-} /* jffs_clear_end_of_node() */
-
-/* Try to erase as much as possible of the dirt in the flash memory. */
-static long
-jffs_try_to_erase(struct jffs_control *c)
-{
- struct jffs_fmcontrol *fmc = c->fmc;
- long erase_size;
- int err;
- __u32 offset;
-
- D3(printk("jffs_try_to_erase()\n"));
-
- erase_size = jffs_erasable_size(fmc);
-
- D2(printk("jffs_try_to_erase(): erase_size = %ld\n", erase_size));
-
- if (erase_size == 0) {
- return 0;
- }
- else if (erase_size < 0) {
- printk(KERN_ERR "JFFS: jffs_try_to_erase: "
- "jffs_erasable_size returned %ld.\n", erase_size);
- return erase_size;
- }
-
- if ((err = jffs_clear_end_of_node(c, erase_size)) < 0) {
- printk(KERN_ERR "JFFS: jffs_try_to_erase: "
- "Clearing of node failed.\n");
- return err;
- }
-
- offset = fmc->head->offset;
-
- /* Now, let's try to do the erase. */
- if ((err = flash_erase_region(fmc->mtd,
- offset, erase_size)) < 0) {
- printk(KERN_ERR "JFFS: Erase of flash failed. "
- "offset = %u, erase_size = %ld\n",
- offset, erase_size);
- /* XXX: Here we should allocate this area as dirty
- with jffs_fmalloced or something similar. Now
- we just report the error. */
- return err;
- }
-
-#if 0
- /* Check if the erased sectors really got erased. */
- {
- __u32 pos;
- __u32 end;
-
- pos = (__u32)flash_get_direct_pointer(to_kdev_t(c->sb->s_dev), offset);
- end = pos + erase_size;
-
- D2(printk("JFFS: Checking erased sector(s)...\n"));
-
- flash_safe_acquire(fmc->mtd);
-
- for (; pos < end; pos += 4) {
- if (*(__u32 *)pos != JFFS_EMPTY_BITMASK) {
- printk("JFFS: Erase failed! pos = 0x%lx\n",
- (long)pos);
- jffs_hexdump(fmc->mtd, pos,
- jffs_min(256, end - pos));
- err = -1;
- break;
- }
- }
-
- flash_safe_release(fmc->mtd);
-
- if (!err) {
- D2(printk("JFFS: Erase succeeded.\n"));
- }
- else {
- /* XXX: Here we should allocate the memory
- with jffs_fmalloced() in order to prevent
- JFFS from using this area accidentally. */
- return err;
- }
- }
-#endif
-
- /* Update the flash memory data structures. */
- jffs_sync_erase(fmc, erase_size);
-
- return erase_size;
-}
-
-
-/* There are different criteria that should trigger a garbage collect:
-
- 1. There is too much dirt in the memory.
- 2. The free space is becoming small.
- 3. There are many versions of a node.
-
- The garbage collect should always be done in a manner that guarantees
- that future garbage collects cannot be locked. E.g. Rewritten chunks
- should not be too large (span more than one sector in the flash memory
- for exemple). Of course there is a limit on how intelligent this garbage
- collection can be. */
-
-
-static int
-jffs_garbage_collect_now(struct jffs_control *c)
-{
- struct jffs_fmcontrol *fmc = c->fmc;
- long erased = 0;
- int result = 0;
- D1(int i = 1);
- D2(printk("***jffs_garbage_collect_now(): fmc->dirty_size = %u, fmc->free_size = 0x%x\n, fcs1=0x%x, fcs2=0x%x",
- fmc->dirty_size, fmc->free_size, jffs_free_size1(fmc), jffs_free_size2(fmc)));
- D2(jffs_print_fmcontrol(fmc));
-
- // down(&fmc->gclock);
-
- /* If it is possible to garbage collect, do so. */
-
- while (erased == 0) {
- D1(printk("***jffs_garbage_collect_now(): round #%u, "
- "fmc->dirty_size = %u\n", i++, fmc->dirty_size));
- D2(jffs_print_fmcontrol(fmc));
-
- if ((erased = jffs_try_to_erase(c)) < 0) {
- printk(KERN_WARNING "JFFS: Error in "
- "garbage collector.\n");
- result = erased;
- goto gc_end;
- }
- if (erased)
- break;
-
- if (fmc->free_size == 0) {
- /* Argh */
- printk(KERN_ERR "jffs_garbage_collect_now(): free_size == 0. This is BAD.\n");
- result = -ENOSPC;
- break;
- }
-
- if (fmc->dirty_size < fmc->sector_size) {
- /* Actually, we _may_ have been able to free some,
- * if there are many overlapping nodes which aren't
- * actually marked dirty because they still have
- * some valid data in each.
- */
- result = -ENOSPC;
- break;
- }
-
- /* Let's dare to make a garbage collect. */
- if ((result = jffs_garbage_collect_next(c)) < 0) {
- printk(KERN_ERR "JFFS: Something "
- "has gone seriously wrong "
- "with a garbage collect.\n");
- goto gc_end;
- }
-
- D1(printk(" jffs_garbage_collect_now(): erased: %ld\n", erased));
- DJM(jffs_print_memory_allocation_statistics());
- }
-
-gc_end:
- // up(&fmc->gclock);
-
- D3(printk(" jffs_garbage_collect_now(): Leaving...\n"));
- D1(if (erased) {
- printk("jffs_g_c_now(): erased = %ld\n", erased);
- jffs_print_fmcontrol(fmc);
- });
-
- if (!erased && !result)
- return -ENOSPC;
-
- return result;
-} /* jffs_garbage_collect_now() */
-
-
-/* Determine if it is reasonable to start garbage collection.
- We start a gc pass if either:
- - The number of free bytes < MIN_FREE_BYTES && at least one
- block is dirty, OR
- - The number of dirty bytes > MAX_DIRTY_BYTES
-*/
-static inline int thread_should_wake (struct jffs_control *c)
-{
- D1(printk (KERN_NOTICE "thread_should_wake(): free=%d, dirty=%d, blocksize=%d.\n",
- c->fmc->free_size, c->fmc->dirty_size, c->fmc->sector_size));
-
- /* If there's not enough dirty space to free a block, there's no point. */
- if (c->fmc->dirty_size < c->fmc->sector_size) {
- D2(printk(KERN_NOTICE "thread_should_wake(): Not waking. Insufficient dirty space\n"));
- return 0;
- }
-#if 1
- /* If there is too much RAM used by the various structures, GC */
- if (jffs_get_node_inuse() > (c->fmc->used_size/c->fmc->max_chunk_size * 5 + jffs_get_file_count() * 2 + 50)) {
- /* FIXME: Provide proof that this test can be satisfied. We
- don't want a filesystem doing endless GC just because this
- condition cannot ever be false.
- */
- D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to number of nodes\n"));
- return 1;
- }
-#endif
- /* If there are fewer free bytes than the threshold, GC */
- if (c->fmc->free_size < c->gc_minfree_threshold) {
- D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to insufficent free space\n"));
- return 1;
- }
- /* If there are more dirty bytes than the threshold, GC */
- if (c->fmc->dirty_size > c->gc_maxdirty_threshold) {
- D2(printk(KERN_NOTICE "thread_should_wake(): Waking due to excessive dirty space\n"));
- return 1;
- }
- /* FIXME: What about the "There are many versions of a node" condition? */
-
- return 0;
-}
-
-
-void jffs_garbage_collect_trigger(struct jffs_control *c)
-{
- /* NOTE: We rely on the fact that we have the BKL here.
- * Otherwise, the gc_task could go away between the check
- * and the wake_up_process()
- */
- if (c->gc_task && thread_should_wake(c))
- send_sig(SIGHUP, c->gc_task, 1);
-}
-
-
-/* Kernel threads take (void *) as arguments. Thus we pass
- the jffs_control data as a (void *) and then cast it. */
-int
-jffs_garbage_collect_thread(void *ptr)
-{
- struct jffs_control *c = (struct jffs_control *) ptr;
- struct jffs_fmcontrol *fmc = c->fmc;
- long erased;
- int result = 0;
- D1(int i = 1);
-
- daemonize("jffs_gcd");
-
- c->gc_task = current;
-
- lock_kernel();
- init_completion(&c->gc_thread_comp); /* barrier */
- spin_lock_irq(&current->sighand->siglock);
- siginitsetinv (&current->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT));
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): Starting infinite loop.\n"));
-
- for (;;) {
-
- /* See if we need to start gc. If we don't, go to sleep.
-
- Current implementation is a BAD THING(tm). If we try
- to unmount the FS, the unmount operation will sleep waiting
- for this thread to exit. We need to arrange to send it a
- sig before the umount process sleeps.
- */
-
- if (!thread_should_wake(c))
- set_current_state (TASK_INTERRUPTIBLE);
-
- schedule(); /* Yes, we do this even if we want to go
- on immediately - we're a low priority
- background task. */
-
- /* Put_super will send a SIGKILL and then wait on the sem.
- */
- while (signal_pending(current)) {
- siginfo_t info;
- unsigned long signr = 0;
-
- if (try_to_freeze())
- continue;
-
- spin_lock_irq(&current->sighand->siglock);
- signr = dequeue_signal(current, &current->blocked, &info);
- spin_unlock_irq(&current->sighand->siglock);
-
- switch(signr) {
- case SIGSTOP:
- D1(printk("jffs_garbage_collect_thread(): SIGSTOP received.\n"));
- set_current_state(TASK_STOPPED);
- schedule();
- break;
-
- case SIGKILL:
- D1(printk("jffs_garbage_collect_thread(): SIGKILL received.\n"));
- c->gc_task = NULL;
- complete_and_exit(&c->gc_thread_comp, 0);
- }
- }
-
-
- D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): collecting.\n"));
-
- D3(printk (KERN_NOTICE "g_c_thread(): down biglock\n"));
- mutex_lock(&fmc->biglock);
-
- D1(printk("***jffs_garbage_collect_thread(): round #%u, "
- "fmc->dirty_size = %u\n", i++, fmc->dirty_size));
- D2(jffs_print_fmcontrol(fmc));
-
- if ((erased = jffs_try_to_erase(c)) < 0) {
- printk(KERN_WARNING "JFFS: Error in "
- "garbage collector: %ld.\n", erased);
- }
-
- if (erased)
- goto gc_end;
-
- if (fmc->free_size == 0) {
- /* Argh. Might as well commit suicide. */
- printk(KERN_ERR "jffs_garbage_collect_thread(): free_size == 0. This is BAD.\n");
- send_sig(SIGQUIT, c->gc_task, 1);
- // panic()
- goto gc_end;
- }
-
- /* Let's dare to make a garbage collect. */
- if ((result = jffs_garbage_collect_next(c)) < 0) {
- printk(KERN_ERR "JFFS: Something "
- "has gone seriously wrong "
- "with a garbage collect: %d\n", result);
- }
-
- gc_end:
- D3(printk (KERN_NOTICE "g_c_thread(): up biglock\n"));
- mutex_unlock(&fmc->biglock);
- } /* for (;;) */
-} /* jffs_garbage_collect_thread() */
diff --git a/fs/jffs/intrep.h b/fs/jffs/intrep.h
deleted file mode 100644
index 5c7abe0e269..00000000000
--- a/fs/jffs/intrep.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000 Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * 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.
- *
- * $Id: intrep.h,v 1.14 2001/09/23 23:28:37 dwmw2 Exp $
- *
- */
-
-#ifndef __LINUX_JFFS_INTREP_H__
-#define __LINUX_JFFS_INTREP_H__
-#include "jffs_fm.h"
-struct jffs_node *jffs_alloc_node(void);
-void jffs_free_node(struct jffs_node *n);
-int jffs_get_node_inuse(void);
-
-void jffs_cleanup_control(struct jffs_control *c);
-int jffs_build_fs(struct super_block *sb);
-
-int jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
- const struct jffs_raw_inode *raw_inode,
- const char *name, struct jffs_node *node);
-struct jffs_file *jffs_find_file(struct jffs_control *c, __u32 ino);
-struct jffs_file *jffs_find_child(struct jffs_file *dir, const char *name, int len);
-
-void jffs_free_node(struct jffs_node *node);
-
-int jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *));
-int jffs_possibly_delete_file(struct jffs_file *f);
-int jffs_insert_file_into_tree(struct jffs_file *f);
-int jffs_unlink_file_from_tree(struct jffs_file *f);
-int jffs_file_count(struct jffs_file *f);
-
-int jffs_write_node(struct jffs_control *c, struct jffs_node *node,
- struct jffs_raw_inode *raw_inode,
- const char *name, const unsigned char *buf,
- int recoverable, struct jffs_file *f);
-int jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset, __u32 size);
-
-/* Garbage collection stuff. */
-int jffs_garbage_collect_thread(void *c);
-void jffs_garbage_collect_trigger(struct jffs_control *c);
-
-/* For debugging purposes. */
-#if 0
-int jffs_print_file(struct jffs_file *f);
-#endif /* 0 */
-void jffs_print_hash_table(struct jffs_control *c);
-void jffs_print_tree(struct jffs_file *first_file, int indent);
-
-#endif /* __LINUX_JFFS_INTREP_H__ */
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c
deleted file mode 100644
index 5a95fbdd6fd..00000000000
--- a/fs/jffs/jffs_fm.c
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000 Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * 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.
- *
- * $Id: jffs_fm.c,v 1.27 2001/09/20 12:29:47 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/blkdev.h>
-#include <linux/jffs.h>
-#include "jffs_fm.h"
-#include "intrep.h"
-
-#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
-static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
-#endif
-
-static struct jffs_fm *jffs_alloc_fm(void);
-static void jffs_free_fm(struct jffs_fm *n);
-
-extern struct kmem_cache *fm_cache;
-extern struct kmem_cache *node_cache;
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-void
-jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
-{
- D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
- D(printk("{\n"));
- D(printk(" %u, /* flash_size */\n", fmc->flash_size));
- D(printk(" %u, /* used_size */\n", fmc->used_size));
- D(printk(" %u, /* dirty_size */\n", fmc->dirty_size));
- D(printk(" %u, /* free_size */\n", fmc->free_size));
- D(printk(" %u, /* sector_size */\n", fmc->sector_size));
- D(printk(" %u, /* min_free_size */\n", fmc->min_free_size));
- D(printk(" %u, /* max_chunk_size */\n", fmc->max_chunk_size));
- D(printk(" 0x%p, /* mtd */\n", fmc->mtd));
- D(printk(" 0x%p, /* head */ "
- "(head->offset = 0x%08x)\n",
- fmc->head, (fmc->head ? fmc->head->offset : 0)));
- D(printk(" 0x%p, /* tail */ "
- "(tail->offset + tail->size = 0x%08x)\n",
- fmc->tail,
- (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
- D(printk(" 0x%p, /* head_extra */\n", fmc->head_extra));
- D(printk(" 0x%p, /* tail_extra */\n", fmc->tail_extra));
- D(printk("}\n"));
-}
-#endif /* CONFIG_JFFS_FS_VERBOSE > 0 */
-
-#if CONFIG_JFFS_FS_VERBOSE > 2
-static void
-jffs_print_fm(struct jffs_fm *fm)
-{
- D(printk("struct jffs_fm: 0x%p\n", fm));
- D(printk("{\n"));
- D(printk(" 0x%08x, /* offset */\n", fm->offset));
- D(printk(" %u, /* size */\n", fm->size));
- D(printk(" 0x%p, /* prev */\n", fm->prev));
- D(printk(" 0x%p, /* next */\n", fm->next));
- D(printk(" 0x%p, /* nodes */\n", fm->nodes));
- D(printk("}\n"));
-}
-#endif /* CONFIG_JFFS_FS_VERBOSE > 2 */
-
-#if 0
-void
-jffs_print_node_ref(struct jffs_node_ref *ref)
-{
- D(printk("struct jffs_node_ref: 0x%p\n", ref));
- D(printk("{\n"));
- D(printk(" 0x%p, /* node */\n", ref->node));
- D(printk(" 0x%p, /* next */\n", ref->next));
- D(printk("}\n"));
-}
-#endif /* 0 */
-
-/* This function creates a new shiny flash memory control structure. */
-struct jffs_fmcontrol *
-jffs_build_begin(struct jffs_control *c, int unit)
-{
- struct jffs_fmcontrol *fmc;
- struct mtd_info *mtd;
-
- D3(printk("jffs_build_begin()\n"));
- fmc = kmalloc(sizeof(*fmc), GFP_KERNEL);
- if (!fmc) {
- D(printk("jffs_build_begin(): Allocation of "
- "struct jffs_fmcontrol failed!\n"));
- return (struct jffs_fmcontrol *)0;
- }
- DJM(no_jffs_fmcontrol++);
-
- mtd = get_mtd_device(NULL, unit);
-
- if (IS_ERR(mtd)) {
- kfree(fmc);
- DJM(no_jffs_fmcontrol--);
- return NULL;
- }
-
- /* Retrieve the size of the flash memory. */
- fmc->flash_size = mtd->size;
- D3(printk(" fmc->flash_size = %d bytes\n", fmc->flash_size));
-
- fmc->used_size = 0;
- fmc->dirty_size = 0;
- fmc->free_size = mtd->size;
- fmc->sector_size = mtd->erasesize;
- fmc->max_chunk_size = fmc->sector_size >> 1;
- /* min_free_size:
- 1 sector, obviously.
- + 1 x max_chunk_size, for when a nodes overlaps the end of a sector
- + 1 x max_chunk_size again, which ought to be enough to handle
- the case where a rename causes a name to grow, and GC has
- to write out larger nodes than the ones it's obsoleting.
- We should fix it so it doesn't have to write the name
- _every_ time. Later.
- + another 2 sectors because people keep getting GC stuck and
- we don't know why. This scares me - I want formal proof
- of correctness of whatever number we put here. dwmw2.
- */
- fmc->min_free_size = fmc->sector_size << 2;
- fmc->mtd = mtd;
- fmc->c = c;
- fmc->head = NULL;
- fmc->tail = NULL;
- fmc->head_extra = NULL;
- fmc->tail_extra = NULL;
- mutex_init(&fmc->biglock);
- return fmc;
-}
-
-
-/* When the flash memory scan has completed, this function should be called
- before use of the control structure. */
-void
-jffs_build_end(struct jffs_fmcontrol *fmc)
-{
- D3(printk("jffs_build_end()\n"));
-
- if (!fmc->head) {
- fmc->head = fmc->head_extra;
- fmc->tail = fmc->tail_extra;
- }
- else if (fmc->head_extra) {
- fmc->tail_extra->next = fmc->head;
- fmc->head->prev = fmc->tail_extra;
- fmc->head = fmc->head_extra;
- }
- fmc->head_extra = NULL; /* These two instructions should be omitted. */
- fmc->tail_extra = NULL;
- D3(jffs_print_fmcontrol(fmc));
-}
-
-
-/* Call this function when the file system is unmounted. This function
- frees all memory used by this module. */
-void
-jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc)
-{
- if (fmc) {
- struct jffs_fm *next = fmc->head;
- while (next) {
- struct jffs_fm *cur = next;
- next = next->next;
- jffs_free_fm(cur);
- }
- put_mtd_device(fmc->mtd);
- kfree(fmc);
- DJM(no_jffs_fmcontrol--);
- }
-}
-
-
-/* This function returns the size of the first chunk of free space on the
- flash memory. This function will return something nonzero if the flash
- memory contains any free space. */
-__u32
-jffs_free_size1(struct jffs_fmcontrol *fmc)
-{
- __u32 head;
- __u32 tail;
- __u32 end = fmc->flash_size;
-
- if (!fmc->head) {
- /* There is nothing on the flash. */
- return fmc->flash_size;
- }
-
- /* Compute the beginning and ending of the contents of the flash. */
- head = fmc->head->offset;
- tail = fmc->tail->offset + fmc->tail->size;
- if (tail == end) {
- tail = 0;
- }
- ASSERT(else if (tail > end) {
- printk(KERN_WARNING "jffs_free_size1(): tail > end\n");
- tail = 0;
- });
-
- if (head <= tail) {
- return end - tail;
- }
- else {
- return head - tail;
- }
-}
-
-/* This function will return something nonzero in case there are two free
- areas on the flash. Like this:
-
- +----------------+------------------+----------------+
- | FREE 1 | USED / DIRTY | FREE 2 |
- +----------------+------------------+----------------+
- fmc->head -----^
- fmc->tail ------------------------^
-
- The value returned, will be the size of the first empty area on the
- flash, in this case marked "FREE 1". */
-__u32
-jffs_free_size2(struct jffs_fmcontrol *fmc)
-{
- if (fmc->head) {
- __u32 head = fmc->head->offset;
- __u32 tail = fmc->tail->offset + fmc->tail->size;
- if (tail == fmc->flash_size) {
- tail = 0;
- }
-
- if (tail >= head) {
- return head;
- }
- }
- return 0;
-}
-
-
-/* Allocate a chunk of flash memory. If there is enough space on the
- device, a reference to the associated node is stored in the jffs_fm
- struct. */
-int
-jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node,
- struct jffs_fm **result)
-{
- struct jffs_fm *fm;
- __u32 free_chunk_size1;
- __u32 free_chunk_size2;
-
- D2(printk("jffs_fmalloc(): fmc = 0x%p, size = %d, "
- "node = 0x%p\n", fmc, size, node));
-
- *result = NULL;
-
- if (!(fm = jffs_alloc_fm())) {
- D(printk("jffs_fmalloc(): kmalloc() failed! (fm)\n"));
- return -ENOMEM;
- }
-
- free_chunk_size1 = jffs_free_size1(fmc);
- free_chunk_size2 = jffs_free_size2(fmc);
- if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) {
- printk(KERN_WARNING "Free size accounting screwed\n");
- printk(KERN_WARNING "free_chunk_size1 == 0x%x, free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", free_chunk_size1, free_chunk_size2, fmc->free_size);
- }
-
- D3(printk("jffs_fmalloc(): free_chunk_size1 = %u, "
- "free_chunk_size2 = %u\n",
- free_chunk_size1, free_chunk_size2));
-
- if (size <= free_chunk_size1) {
- if (!(fm->nodes = (struct jffs_node_ref *)
- kmalloc(sizeof(struct jffs_node_ref),
- GFP_KERNEL))) {
- D(printk("jffs_fmalloc(): kmalloc() failed! "
- "(node_ref)\n"));
- jffs_free_fm(fm);
- return -ENOMEM;
- }
- DJM(no_jffs_node_ref++);
- fm->nodes->node = node;
- fm->nodes->next = NULL;
- if (fmc->tail) {
- fm->offset = fmc->tail->offset + fmc->tail->size;
- if (fm->offset == fmc->flash_size) {
- fm->offset = 0;
- }
- ASSERT(else if (fm->offset > fmc->flash_size) {
- printk(KERN_WARNING "jffs_fmalloc(): "
- "offset > flash_end\n");
- fm->offset = 0;
- });
- }
- else {
- /* There don't have to be files in the file
- system yet. */
- fm->offset = 0;
- }
- fm->size = size;
- fmc->free_size -= size;
- fmc->used_size += size;
- }
- else if (size > free_chunk_size2) {
- printk(KERN_WARNING "JFFS: Tried to allocate a too "
- "large flash memory chunk. (size = %u)\n", size);
- jffs_free_fm(fm);
- return -ENOSPC;
- }
- else {
- fm->offset = fmc->tail->offset + fmc->tail->size;
- fm->size = free_chunk_size1;
- fm->nodes = NULL;
- fmc->free_size -= fm->size;
- fmc->dirty_size += fm->size; /* Changed by simonk. This seemingly fixes a
- bug that caused infinite garbage collection.
- It previously set fmc->dirty_size to size (which is the
- size of the requested chunk).
- */
- }
-
- fm->next = NULL;
- if (!fmc->head) {
- fm->prev = NULL;
- fmc->head = fm;
- fmc->tail = fm;
- }
- else {
- fm->prev = fmc->tail;
- fmc->tail->next = fm;
- fmc->tail = fm;
- }
-
- D3(jffs_print_fmcontrol(fmc));
- D3(jffs_print_fm(fm));
- *result = fm;
- return 0;
-}
-
-
-/* The on-flash space is not needed anymore by the passed node. Remove
- the reference to the node from the node list. If the data chunk in
- the flash memory isn't used by any more nodes anymore (fm->nodes == 0),
- then mark that chunk as dirty. */
-int
-jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, struct jffs_node *node)
-{
- struct jffs_node_ref *ref;
- struct jffs_node_ref *prev;
- ASSERT(int del = 0);
-
- D2(printk("jffs_fmfree(): node->ino = %u, node->version = %u\n",
- node->ino, node->version));
-
- ASSERT(if (!fmc || !fm || !fm->nodes) {
- printk(KERN_ERR "jffs_fmfree(): fmc: 0x%p, fm: 0x%p, "
- "fm->nodes: 0x%p\n",
- fmc, fm, (fm ? fm->nodes : NULL));
- return -1;
- });
-
- /* Find the reference to the node that is going to be removed
- and remove it. */
- for (ref = fm->nodes, prev = NULL; ref; ref = ref->next) {
- if (ref->node == node) {
- if (prev) {
- prev->next = ref->next;
- }
- else {
- fm->nodes = ref->next;
- }
- kfree(ref);
- DJM(no_jffs_node_ref--);
- ASSERT(del = 1);
- break;
- }
- prev = ref;
- }
-
- /* If the data chunk in the flash memory isn't used anymore
- just mark it as obsolete. */
- if (!fm->nodes) {
- /* No node uses this chunk so let's remove it. */
- fmc->used_size -= fm->size;
- fmc->dirty_size += fm->size;
-#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
- if (jffs_mark_obsolete(fmc, fm->offset) < 0) {
- D1(printk("jffs_fmfree(): Failed to mark an on-flash "
- "node obsolete!\n"));
- return -1;
- }
-#endif
- }
-
- ASSERT(if (!del) {
- printk(KERN_WARNING "***jffs_fmfree(): "
- "Didn't delete any node reference!\n");
- });
-
- return 0;
-}
-
-
-/* This allocation function is used during the initialization of
- the file system. */
-struct jffs_fm *
-jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset, __u32 size,
- struct jffs_node *node)
-{
- struct jffs_fm *fm;
-
- D3(printk("jffs_fmalloced()\n"));
-
- if (!(fm = jffs_alloc_fm())) {
- D(printk("jffs_fmalloced(0x%p, %u, %u, 0x%p): failed!\n",
- fmc, offset, size, node));
- return NULL;
- }
- fm->offset = offset;
- fm->size = size;
- fm->prev = NULL;
- fm->next = NULL;
- fm->nodes = NULL;
- if (node) {
- /* `node' exists and it should be associated with the
- jffs_fm structure `fm'. */
- if (!(fm->nodes = (struct jffs_node_ref *)
- kmalloc(sizeof(struct jffs_node_ref),
- GFP_KERNEL))) {
- D(printk("jffs_fmalloced(): !fm->nodes\n"));
- jffs_free_fm(fm);
- return NULL;
- }
- DJM(no_jffs_node_ref++);
- fm->nodes->node = node;
- fm->nodes->next = NULL;
- fmc->used_size += size;
- fmc->free_size -= size;
- }
- else {
- /* If there is no node, then this is just a chunk of dirt. */
- fmc->dirty_size += size;
- fmc->free_size -= size;
- }
-
- if (fmc->head_extra) {
- fm->prev = fmc->tail_extra;
- fmc->tail_extra->next = fm;
- fmc->tail_extra = fm;
- }
- else if (!fmc->head) {
- fmc->head = fm;
- fmc->tail = fm;
- }
- else if (fmc->tail->offset + fmc->tail->size < offset) {
- fmc->head_extra = fm;
- fmc->tail_extra = fm;
- }
- else {
- fm->prev = fmc->tail;
- fmc->tail->next = fm;
- fmc->tail = fm;
- }
- D3(jffs_print_fmcontrol(fmc));
- D3(jffs_print_fm(fm));
- return fm;
-}
-
-
-/* Add a new node to an already existing jffs_fm struct. */
-int
-jffs_add_node(struct jffs_node *node)
-{
- struct jffs_node_ref *ref;
-
- D3(printk("jffs_add_node(): ino = %u\n", node->ino));
-
- ref = kmalloc(sizeof(*ref), GFP_KERNEL);
- if (!ref)
- return -ENOMEM;
-
- DJM(no_jffs_node_ref++);
- ref->node = node;
- ref->next = node->fm->nodes;
- node->fm->nodes = ref;
- return 0;
-}
-
-
-/* Free a part of some allocated space. */
-void
-jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm, __u32 size)
-{
- D1(printk("***jffs_fmfree_partly(): fm = 0x%p, fm->nodes = 0x%p, "
- "fm->nodes->node->ino = %u, size = %u\n",
- fm, (fm ? fm->nodes : 0),
- (!fm ? 0 : (!fm->nodes ? 0 : fm->nodes->node->ino)), size));
-
- if (fm->nodes) {
- kfree(fm->nodes);
- DJM(no_jffs_node_ref--);
- fm->nodes = NULL;
- }
- fmc->used_size -= fm->size;
- if (fm == fmc->tail) {
- fm->size -= size;
- fmc->free_size += size;
- }
- fmc->dirty_size += fm->size;
-}
-
-
-/* Find the jffs_fm struct that contains the end of the data chunk that
- begins at the logical beginning of the flash memory and spans `size'
- bytes. If we want to erase a sector of the flash memory, we use this
- function to find where the sector limit cuts a chunk of data. */
-struct jffs_fm *
-jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size)
-{
- struct jffs_fm *fm;
- __u32 pos = 0;
-
- if (size == 0) {
- return NULL;
- }
-
- ASSERT(if (!fmc) {
- printk(KERN_ERR "jffs_cut_node(): fmc == NULL\n");
- return NULL;
- });
-
- fm = fmc->head;
-
- while (fm) {
- pos += fm->size;
- if (pos < size) {
- fm = fm->next;
- }
- else if (pos > size) {
- break;
- }
- else {
- fm = NULL;
- break;
- }
- }
-
- return fm;
-}
-
-
-/* Move the head of the fmc structures and delete the obsolete parts. */
-void
-jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size)
-{
- struct jffs_fm *fm;
- struct jffs_fm *del;
-
- ASSERT(if (!fmc) {
- printk(KERN_ERR "jffs_sync_erase(): fmc == NULL\n");
- return;
- });
-
- fmc->dirty_size -= erased_size;
- fmc->free_size += erased_size;
-
- for (fm = fmc->head; fm && (erased_size > 0);) {
- if (erased_size >= fm->size) {
- erased_size -= fm->size;
- del = fm;
- fm = fm->next;
- fm->prev = NULL;
- fmc->head = fm;
- jffs_free_fm(del);
- }
- else {
- fm->size -= erased_size;
- fm->offset += erased_size;
- break;
- }
- }
-}
-
-
-/* Return the oldest used node in the flash memory. */
-struct jffs_node *
-jffs_get_oldest_node(struct jffs_fmcontrol *fmc)
-{
- struct jffs_fm *fm;
- struct jffs_node_ref *nref;
- struct jffs_node *node = NULL;
-
- ASSERT(if (!fmc) {
- printk(KERN_ERR "jffs_get_oldest_node(): fmc == NULL\n");
- return NULL;
- });
-
- for (fm = fmc->head; fm && !fm->nodes; fm = fm->next);
-
- if (!fm) {
- return NULL;
- }
-
- /* The oldest node is the last one in the reference list. This list
- shouldn't be too long; just one or perhaps two elements. */
- for (nref = fm->nodes; nref; nref = nref->next) {
- node = nref->node;
- }
-
- D2(printk("jffs_get_oldest_node(): ino = %u, version = %u\n",
- (node ? node->ino : 0), (node ? node->version : 0)));
-
- return node;
-}
-
-
-#if defined(JFFS_MARK_OBSOLETE) && JFFS_MARK_OBSOLETE
-
-/* Mark an on-flash node as obsolete.
-
- Note that this is just an optimization that isn't necessary for the
- filesystem to work. */
-
-static int
-jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset)
-{
- /* The `accurate_pos' holds the position of the accurate byte
- in the jffs_raw_inode structure that we are going to mark
- as obsolete. */
- __u32 accurate_pos = fm_offset + JFFS_RAW_INODE_ACCURATE_OFFSET;
- unsigned char zero = 0x00;
- size_t len;
-
- D3(printk("jffs_mark_obsolete(): accurate_pos = %u\n", accurate_pos));
- ASSERT(if (!fmc) {
- printk(KERN_ERR "jffs_mark_obsolete(): fmc == NULL\n");
- return -1;
- });
-
- /* Write 0x00 to the raw inode's accurate member. Don't care
- about the return value. */
- MTD_WRITE(fmc->mtd, accurate_pos, 1, &len, &zero);
- return 0;
-}
-
-#endif /* JFFS_MARK_OBSOLETE */
-
-/* check if it's possible to erase the wanted range, and if not, return
- * the range that IS erasable, or a negative error code.
- */
-static long
-jffs_flash_erasable_size(struct mtd_info *mtd, __u32 offset, __u32 size)
-{
- u_long ssize;
-
- /* assume that sector size for a partition is constant even
- * if it spans more than one chip (you usually put the same
- * type of chips in a system)
- */
-
- ssize = mtd->erasesize;
-
- if (offset % ssize) {
- printk(KERN_WARNING "jffs_flash_erasable_size() given non-aligned offset %x (erasesize %lx)\n", offset, ssize);
- /* The offset is not sector size aligned. */
- return -1;
- }
- else if (offset > mtd->size) {
- printk(KERN_WARNING "jffs_flash_erasable_size given offset off the end of device (%x > %x)\n", offset, mtd->size);
- return -2;
- }
- else if (offset + size > mtd->size) {
- printk(KERN_WARNING "jffs_flash_erasable_size() given length which runs off the end of device (ofs %x + len %x = %x, > %x)\n", offset,size, offset+size, mtd->size);
- return -3;
- }
-
- return (size / ssize) * ssize;
-}
-
-
-/* How much dirty flash memory is possible to erase at the moment? */
-long
-jffs_erasable_size(struct jffs_fmcontrol *fmc)
-{
- struct jffs_fm *fm;
- __u32 size = 0;
- long ret;
-
- ASSERT(if (!fmc) {
- printk(KERN_ERR "jffs_erasable_size(): fmc = NULL\n");
- return -1;
- });
-
- if (!fmc->head) {
- /* The flash memory is totally empty. No nodes. No dirt.
- Just return. */
- return 0;
- }
-
- /* Calculate how much space that is dirty. */
- for (fm = fmc->head; fm && !fm->nodes; fm = fm->next) {
- if (size && fm->offset == 0) {
- /* We have reached the beginning of the flash. */
- break;
- }
- size += fm->size;
- }
-
- /* Someone's signature contained this:
- There's a fine line between fishing and just standing on
- the shore like an idiot... */
- ret = jffs_flash_erasable_size(fmc->mtd, fmc->head->offset, size);
-
- ASSERT(if (ret < 0) {
- printk("jffs_erasable_size: flash_erasable_size() "
- "returned something less than zero (%ld).\n", ret);
- printk("jffs_erasable_size: offset = 0x%08x\n",
- fmc->head->offset);
- });
-
- /* If there is dirt on the flash (which is the reason to why
- this function was called in the first place) but no space is
- possible to erase right now, the initial part of the list of
- jffs_fm structs, that hold place for dirty space, could perhaps
- be shortened. The list's initial "dirty" elements are merged
- into just one large dirty jffs_fm struct. This operation must
- only be performed if nothing is possible to erase. Otherwise,
- jffs_clear_end_of_node() won't work as expected. */
- if (ret == 0) {
- struct jffs_fm *head = fmc->head;
- struct jffs_fm *del;
- /* While there are two dirty nodes beside each other.*/
- while (head->nodes == 0
- && head->next
- && head->next->nodes == 0) {
- del = head->next;
- head->size += del->size;
- head->next = del->next;
- if (del->next) {
- del->next->prev = head;
- }
- jffs_free_fm(del);
- }
- }
-
- return (ret >= 0 ? ret : 0);
-}
-
-static struct jffs_fm *jffs_alloc_fm(void)
-{
- struct jffs_fm *fm;
-
- fm = kmem_cache_alloc(fm_cache,GFP_KERNEL);
- DJM(if (fm) no_jffs_fm++;);
-
- return fm;
-}
-
-static void jffs_free_fm(struct jffs_fm *n)
-{
- kmem_cache_free(fm_cache,n);
- DJM(no_jffs_fm--);
-}
-
-
-
-struct jffs_node *jffs_alloc_node(void)
-{
- struct jffs_node *n;
-
- n = (struct jffs_node *)kmem_cache_alloc(node_cache,GFP_KERNEL);
- if(n != NULL)
- no_jffs_node++;
- return n;
-}
-
-void jffs_free_node(struct jffs_node *n)
-{
- kmem_cache_free(node_cache,n);
- no_jffs_node--;
-}
-
-
-int jffs_get_node_inuse(void)
-{
- return no_jffs_node;
-}
diff --git a/fs/jffs/jffs_fm.h b/fs/jffs/jffs_fm.h
deleted file mode 100644
index 9ee6ad29eff..00000000000
--- a/fs/jffs/jffs_fm.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000 Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * 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.
- *
- * $Id: jffs_fm.h,v 1.13 2001/01/11 12:03:25 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-
-#ifndef __LINUX_JFFS_FM_H__
-#define __LINUX_JFFS_FM_H__
-
-#include <linux/types.h>
-#include <linux/jffs.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mutex.h>
-
-/* The alignment between two nodes in the flash memory. */
-#define JFFS_ALIGN_SIZE 4
-
-/* Mark the on-flash space as obsolete when appropriate. */
-#define JFFS_MARK_OBSOLETE 0
-
-#ifndef CONFIG_JFFS_FS_VERBOSE
-#define CONFIG_JFFS_FS_VERBOSE 1
-#endif
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-#define D(x) x
-#define D1(x) D(x)
-#else
-#define D(x)
-#define D1(x)
-#endif
-
-#if CONFIG_JFFS_FS_VERBOSE > 1
-#define D2(x) D(x)
-#else
-#define D2(x)
-#endif
-
-#if CONFIG_JFFS_FS_VERBOSE > 2
-#define D3(x) D(x)
-#else
-#define D3(x)
-#endif
-
-#define ASSERT(x) x
-
-/* How many padding bytes should be inserted between two chunks of data
- on the flash? */
-#define JFFS_GET_PAD_BYTES(size) ( (JFFS_ALIGN_SIZE-1) & -(__u32)(size) )
-#define JFFS_PAD(size) ( (size + (JFFS_ALIGN_SIZE-1)) & ~(JFFS_ALIGN_SIZE-1) )
-
-
-
-struct jffs_node_ref
-{
- struct jffs_node *node;
- struct jffs_node_ref *next;
-};
-
-
-/* The struct jffs_fm represents a chunk of data in the flash memory. */
-struct jffs_fm
-{
- __u32 offset;
- __u32 size;
- struct jffs_fm *prev;
- struct jffs_fm *next;
- struct jffs_node_ref *nodes; /* USED if != 0. */
-};
-
-struct jffs_fmcontrol
-{
- __u32 flash_size;
- __u32 used_size;
- __u32 dirty_size;
- __u32 free_size;
- __u32 sector_size;
- __u32 min_free_size; /* The minimum free space needed to be able
- to perform garbage collections. */
- __u32 max_chunk_size; /* The maximum size of a chunk of data. */
- struct mtd_info *mtd;
- struct jffs_control *c;
- struct jffs_fm *head;
- struct jffs_fm *tail;
- struct jffs_fm *head_extra;
- struct jffs_fm *tail_extra;
- struct mutex biglock;
-};
-
-/* Notice the two members head_extra and tail_extra in the jffs_control
- structure above. Those are only used during the scanning of the flash
- memory; while the file system is being built. If the data in the flash
- memory is organized like
-
- +----------------+------------------+----------------+
- | USED / DIRTY | FREE | USED / DIRTY |
- +----------------+------------------+----------------+
-
- then the scan is split in two parts. The first scanned part of the
- flash memory is organized through the members head and tail. The
- second scanned part is organized with head_extra and tail_extra. When
- the scan is completed, the two lists are merged together. The jffs_fm
- struct that head_extra references is the logical beginning of the
- flash memory so it will be referenced by the head member. */
-
-
-
-struct jffs_fmcontrol *jffs_build_begin(struct jffs_control *c, int unit);
-void jffs_build_end(struct jffs_fmcontrol *fmc);
-void jffs_cleanup_fmcontrol(struct jffs_fmcontrol *fmc);
-
-int jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size,
- struct jffs_node *node, struct jffs_fm **result);
-int jffs_fmfree(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
- struct jffs_node *node);
-
-__u32 jffs_free_size1(struct jffs_fmcontrol *fmc);
-__u32 jffs_free_size2(struct jffs_fmcontrol *fmc);
-void jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size);
-struct jffs_fm *jffs_cut_node(struct jffs_fmcontrol *fmc, __u32 size);
-struct jffs_node *jffs_get_oldest_node(struct jffs_fmcontrol *fmc);
-long jffs_erasable_size(struct jffs_fmcontrol *fmc);
-struct jffs_fm *jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset,
- __u32 size, struct jffs_node *node);
-int jffs_add_node(struct jffs_node *node);
-void jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
- __u32 size);
-
-#if CONFIG_JFFS_FS_VERBOSE > 0
-void jffs_print_fmcontrol(struct jffs_fmcontrol *fmc);
-#endif
-#if 0
-void jffs_print_node_ref(struct jffs_node_ref *ref);
-#endif /* 0 */
-
-#endif /* __LINUX_JFFS_FM_H__ */
diff --git a/fs/jffs/jffs_proc.c b/fs/jffs/jffs_proc.c
deleted file mode 100644
index 9bdd99a557c..00000000000
--- a/fs/jffs/jffs_proc.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 2000 Axis Communications AB.
- *
- * Created by Simon Kagstrom <simonk@axis.com>.
- *
- * $Id: jffs_proc.c,v 1.5 2001/06/02 14:34:55 dwmw2 Exp $
- *
- * 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.
- *
- * Overview:
- * This file defines JFFS partition entries in the proc file system.
- *
- * TODO:
- * Create some more proc files for different kinds of info, i.e. statistics
- * about written and read bytes, number of calls to different routines,
- * reports about failures.
- */
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/jffs.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/time.h>
-#include <linux/types.h>
-#include "jffs_fm.h"
-#include "jffs_proc.h"
-
-/*
- * Structure for a JFFS partition in the system
- */
-struct jffs_partition_dir {
- struct jffs_control *c;
- struct proc_dir_entry *part_root;
- struct proc_dir_entry *part_info;
- struct proc_dir_entry *part_layout;
- struct jffs_partition_dir *next;
-};
-
-/*
- * Structure for top-level entry in '/proc/fs' directory
- */
-struct proc_dir_entry *jffs_proc_root;
-
-/*
- * Linked list of 'jffs_partition_dirs' to help us track
- * the mounted JFFS partitions in the system
- */
-static struct jffs_partition_dir *jffs_part_dirs;
-
-/*
- * Read functions for entries
- */
-static int jffs_proc_info_read(char *page, char **start, off_t off,
- int count, int *eof, void *data);
-static int jffs_proc_layout_read (char *page, char **start, off_t off,
- int count, int *eof, void *data);
-
-
-/*
- * Register a JFFS partition directory (called upon mount)
- */
-int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c)
-{
- struct jffs_partition_dir *part_dir;
- struct proc_dir_entry *part_info = NULL;
- struct proc_dir_entry *part_layout = NULL;
- struct proc_dir_entry *part_root = NULL;
- char name[10];
-
- sprintf(name, "%d", mtd);
- /* Allocate structure for local JFFS partition table */
- part_dir = (struct jffs_partition_dir *)
- kmalloc(sizeof (struct jffs_partition_dir), GFP_KERNEL);
- if (!part_dir)
- goto out;
-
- /* Create entry for this partition */
- part_root = proc_mkdir(name, jffs_proc_root);
- if (!part_root)
- goto out1;
-
- /* Create entry for 'info' file */
- part_info = create_proc_entry ("info", 0, part_root);
- if (!part_info)
- goto out2;
- part_info->read_proc = jffs_proc_info_read;
- part_info->data = (void *) c;
-
- /* Create entry for 'layout' file */
- part_layout = create_proc_entry ("layout", 0, part_root);
- if (!part_layout)
- goto out3;
- part_layout->read_proc = jffs_proc_layout_read;
- part_layout->data = (void *) c;
-
- /* Fill in structure for table and insert in the list */
- part_dir->c = c;
- part_dir->part_root = part_root;
- part_dir->part_info = part_info;
- part_dir->part_layout = part_layout;
- part_dir->next = jffs_part_dirs;
- jffs_part_dirs = part_dir;
-
- /* Return happy */
- return 0;
-
-out3:
- remove_proc_entry("info", part_root);
-out2:
- remove_proc_entry(name, jffs_proc_root);
-out1:
- kfree(part_dir);
-out:
- return -ENOMEM;
-}
-
-
-/*
- * Unregister a JFFS partition directory (called at umount)
- */
-int jffs_unregister_jffs_proc_dir(struct jffs_control *c)
-{
- struct jffs_partition_dir *part_dir = jffs_part_dirs;
- struct jffs_partition_dir *prev_part_dir = NULL;
-
- while (part_dir) {
- if (part_dir->c == c) {
- /* Remove entries for partition */
- remove_proc_entry (part_dir->part_info->name,
- part_dir->part_root);
- remove_proc_entry (part_dir->part_layout->name,
- part_dir->part_root);
- remove_proc_entry (part_dir->part_root->name,
- jffs_proc_root);
-
- /* Remove entry from list */
- if (prev_part_dir)
- prev_part_dir->next = part_dir->next;
- else
- jffs_part_dirs = part_dir->next;
-
- /*
- * Check to see if this is the last one
- * and remove the entry from '/proc/fs'
- * if it is.
- */
- if (jffs_part_dirs == part_dir->next)
- remove_proc_entry ("jffs", proc_root_fs);
-
- /* Free memory for entry */
- kfree(part_dir);
-
- /* Return happy */
- return 0;
- }
-
- /* Move to next entry */
- prev_part_dir = part_dir;
- part_dir = part_dir->next;
- }
-
- /* Return unhappy */
- return -1;
-}
-
-
-/*
- * Read a JFFS partition's `info' file
- */
-static int jffs_proc_info_read (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct jffs_control *c = (struct jffs_control *) data;
- int len = 0;
-
- /* Get information on the parition */
- len += sprintf (page,
- "partition size: %08lX (%u)\n"
- "sector size: %08lX (%u)\n"
- "used size: %08lX (%u)\n"
- "dirty size: %08lX (%u)\n"
- "free size: %08lX (%u)\n\n",
- (unsigned long) c->fmc->flash_size, c->fmc->flash_size,
- (unsigned long) c->fmc->sector_size, c->fmc->sector_size,
- (unsigned long) c->fmc->used_size, c->fmc->used_size,
- (unsigned long) c->fmc->dirty_size, c->fmc->dirty_size,
- (unsigned long) (c->fmc->flash_size -
- (c->fmc->used_size + c->fmc->dirty_size)),
- c->fmc->flash_size - (c->fmc->used_size + c->fmc->dirty_size));
-
- /* We're done */
- *eof = 1;
-
- /* Return length */
- return len;
-}
-
-
-/*
- * Read a JFFS partition's `layout' file
- */
-static int jffs_proc_layout_read (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct jffs_control *c = (struct jffs_control *) data;
- struct jffs_fm *fm = NULL;
- struct jffs_fm *last_fm = NULL;
- int len = 0;
-
- /* Get the first item in the list */
- fm = c->fmc->head;
-
- /* Print free space */
- if (fm && fm->offset) {
- len += sprintf (page, "00000000 %08lX free\n",
- (unsigned long) fm->offset);
- }
-
- /* Loop through all of the flash control structures */
- while (fm && (len < (off + count))) {
- if (fm->nodes) {
- len += sprintf (page + len,
- "%08lX %08lX ino=%08lX, ver=%08lX\n",
- (unsigned long) fm->offset,
- (unsigned long) fm->size,
- (unsigned long) fm->nodes->node->ino,
- (unsigned long) fm->nodes->node->version);
- }
- else {
- len += sprintf (page + len,
- "%08lX %08lX dirty\n",
- (unsigned long) fm->offset,
- (unsigned long) fm->size);
- }
- last_fm = fm;
- fm = fm->next;
- }
-
- /* Print free space */
- if ((len < (off + count)) && last_fm
- && (last_fm->offset < c->fmc->flash_size)) {
- len += sprintf (page + len,
- "%08lX %08lX free\n",
- (unsigned long) last_fm->offset +
- last_fm->size,
- (unsigned long) (c->fmc->flash_size -
- (last_fm->offset + last_fm->size)));
- }
-
- /* We're done */
- *eof = 1;
-
- /* Return length */
- return len;
-}
diff --git a/fs/jffs/jffs_proc.h b/fs/jffs/jffs_proc.h
deleted file mode 100644
index 39a1c5d162b..00000000000
--- a/fs/jffs/jffs_proc.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * JFFS -- Journaling Flash File System, Linux implementation.
- *
- * Copyright (C) 2000 Axis Communications AB.
- *
- * Created by Simon Kagstrom <simonk@axis.com>.
- *
- * 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.
- *
- * $Id: jffs_proc.h,v 1.2 2000/11/15 22:04:12 sjhill Exp $
- */
-
-/* jffs_proc.h defines a structure for inclusion in the proc-file system. */
-#ifndef __LINUX_JFFS_PROC_H__
-#define __LINUX_JFFS_PROC_H__
-
-#include <linux/proc_fs.h>
-
-/* The proc_dir_entry for jffs (defined in jffs_proc.c). */
-extern struct proc_dir_entry *jffs_proc_root;
-
-int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c);
-int jffs_unregister_jffs_proc_dir(struct jffs_control *c);
-
-#endif /* __LINUX_JFFS_PROC_H__ */
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index ac32a2e8540..22d38ffc9ef 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -358,8 +358,7 @@ void delete_partition(struct gendisk *disk, int part)
p->ios[0] = p->ios[1] = 0;
p->sectors[0] = p->sectors[1] = 0;
sysfs_remove_link(&p->kobj, "subsystem");
- if (p->holder_dir)
- kobject_unregister(p->holder_dir);
+ kobject_unregister(p->holder_dir);
kobject_uevent(&p->kobj, KOBJ_REMOVE);
kobject_del(&p->kobj);
kobject_put(&p->kobj);
@@ -603,10 +602,8 @@ void del_gendisk(struct gendisk *disk)
disk->stamp = 0;
kobject_uevent(&disk->kobj, KOBJ_REMOVE);
- if (disk->holder_dir)
- kobject_unregister(disk->holder_dir);
- if (disk->slave_dir)
- kobject_unregister(disk->slave_dir);
+ kobject_unregister(disk->holder_dir);
+ kobject_unregister(disk->slave_dir);
if (disk->driverfs_dev) {
char *disk_name = make_block_name(disk);
sysfs_remove_link(&disk->kobj, "device");
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index c0e117649a4..98b0910ad80 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -54,7 +54,7 @@ static struct sysfs_ops subsys_sysfs_ops = {
/**
* add_to_collection - add buffer to a collection
* @buffer: buffer to be added
- * @node inode of set to add to
+ * @node: inode of set to add to
*/
static inline void
diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h
index ce7c9d65391..73967c8152d 100644
--- a/include/acpi/acinterp.h
+++ b/include/acpi/acinterp.h
@@ -253,7 +253,8 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread);
-void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc);
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc,
+ struct acpi_thread_state *thread);
/*
* exprep - ACPI AML execution - prep utilities
diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
index 04e9735a674..5206d61d74a 100644
--- a/include/acpi/acobject.h
+++ b/include/acpi/acobject.h
@@ -155,7 +155,7 @@ struct acpi_object_event {
struct acpi_object_mutex {
ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */
u16 acquisition_depth; /* Allow multiple Acquires, same thread */
- struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
+ acpi_thread_id owner_thread_id; /* Current owner of the mutex */
acpi_mutex os_mutex; /* Actual OS synchronization object */
union acpi_operand_object *prev; /* Link for list of acquired mutexes */
union acpi_operand_object *next; /* Link for list of acquired mutexes */
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index 4dc8a5043ef..f6275b0e66d 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -105,12 +105,6 @@ int acpi_ec_ecdt_probe(void);
int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
-/* --------------------------------------------------------------------------
- Hot Keys
- -------------------------------------------------------------------------- */
-
-extern int acpi_specific_hotkey_enabled;
-
/*--------------------------------------------------------------------------
Dock Station
-------------------------------------------------------------------------- */
@@ -122,10 +116,34 @@ extern int register_hotplug_dock_device(acpi_handle handle,
acpi_notify_handler handler, void *context);
extern void unregister_hotplug_dock_device(acpi_handle handle);
#else
-#define is_dock_device(h) (0)
-#define register_dock_notifier(nb) (-ENODEV)
-#define unregister_dock_notifier(nb) do { } while(0)
-#define register_hotplug_dock_device(h1, h2, c) (-ENODEV)
-#define unregister_hotplug_dock_device(h) do { } while(0)
+static inline int is_dock_device(acpi_handle handle)
+{
+ return 0;
+}
+static inline int register_dock_notifier(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+static inline void unregister_dock_notifier(struct notifier_block *nb)
+{
+}
+static inline int register_hotplug_dock_device(acpi_handle handle,
+ acpi_notify_handler handler, void *context)
+{
+ return -ENODEV;
+}
+static inline void unregister_hotplug_dock_device(acpi_handle handle)
+{
+}
+#endif
+
+/*--------------------------------------------------------------------------
+ Suspend/Resume
+ -------------------------------------------------------------------------- */
+#ifdef CONFIG_ACPI_SLEEP
+extern int acpi_sleep_init(void);
+#else
+#define acpi_sleep_init() do {} while (0)
#endif
+
#endif /*__ACPI_DRIVERS_H__*/
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 781394b9efe..2785058c82a 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -240,12 +240,6 @@ acpi_status
acpi_os_validate_address(u8 space_id,
acpi_physical_address address, acpi_size length);
-u8 acpi_os_readable(void *pointer, acpi_size length);
-
-#ifdef ACPI_FUTURE_USAGE
-u8 acpi_os_writable(void *pointer, acpi_size length);
-#endif
-
u64 acpi_os_get_timer(void);
acpi_status acpi_os_signal(u32 function, void *info);
diff --git a/include/asm-arm/.gitignore b/include/asm-arm/.gitignore
new file mode 100644
index 00000000000..e02c15d158f
--- /dev/null
+++ b/include/asm-arm/.gitignore
@@ -0,0 +1,2 @@
+arch
+mach-types.h
diff --git a/include/asm-arm/arch-at91rm9200/at91_aic.h b/include/asm-arm/arch-at91/at91_aic.h
index 267e69812e2..df44c12a12d 100644
--- a/include/asm-arm/arch-at91rm9200/at91_aic.h
+++ b/include/asm-arm/arch-at91/at91_aic.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_aic.h
+ * include/asm-arm/arch-at91/at91_aic.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/include/asm-arm/arch-at91rm9200/at91_dbgu.h b/include/asm-arm/arch-at91/at91_dbgu.h
index e4b8b27acfc..b0369e176f7 100644
--- a/include/asm-arm/arch-at91rm9200/at91_dbgu.h
+++ b/include/asm-arm/arch-at91/at91_dbgu.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_dbgu.h
+ * include/asm-arm/arch-at91/at91_dbgu.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
@@ -35,6 +35,20 @@
#define AT91_CIDR_NVPSIZ (0xf << 8) /* Nonvolatile Program Memory Size */
#define AT91_CIDR_NVPSIZ2 (0xf << 12) /* Second Nonvolatile Program Memory Size */
#define AT91_CIDR_SRAMSIZ (0xf << 16) /* Internal SRAM Size */
+#define AT91_CIDR_SRAMSIZ_1K (1 << 16)
+#define AT91_CIDR_SRAMSIZ_2K (2 << 16)
+#define AT91_CIDR_SRAMSIZ_112K (4 << 16)
+#define AT91_CIDR_SRAMSIZ_4K (5 << 16)
+#define AT91_CIDR_SRAMSIZ_80K (6 << 16)
+#define AT91_CIDR_SRAMSIZ_160K (7 << 16)
+#define AT91_CIDR_SRAMSIZ_8K (8 << 16)
+#define AT91_CIDR_SRAMSIZ_16K (9 << 16)
+#define AT91_CIDR_SRAMSIZ_32K (10 << 16)
+#define AT91_CIDR_SRAMSIZ_64K (11 << 16)
+#define AT91_CIDR_SRAMSIZ_128K (12 << 16)
+#define AT91_CIDR_SRAMSIZ_256K (13 << 16)
+#define AT91_CIDR_SRAMSIZ_96K (14 << 16)
+#define AT91_CIDR_SRAMSIZ_512K (15 << 16)
#define AT91_CIDR_ARCH (0xff << 20) /* Architecture Identifier */
#define AT91_CIDR_NVPTYP (7 << 28) /* Nonvolatile Program Memory Type */
#define AT91_CIDR_EXT (1 << 31) /* Extension Flag */
diff --git a/include/asm-arm/arch-at91rm9200/at91_ecc.h b/include/asm-arm/arch-at91/at91_ecc.h
index 5c564ede5c5..ff93df516d6 100644
--- a/include/asm-arm/arch-at91rm9200/at91_ecc.h
+++ b/include/asm-arm/arch-at91/at91_ecc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_ecc.h
+ * include/asm-arm/arch-at91/at91_ecc.h
*
* Error Corrected Code Controller (ECC) - System peripherals regsters.
* Based on AT91SAM9260 datasheet revision B.
diff --git a/include/asm-arm/arch-at91rm9200/at91_lcdc.h b/include/asm-arm/arch-at91/at91_lcdc.h
index 9cbfcdd3c47..ab040a40d37 100644
--- a/include/asm-arm/arch-at91rm9200/at91_lcdc.h
+++ b/include/asm-arm/arch-at91/at91_lcdc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_lcdc.h
+ * include/asm-arm/arch-at91/at91_lcdc.h
*
* LCD Controller (LCDC).
* Based on AT91SAM9261 datasheet revision E.
diff --git a/include/asm-arm/arch-at91rm9200/at91_mci.h b/include/asm-arm/arch-at91/at91_mci.h
index 9a552cb743c..40a9876b661 100644
--- a/include/asm-arm/arch-at91rm9200/at91_mci.h
+++ b/include/asm-arm/arch-at91/at91_mci.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_mci.h
+ * include/asm-arm/arch-at91/at91_mci.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/include/asm-arm/arch-at91rm9200/at91_pio.h b/include/asm-arm/arch-at91/at91_pio.h
index 680eaa1f591..84c3866d309 100644
--- a/include/asm-arm/arch-at91rm9200/at91_pio.h
+++ b/include/asm-arm/arch-at91/at91_pio.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_pio.h
+ * include/asm-arm/arch-at91/at91_pio.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/include/asm-arm/arch-at91rm9200/at91_pit.h b/include/asm-arm/arch-at91/at91_pit.h
index 4a30d009c58..5026325a5ae 100644
--- a/include/asm-arm/arch-at91rm9200/at91_pit.h
+++ b/include/asm-arm/arch-at91/at91_pit.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_pit.h
+ * include/asm-arm/arch-at91/at91_pit.h
*
* Periodic Interval Timer (PIT) - System peripherals regsters.
* Based on AT91SAM9261 datasheet revision D.
diff --git a/include/asm-arm/arch-at91rm9200/at91_pmc.h b/include/asm-arm/arch-at91/at91_pmc.h
index c3b489d09b6..33ff5b6798e 100644
--- a/include/asm-arm/arch-at91rm9200/at91_pmc.h
+++ b/include/asm-arm/arch-at91/at91_pmc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_pmc.h
+ * include/asm-arm/arch-at91/at91_pmc.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/include/asm-arm/arch-at91rm9200/at91_rstc.h b/include/asm-arm/arch-at91/at91_rstc.h
index 237d3c40b31..fb8d1618a23 100644
--- a/include/asm-arm/arch-at91rm9200/at91_rstc.h
+++ b/include/asm-arm/arch-at91/at91_rstc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_rstc.h
+ * include/asm-arm/arch-at91/at91_rstc.h
*
* Reset Controller (RSTC) - System peripherals regsters.
* Based on AT91SAM9261 datasheet revision D.
@@ -17,7 +17,7 @@
#define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */
#define AT91_RSTC_PERRST (1 << 2) /* Peripheral Reset */
#define AT91_RSTC_EXTRST (1 << 3) /* External Reset */
-#define AT91_RSTC_KEY (0xff << 24) /* KEY Password */
+#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
#define AT91_RSTC_SR (AT91_RSTC + 0x04) /* Reset Controller Status Register */
#define AT91_RSTC_URSTS (1 << 0) /* User Reset Status */
@@ -34,6 +34,5 @@
#define AT91_RSTC_URSTEN (1 << 0) /* User Reset Enable */
#define AT91_RSTC_URSTIEN (1 << 4) /* User Reset Interrupt Enable */
#define AT91_RSTC_ERSTL (0xf << 8) /* External Reset Length */
-#define AT91_RSTC_KEY (0xff << 24) /* KEY Password */
#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91_rtc.h b/include/asm-arm/arch-at91/at91_rtc.h
index 095fe088310..af9bd28174c 100644
--- a/include/asm-arm/arch-at91rm9200/at91_rtc.h
+++ b/include/asm-arm/arch-at91/at91_rtc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_rtc.h
+ * include/asm-arm/arch-at91/at91_rtc.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/include/asm-arm/arch-at91rm9200/at91_rtt.h b/include/asm-arm/arch-at91/at91_rtt.h
index c6751ba3ccc..bae1103fbbb 100644
--- a/include/asm-arm/arch-at91rm9200/at91_rtt.h
+++ b/include/asm-arm/arch-at91/at91_rtt.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_rtt.h
+ * include/asm-arm/arch-at91/at91_rtt.h
*
* Real-time Timer (RTT) - System peripherals regsters.
* Based on AT91SAM9261 datasheet revision D.
diff --git a/include/asm-arm/arch-at91rm9200/at91_shdwc.h b/include/asm-arm/arch-at91/at91_shdwc.h
index 0439250553c..795fcc26622 100644
--- a/include/asm-arm/arch-at91rm9200/at91_shdwc.h
+++ b/include/asm-arm/arch-at91/at91_shdwc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_shdwc.h
+ * include/asm-arm/arch-at91/at91_shdwc.h
*
* Shutdown Controller (SHDWC) - System peripherals regsters.
* Based on AT91SAM9261 datasheet revision D.
diff --git a/include/asm-arm/arch-at91rm9200/at91_spi.h b/include/asm-arm/arch-at91/at91_spi.h
index bec48ca89bb..f9b9a846499 100644
--- a/include/asm-arm/arch-at91rm9200/at91_spi.h
+++ b/include/asm-arm/arch-at91/at91_spi.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_spi.h
+ * include/asm-arm/arch-at91/at91_spi.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/include/asm-arm/arch-at91rm9200/at91_ssc.h b/include/asm-arm/arch-at91/at91_ssc.h
index 694bcaa8f7c..0ecc73460b5 100644
--- a/include/asm-arm/arch-at91rm9200/at91_ssc.h
+++ b/include/asm-arm/arch-at91/at91_ssc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_ssc.h
+ * include/asm-arm/arch-at91/at91_ssc.h
*
* Copyright (C) SAN People
*
diff --git a/include/asm-arm/arch-at91rm9200/at91_st.h b/include/asm-arm/arch-at91/at91_st.h
index 2432ddfc6c4..30446e2ea77 100644
--- a/include/asm-arm/arch-at91rm9200/at91_st.h
+++ b/include/asm-arm/arch-at91/at91_st.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_st.h
+ * include/asm-arm/arch-at91/at91_st.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/include/asm-arm/arch-at91rm9200/at91_tc.h b/include/asm-arm/arch-at91/at91_tc.h
index 8d06eb078e1..b85d3faeef5 100644
--- a/include/asm-arm/arch-at91rm9200/at91_tc.h
+++ b/include/asm-arm/arch-at91/at91_tc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_tc.h
+ * include/asm-arm/arch-at91/at91_tc.h
*
* Copyright (C) SAN People
*
diff --git a/include/asm-arm/arch-at91rm9200/at91_twi.h b/include/asm-arm/arch-at91/at91_twi.h
index cda914f1e74..ca9a9073345 100644
--- a/include/asm-arm/arch-at91rm9200/at91_twi.h
+++ b/include/asm-arm/arch-at91/at91_twi.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_twi.h
+ * include/asm-arm/arch-at91/at91_twi.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/include/asm-arm/arch-at91rm9200/at91_wdt.h b/include/asm-arm/arch-at91/at91_wdt.h
index ac63e775772..7251a344c74 100644
--- a/include/asm-arm/arch-at91rm9200/at91_wdt.h
+++ b/include/asm-arm/arch-at91/at91_wdt.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91_wdt.h
+ * include/asm-arm/arch-at91/at91_wdt.h
*
* Watchdog Timer (WDT) - System peripherals regsters.
* Based on AT91SAM9261 datasheet revision D.
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200.h b/include/asm-arm/arch-at91/at91rm9200.h
index c569b6a21a4..a12ac8ab2ad 100644
--- a/include/asm-arm/arch-at91rm9200/at91rm9200.h
+++ b/include/asm-arm/arch-at91/at91rm9200.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91rm9200.h
+ * include/asm-arm/arch-at91/at91rm9200.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_emac.h b/include/asm-arm/arch-at91/at91rm9200_emac.h
index fbc091e61e2..0c417af5fe7 100644
--- a/include/asm-arm/arch-at91rm9200/at91rm9200_emac.h
+++ b/include/asm-arm/arch-at91/at91rm9200_emac.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91rm9200_emac.h
+ * include/asm-arm/arch-at91/at91rm9200_emac.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_mc.h b/include/asm-arm/arch-at91/at91rm9200_mc.h
index 0c0d81480b3..24d012939cc 100644
--- a/include/asm-arm/arch-at91rm9200/at91rm9200_mc.h
+++ b/include/asm-arm/arch-at91/at91rm9200_mc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91rm9200_mc.h
+ * include/asm-arm/arch-at91/at91rm9200_mc.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9260.h b/include/asm-arm/arch-at91/at91sam9260.h
index 46f4dd65c03..2cadebc36af 100644
--- a/include/asm-arm/arch-at91rm9200/at91sam9260.h
+++ b/include/asm-arm/arch-at91/at91sam9260.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91sam9260.h
+ * include/asm-arm/arch-at91/at91sam9260.h
*
* (C) 2006 Andrew Victor
*
@@ -113,6 +113,10 @@
#define AT91SAM9260_UHP_BASE 0x00500000 /* USB Host controller */
+#define AT91SAM9XE_FLASH_BASE 0x00200000 /* Internal FLASH base address */
+#define AT91SAM9XE_SRAM_BASE 0x00300000 /* Internal SRAM base address */
+
+
#if 0
/*
* PIO pin definitions (peripheral A/B multiplexing).
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h b/include/asm-arm/arch-at91/at91sam9260_matrix.h
index 78f6b4917b8..aacb1e97642 100644
--- a/include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
+++ b/include/asm-arm/arch-at91/at91sam9260_matrix.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91sam9260_matrix.h
+ * include/asm-arm/arch-at91/at91sam9260_matrix.h
*
* Memory Controllers (MATRIX, EBI) - System peripherals registers.
* Based on AT91SAM9260 datasheet revision B.
@@ -18,7 +18,7 @@
#define AT91_MATRIX_MCFG2 (AT91_MATRIX + 0x08) /* Master Configuration Register 2 */
#define AT91_MATRIX_MCFG3 (AT91_MATRIX + 0x0C) /* Master Configuration Register 3 */
#define AT91_MATRIX_MCFG4 (AT91_MATRIX + 0x10) /* Master Configuration Register 4 */
-#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x04) /* Master Configuration Register 5 */
+#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x14) /* Master Configuration Register 5 */
#define AT91_MATRIX_ULBT (7 << 0) /* Undefined Length Burst Type */
#define AT91_MATRIX_ULBT_INFINITE (0 << 0)
#define AT91_MATRIX_ULBT_SINGLE (1 << 0)
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9261.h b/include/asm-arm/arch-at91/at91sam9261.h
index 8d39672d5b8..01b58ffe2e2 100644
--- a/include/asm-arm/arch-at91rm9200/at91sam9261.h
+++ b/include/asm-arm/arch-at91/at91sam9261.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91sam9261.h
+ * include/asm-arm/arch-at91/at91sam9261.h
*
* Copyright (C) SAN People
*
diff --git a/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h b/include/asm-arm/arch-at91/at91sam9261_matrix.h
index ec88efabbe6..6f072421be5 100644
--- a/include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
+++ b/include/asm-arm/arch-at91/at91sam9261_matrix.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91sam9261_matrix.h
+ * include/asm-arm/arch-at91/at91sam9261_matrix.h
*
* Memory Controllers (MATRIX, EBI) - System peripherals registers.
* Based on AT91SAM9261 datasheet revision D.
diff --git a/include/asm-arm/arch-at91/at91sam9263.h b/include/asm-arm/arch-at91/at91sam9263.h
new file mode 100644
index 00000000000..f4af68ae0ea
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91sam9263.h
@@ -0,0 +1,131 @@
+/*
+ * include/asm-arm/arch-at91/at91sam9263.h
+ *
+ * (C) 2007 Atmel Corporation.
+ *
+ * Common definitions.
+ * Based on AT91SAM9263 datasheet revision B (Preliminary).
+ *
+ * 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.
+ */
+
+#ifndef AT91SAM9263_H
+#define AT91SAM9263_H
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS 1 /* System Peripherals */
+#define AT91SAM9263_ID_PIOA 2 /* Parallel IO Controller A */
+#define AT91SAM9263_ID_PIOB 3 /* Parallel IO Controller B */
+#define AT91SAM9263_ID_PIOCDE 4 /* Parallel IO Controller C, D and E */
+#define AT91SAM9263_ID_US0 7 /* USART 0 */
+#define AT91SAM9263_ID_US1 8 /* USART 1 */
+#define AT91SAM9263_ID_US2 9 /* USART 2 */
+#define AT91SAM9263_ID_MCI0 10 /* Multimedia Card Interface 0 */
+#define AT91SAM9263_ID_MCI1 11 /* Multimedia Card Interface 1 */
+#define AT91SAM9263_ID_CAN 12 /* CAN */
+#define AT91SAM9263_ID_TWI 13 /* Two-Wire Interface */
+#define AT91SAM9263_ID_SPI0 14 /* Serial Peripheral Interface 0 */
+#define AT91SAM9263_ID_SPI1 15 /* Serial Peripheral Interface 1 */
+#define AT91SAM9263_ID_SSC0 16 /* Serial Synchronous Controller 0 */
+#define AT91SAM9263_ID_SSC1 17 /* Serial Synchronous Controller 1 */
+#define AT91SAM9263_ID_AC97C 18 /* AC97 Controller */
+#define AT91SAM9263_ID_TCB 19 /* Timer Counter 0, 1 and 2 */
+#define AT91SAM9263_ID_PWMC 20 /* Pulse Width Modulation Controller */
+#define AT91SAM9263_ID_EMAC 21 /* Ethernet */
+#define AT91SAM9263_ID_2DGE 23 /* 2D Graphic Engine */
+#define AT91SAM9263_ID_UDP 24 /* USB Device Port */
+#define AT91SAM9263_ID_ISI 25 /* Image Sensor Interface */
+#define AT91SAM9263_ID_LCDC 26 /* LCD Controller */
+#define AT91SAM9263_ID_DMA 27 /* DMA Controller */
+#define AT91SAM9263_ID_UHP 29 /* USB Host port */
+#define AT91SAM9263_ID_IRQ0 30 /* Advanced Interrupt Controller (IRQ0) */
+#define AT91SAM9263_ID_IRQ1 31 /* Advanced Interrupt Controller (IRQ1) */
+
+
+/*
+ * User Peripheral physical base addresses.
+ */
+#define AT91SAM9263_BASE_UDP 0xfff78000
+#define AT91SAM9263_BASE_TCB0 0xfff7c000
+#define AT91SAM9263_BASE_TC0 0xfff7c000
+#define AT91SAM9263_BASE_TC1 0xfff7c040
+#define AT91SAM9263_BASE_TC2 0xfff7c080
+#define AT91SAM9263_BASE_MCI0 0xfff80000
+#define AT91SAM9263_BASE_MCI1 0xfff84000
+#define AT91SAM9263_BASE_TWI 0xfff88000
+#define AT91SAM9263_BASE_US0 0xfff8c000
+#define AT91SAM9263_BASE_US1 0xfff90000
+#define AT91SAM9263_BASE_US2 0xfff94000
+#define AT91SAM9263_BASE_SSC0 0xfff98000
+#define AT91SAM9263_BASE_SSC1 0xfff9c000
+#define AT91SAM9263_BASE_AC97C 0xfffa0000
+#define AT91SAM9263_BASE_SPI0 0xfffa4000
+#define AT91SAM9263_BASE_SPI1 0xfffa8000
+#define AT91SAM9263_BASE_CAN 0xfffac000
+#define AT91SAM9263_BASE_PWMC 0xfffb8000
+#define AT91SAM9263_BASE_EMAC 0xfffbc000
+#define AT91SAM9263_BASE_ISI 0xfffc4000
+#define AT91SAM9263_BASE_2DGE 0xfffc8000
+#define AT91_BASE_SYS 0xffffe000
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_ECC0 (0xffffe000 - AT91_BASE_SYS)
+#define AT91_SDRAMC0 (0xffffe200 - AT91_BASE_SYS)
+#define AT91_SMC0 (0xffffe400 - AT91_BASE_SYS)
+#define AT91_ECC1 (0xffffe600 - AT91_BASE_SYS)
+#define AT91_SDRAMC1 (0xffffe800 - AT91_BASE_SYS)
+#define AT91_SMC1 (0xffffea00 - AT91_BASE_SYS)
+#define AT91_MATRIX (0xffffec00 - AT91_BASE_SYS)
+#define AT91_CCFG (0xffffed10 - AT91_BASE_SYS)
+#define AT91_DBGU (0xffffee00 - AT91_BASE_SYS)
+#define AT91_AIC (0xfffff000 - AT91_BASE_SYS)
+#define AT91_PIOA (0xfffff200 - AT91_BASE_SYS)
+#define AT91_PIOB (0xfffff400 - AT91_BASE_SYS)
+#define AT91_PIOC (0xfffff600 - AT91_BASE_SYS)
+#define AT91_PIOD (0xfffff800 - AT91_BASE_SYS)
+#define AT91_PIOE (0xfffffa00 - AT91_BASE_SYS)
+#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
+#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
+#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS)
+#define AT91_RTT0 (0xfffffd20 - AT91_BASE_SYS)
+#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS)
+#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS)
+#define AT91_RTT1 (0xfffffd50 - AT91_BASE_SYS)
+#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS)
+
+#define AT91_SMC AT91_SMC0
+
+/*
+ * Internal Memory.
+ */
+#define AT91SAM9263_SRAM0_BASE 0x00300000 /* Internal SRAM 0 base address */
+#define AT91SAM9263_SRAM0_SIZE (80 * SZ_1K) /* Internal SRAM 0 size (80Kb) */
+
+#define AT91SAM9263_ROM_BASE 0x00400000 /* Internal ROM base address */
+#define AT91SAM9263_ROM_SIZE SZ_128K /* Internal ROM size (128Kb) */
+
+#define AT91SAM9263_SRAM1_BASE 0x00500000 /* Internal SRAM 1 base address */
+#define AT91SAM9263_SRAM1_SIZE SZ_16K /* Internal SRAM 1 size (16Kb) */
+
+#define AT91SAM9263_LCDC_BASE 0x00700000 /* LCD Controller */
+#define AT91SAM9263_DMAC_BASE 0x00800000 /* DMA Controller */
+#define AT91SAM9263_UHP_BASE 0x00a00000 /* USB Host controller */
+
+#if 0
+/*
+ * PIO pin definitions (peripheral A/B multiplexing).
+ */
+
+// TODO: Add
+
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-at91/at91sam9263_matrix.h b/include/asm-arm/arch-at91/at91sam9263_matrix.h
new file mode 100644
index 00000000000..6fc6e4be624
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91sam9263_matrix.h
@@ -0,0 +1,129 @@
+/*
+ * include/asm-arm/arch-at91/at91sam9263_matrix.h
+ *
+ * Copyright (C) 2006 Atmel Corporation.
+ *
+ * Memory Controllers (MATRIX, EBI) - System peripherals registers.
+ * Based on AT91SAM9263 datasheet revision B (Preliminary).
+ *
+ * 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.
+ */
+
+#ifndef AT91SAM9263_MATRIX_H
+#define AT91SAM9263_MATRIX_H
+
+#define AT91_MATRIX_MCFG0 (AT91_MATRIX + 0x00) /* Master Configuration Register 0 */
+#define AT91_MATRIX_MCFG1 (AT91_MATRIX + 0x04) /* Master Configuration Register 1 */
+#define AT91_MATRIX_MCFG2 (AT91_MATRIX + 0x08) /* Master Configuration Register 2 */
+#define AT91_MATRIX_MCFG3 (AT91_MATRIX + 0x0C) /* Master Configuration Register 3 */
+#define AT91_MATRIX_MCFG4 (AT91_MATRIX + 0x10) /* Master Configuration Register 4 */
+#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x14) /* Master Configuration Register 5 */
+#define AT91_MATRIX_MCFG6 (AT91_MATRIX + 0x18) /* Master Configuration Register 6 */
+#define AT91_MATRIX_MCFG7 (AT91_MATRIX + 0x1C) /* Master Configuration Register 7 */
+#define AT91_MATRIX_MCFG8 (AT91_MATRIX + 0x20) /* Master Configuration Register 8 */
+#define AT91_MATRIX_ULBT (7 << 0) /* Undefined Length Burst Type */
+#define AT91_MATRIX_ULBT_INFINITE (0 << 0)
+#define AT91_MATRIX_ULBT_SINGLE (1 << 0)
+#define AT91_MATRIX_ULBT_FOUR (2 << 0)
+#define AT91_MATRIX_ULBT_EIGHT (3 << 0)
+#define AT91_MATRIX_ULBT_SIXTEEN (4 << 0)
+
+#define AT91_MATRIX_SCFG0 (AT91_MATRIX + 0x40) /* Slave Configuration Register 0 */
+#define AT91_MATRIX_SCFG1 (AT91_MATRIX + 0x44) /* Slave Configuration Register 1 */
+#define AT91_MATRIX_SCFG2 (AT91_MATRIX + 0x48) /* Slave Configuration Register 2 */
+#define AT91_MATRIX_SCFG3 (AT91_MATRIX + 0x4C) /* Slave Configuration Register 3 */
+#define AT91_MATRIX_SCFG4 (AT91_MATRIX + 0x50) /* Slave Configuration Register 4 */
+#define AT91_MATRIX_SCFG5 (AT91_MATRIX + 0x54) /* Slave Configuration Register 5 */
+#define AT91_MATRIX_SCFG6 (AT91_MATRIX + 0x58) /* Slave Configuration Register 6 */
+#define AT91_MATRIX_SCFG7 (AT91_MATRIX + 0x5C) /* Slave Configuration Register 7 */
+#define AT91_MATRIX_SLOT_CYCLE (0xff << 0) /* Maximum Number of Allowed Cycles for a Burst */
+#define AT91_MATRIX_DEFMSTR_TYPE (3 << 16) /* Default Master Type */
+#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16)
+#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16)
+#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16)
+#define AT91_MATRIX_FIXED_DEFMSTR (7 << 18) /* Fixed Index of Default Master */
+#define AT91_MATRIX_ARBT (3 << 24) /* Arbitration Type */
+#define AT91_MATRIX_ARBT_ROUND_ROBIN (0 << 24)
+#define AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24)
+
+#define AT91_MATRIX_PRAS0 (AT91_MATRIX + 0x80) /* Priority Register A for Slave 0 */
+#define AT91_MATRIX_PRBS0 (AT91_MATRIX + 0x84) /* Priority Register B for Slave 0 */
+#define AT91_MATRIX_PRAS1 (AT91_MATRIX + 0x88) /* Priority Register A for Slave 1 */
+#define AT91_MATRIX_PRBS1 (AT91_MATRIX + 0x8C) /* Priority Register B for Slave 1 */
+#define AT91_MATRIX_PRAS2 (AT91_MATRIX + 0x90) /* Priority Register A for Slave 2 */
+#define AT91_MATRIX_PRBS2 (AT91_MATRIX + 0x94) /* Priority Register B for Slave 2 */
+#define AT91_MATRIX_PRAS3 (AT91_MATRIX + 0x98) /* Priority Register A for Slave 3 */
+#define AT91_MATRIX_PRBS3 (AT91_MATRIX + 0x9C) /* Priority Register B for Slave 3 */
+#define AT91_MATRIX_PRAS4 (AT91_MATRIX + 0xA0) /* Priority Register A for Slave 4 */
+#define AT91_MATRIX_PRBS4 (AT91_MATRIX + 0xA4) /* Priority Register B for Slave 4 */
+#define AT91_MATRIX_PRAS5 (AT91_MATRIX + 0xA8) /* Priority Register A for Slave 5 */
+#define AT91_MATRIX_PRBS5 (AT91_MATRIX + 0xAC) /* Priority Register B for Slave 5 */
+#define AT91_MATRIX_PRAS6 (AT91_MATRIX + 0xB0) /* Priority Register A for Slave 6 */
+#define AT91_MATRIX_PRBS6 (AT91_MATRIX + 0xB4) /* Priority Register B for Slave 6 */
+#define AT91_MATRIX_PRAS7 (AT91_MATRIX + 0xB8) /* Priority Register A for Slave 7 */
+#define AT91_MATRIX_PRBS7 (AT91_MATRIX + 0xBC) /* Priority Register B for Slave 7 */
+#define AT91_MATRIX_M0PR (3 << 0) /* Master 0 Priority */
+#define AT91_MATRIX_M1PR (3 << 4) /* Master 1 Priority */
+#define AT91_MATRIX_M2PR (3 << 8) /* Master 2 Priority */
+#define AT91_MATRIX_M3PR (3 << 12) /* Master 3 Priority */
+#define AT91_MATRIX_M4PR (3 << 16) /* Master 4 Priority */
+#define AT91_MATRIX_M5PR (3 << 20) /* Master 5 Priority */
+#define AT91_MATRIX_M6PR (3 << 24) /* Master 6 Priority */
+#define AT91_MATRIX_M7PR (3 << 28) /* Master 7 Priority */
+#define AT91_MATRIX_M8PR (3 << 0) /* Master 8 Priority (in Register B) */
+
+#define AT91_MATRIX_MRCR (AT91_MATRIX + 0x100) /* Master Remap Control Register */
+#define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
+#define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
+#define AT91_MATRIX_RCB2 (1 << 2)
+#define AT91_MATRIX_RCB3 (1 << 3)
+#define AT91_MATRIX_RCB4 (1 << 4)
+#define AT91_MATRIX_RCB5 (1 << 5)
+#define AT91_MATRIX_RCB6 (1 << 6)
+#define AT91_MATRIX_RCB7 (1 << 7)
+#define AT91_MATRIX_RCB8 (1 << 8)
+
+#define AT91_MATRIX_TCMR (AT91_MATRIX + 0x114) /* TCM Configuration Register */
+#define AT91_MATRIX_ITCM_SIZE (0xf << 0) /* Size of ITCM enabled memory block */
+#define AT91_MATRIX_ITCM_0 (0 << 0)
+#define AT91_MATRIX_ITCM_16 (5 << 0)
+#define AT91_MATRIX_ITCM_32 (6 << 0)
+#define AT91_MATRIX_DTCM_SIZE (0xf << 4) /* Size of DTCM enabled memory block */
+#define AT91_MATRIX_DTCM_0 (0 << 4)
+#define AT91_MATRIX_DTCM_16 (5 << 4)
+#define AT91_MATRIX_DTCM_32 (6 << 4)
+
+#define AT91_MATRIX_EBI0CSA (AT91_MATRIX + 0x120) /* EBI0 Chip Select Assignment Register */
+#define AT91_MATRIX_EBI0_CS1A (1 << 1) /* Chip Select 1 Assignment */
+#define AT91_MATRIX_EBI0_CS1A_SMC (0 << 1)
+#define AT91_MATRIX_EBI0_CS1A_SDRAMC (1 << 1)
+#define AT91_MATRIX_EBI0_CS3A (1 << 3) /* Chip Select 3 Assignment */
+#define AT91_MATRIX_EBI0_CS3A_SMC (0 << 3)
+#define AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA (1 << 3)
+#define AT91_MATRIX_EBI0_CS4A (1 << 4) /* Chip Select 4 Assignment */
+#define AT91_MATRIX_EBI0_CS4A_SMC (0 << 4)
+#define AT91_MATRIX_EBI0_CS4A_SMC_CF1 (1 << 4)
+#define AT91_MATRIX_EBI0_CS5A (1 << 5) /* Chip Select 5 Assignment */
+#define AT91_MATRIX_EBI0_CS5A_SMC (0 << 5)
+#define AT91_MATRIX_EBI0_CS5A_SMC_CF2 (1 << 5)
+#define AT91_MATRIX_EBI0_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */
+#define AT91_MATRIX_EBI0_VDDIOMSEL (1 << 16) /* Memory voltage selection */
+#define AT91_MATRIX_EBI0_VDDIOMSEL_1_8V (0 << 16)
+#define AT91_MATRIX_EBI0_VDDIOMSEL_3_3V (1 << 16)
+
+#define AT91_MATRIX_EBI1CSA (AT91_MATRIX + 0x124) /* EBI1 Chip Select Assignment Register */
+#define AT91_MATRIX_EBI1_CS1A (1 << 1) /* Chip Select 1 Assignment */
+#define AT91_MATRIX_EBI1_CS1A_SMC (0 << 1)
+#define AT91_MATRIX_EBI1_CS1A_SDRAMC (1 << 1)
+#define AT91_MATRIX_EBI1_CS2A (1 << 3) /* Chip Select 3 Assignment */
+#define AT91_MATRIX_EBI1_CS2A_SMC (0 << 3)
+#define AT91_MATRIX_EBI1_CS2A_SMC_SMARTMEDIA (1 << 3)
+#define AT91_MATRIX_EBI1_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */
+#define AT91_MATRIX_EBI1_VDDIOMSEL (1 << 16) /* Memory voltage selection */
+#define AT91_MATRIX_EBI1_VDDIOMSEL_1_8V (0 << 16)
+#define AT91_MATRIX_EBI1_VDDIOMSEL_3_3V (1 << 16)
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h b/include/asm-arm/arch-at91/at91sam926x_mc.h
index 972e7531c7f..d82631c251f 100644
--- a/include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
+++ b/include/asm-arm/arch-at91/at91sam926x_mc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/at91sam926x_mc.h
+ * include/asm-arm/arch-at91/at91sam926x_mc.h
*
* Memory Controllers (SMC, SDRAMC) - System peripherals registers.
* Based on AT91SAM9261 datasheet revision D.
@@ -131,4 +131,11 @@
#define AT91_SMC_PS_16 (2 << 28)
#define AT91_SMC_PS_32 (3 << 28)
+#if defined(AT91_SMC1) /* The AT91SAM9263 has 2 Static Memory contollers */
+#define AT91_SMC1_SETUP(n) (AT91_SMC1 + 0x00 + ((n)*0x10)) /* Setup Register for CS n */
+#define AT91_SMC1_PULSE(n) (AT91_SMC1 + 0x04 + ((n)*0x10)) /* Pulse Register for CS n */
+#define AT91_SMC1_CYCLE(n) (AT91_SMC1 + 0x08 + ((n)*0x10)) /* Cycle Register for CS n */
+#define AT91_SMC1_MODE(n) (AT91_SMC1 + 0x0c + ((n)*0x10)) /* Mode Register for CS n */
+#endif
+
#endif
diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91/board.h
index 768e0fc6aa2..7b9903c2c44 100644
--- a/include/asm-arm/arch-at91rm9200/board.h
+++ b/include/asm-arm/arch-at91/board.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/board.h
+ * include/asm-arm/arch-at91/board.h
*
* Copyright (C) 2005 HP Labs
*
@@ -60,7 +60,7 @@ struct at91_mmc_data {
u8 wp_pin; /* (SD) writeprotect detect */
u8 vcc_pin; /* power switching (high == on) */
};
-extern void __init at91_add_device_mmc(struct at91_mmc_data *data);
+extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data);
/* Ethernet */
struct at91_eth_data {
@@ -69,9 +69,14 @@ struct at91_eth_data {
};
extern void __init at91_add_device_eth(struct at91_eth_data *data);
+#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9263)
+#define eth_platform_data at91_eth_data
+#endif
+
/* USB Host */
struct at91_usbh_data {
u8 ports; /* number of ports on root hub */
+ u8 vbus_pin[]; /* port power-control pin */
};
extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
diff --git a/include/asm-arm/arch-at91rm9200/cpu.h b/include/asm-arm/arch-at91/cpu.h
index 6f8d09b0869..d464ca58cdb 100644
--- a/include/asm-arm/arch-at91rm9200/cpu.h
+++ b/include/asm-arm/arch-at91/cpu.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/cpu.h
+ * include/asm-arm/arch-at91/cpu.h
*
* Copyright (C) 2006 SAN People
*
@@ -20,7 +20,11 @@
#define ARCH_ID_AT91RM9200 0x09290780
#define ARCH_ID_AT91SAM9260 0x019803a0
#define ARCH_ID_AT91SAM9261 0x019703a0
+#define ARCH_ID_AT91SAM9263 0x019607a0
+#define ARCH_ID_AT91SAM9XE128 0x329973a0
+#define ARCH_ID_AT91SAM9XE256 0x329a93a0
+#define ARCH_ID_AT91SAM9XE512 0x329aa3a0
static inline unsigned long at91_cpu_identify(void)
{
@@ -28,6 +32,16 @@ static inline unsigned long at91_cpu_identify(void)
}
+#define ARCH_FAMILY_AT91X92 0x09200000
+#define ARCH_FAMILY_AT91SAM9 0x01900000
+#define ARCH_FAMILY_AT91SAM9XE 0x02900000
+
+static inline unsigned long at91_arch_identify(void)
+{
+ return (at91_sys_read(AT91_DBGU_CIDR) & AT91_CIDR_ARCH);
+}
+
+
#ifdef CONFIG_ARCH_AT91RM9200
#define cpu_is_at91rm9200() (at91_cpu_identify() == ARCH_ID_AT91RM9200)
#else
@@ -35,8 +49,10 @@ static inline unsigned long at91_cpu_identify(void)
#endif
#ifdef CONFIG_ARCH_AT91SAM9260
-#define cpu_is_at91sam9260() (at91_cpu_identify() == ARCH_ID_AT91SAM9260)
+#define cpu_is_at91sam9xe() (at91_arch_identify() == ARCH_FAMILY_AT91SAM9XE)
+#define cpu_is_at91sam9260() ((at91_cpu_identify() == ARCH_ID_AT91SAM9260) || cpu_is_at91sam9xe())
#else
+#define cpu_is_at91sam9xe() (0)
#define cpu_is_at91sam9260() (0)
#endif
@@ -46,4 +62,10 @@ static inline unsigned long at91_cpu_identify(void)
#define cpu_is_at91sam9261() (0)
#endif
+#ifdef CONFIG_ARCH_AT91SAM9263
+#define cpu_is_at91sam9263() (at91_cpu_identify() == ARCH_ID_AT91SAM9263)
+#else
+#define cpu_is_at91sam9263() (0)
+#endif
+
#endif
diff --git a/include/asm-arm/arch-at91/debug-macro.S b/include/asm-arm/arch-at91/debug-macro.S
new file mode 100644
index 00000000000..13e9f5e1d4f
--- /dev/null
+++ b/include/asm-arm/arch-at91/debug-macro.S
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-at91/debug-macro.S
+ *
+ * Copyright (C) 2003-2005 SAN People
+ *
+ * Debugging macro include header
+ *
+ * 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/hardware.h>
+#include <asm/arch/at91_dbgu.h>
+
+ .macro addruart,rx
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled?
+ ldreq \rx, =(AT91_BASE_SYS + AT91_DBGU) @ System peripherals (phys address)
+ ldrne \rx, =(AT91_VA_BASE_SYS + AT91_DBGU) @ System peripherals (virt address)
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx, #(AT91_DBGU_THR - AT91_DBGU)] @ Write to Transmitter Holding Register
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldr \rd, [\rx, #(AT91_DBGU_SR - AT91_DBGU)] @ Read Status Register
+ tst \rd, #AT91_DBGU_TXRDY @ DBGU_TXRDY = 1 when ready to transmit
+ beq 1001b
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #(AT91_DBGU_SR - AT91_DBGU)] @ Read Status Register
+ tst \rd, #AT91_DBGU_TXEMPTY @ DBGU_TXEMPTY = 1 when transmission complete
+ beq 1001b
+ .endm
+
diff --git a/include/asm-arm/arch-at91rm9200/dma.h b/include/asm-arm/arch-at91/dma.h
index 22c1dfdd8da..774565412be 100644
--- a/include/asm-arm/arch-at91rm9200/dma.h
+++ b/include/asm-arm/arch-at91/dma.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/dma.h
+ * include/asm-arm/arch-at91/dma.h
*
* Copyright (C) 2003 SAN People
*
diff --git a/include/asm-arm/arch-at91/entry-macro.S b/include/asm-arm/arch-at91/entry-macro.S
new file mode 100644
index 00000000000..76c8cccf73a
--- /dev/null
+++ b/include/asm-arm/arch-at91/entry-macro.S
@@ -0,0 +1,26 @@
+/*
+ * include/asm-arm/arch-at91/entry-macro.S
+ *
+ * Copyright (C) 2003-2005 SAN People
+ *
+ * Low-level IRQ helper macros for AT91RM9200 platforms
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <asm/hardware.h>
+#include <asm/arch/at91_aic.h>
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \base, =(AT91_VA_BASE_SYS + AT91_AIC) @ base virtual address of AIC peripheral
+ ldr \irqnr, [\base, #(AT91_AIC_IVR - AT91_AIC)] @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
+ ldr \irqstat, [\base, #(AT91_AIC_ISR - AT91_AIC)] @ read interrupt source number
+ teq \irqstat, #0 @ ISR is 0 when no current interrupt, or spurious interrupt
+ streq \tmp, [\base, #(AT91_AIC_EOICR - AT91_AIC)] @ not going to be handled further, then ACK it now.
+ .endm
+
diff --git a/include/asm-arm/arch-at91rm9200/gpio.h b/include/asm-arm/arch-at91/gpio.h
index e09d6528fad..98ad2114f43 100644
--- a/include/asm-arm/arch-at91rm9200/gpio.h
+++ b/include/asm-arm/arch-at91/gpio.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/gpio.h
+ * include/asm-arm/arch-at91/gpio.h
*
* Copyright (C) 2005 HP Labs
*
@@ -17,7 +17,7 @@
#define PIN_BASE NR_AIC_IRQS
-#define MAX_GPIO_BANKS 4
+#define MAX_GPIO_BANKS 5
/* these pin numbers double as IRQ numbers, like AT91xxx_ID_* values */
@@ -26,37 +26,31 @@
#define AT91_PIN_PA2 (PIN_BASE + 0x00 + 2)
#define AT91_PIN_PA3 (PIN_BASE + 0x00 + 3)
#define AT91_PIN_PA4 (PIN_BASE + 0x00 + 4)
-
#define AT91_PIN_PA5 (PIN_BASE + 0x00 + 5)
#define AT91_PIN_PA6 (PIN_BASE + 0x00 + 6)
#define AT91_PIN_PA7 (PIN_BASE + 0x00 + 7)
#define AT91_PIN_PA8 (PIN_BASE + 0x00 + 8)
#define AT91_PIN_PA9 (PIN_BASE + 0x00 + 9)
-
#define AT91_PIN_PA10 (PIN_BASE + 0x00 + 10)
#define AT91_PIN_PA11 (PIN_BASE + 0x00 + 11)
#define AT91_PIN_PA12 (PIN_BASE + 0x00 + 12)
#define AT91_PIN_PA13 (PIN_BASE + 0x00 + 13)
#define AT91_PIN_PA14 (PIN_BASE + 0x00 + 14)
-
#define AT91_PIN_PA15 (PIN_BASE + 0x00 + 15)
#define AT91_PIN_PA16 (PIN_BASE + 0x00 + 16)
#define AT91_PIN_PA17 (PIN_BASE + 0x00 + 17)
#define AT91_PIN_PA18 (PIN_BASE + 0x00 + 18)
#define AT91_PIN_PA19 (PIN_BASE + 0x00 + 19)
-
#define AT91_PIN_PA20 (PIN_BASE + 0x00 + 20)
#define AT91_PIN_PA21 (PIN_BASE + 0x00 + 21)
#define AT91_PIN_PA22 (PIN_BASE + 0x00 + 22)
#define AT91_PIN_PA23 (PIN_BASE + 0x00 + 23)
#define AT91_PIN_PA24 (PIN_BASE + 0x00 + 24)
-
#define AT91_PIN_PA25 (PIN_BASE + 0x00 + 25)
#define AT91_PIN_PA26 (PIN_BASE + 0x00 + 26)
#define AT91_PIN_PA27 (PIN_BASE + 0x00 + 27)
#define AT91_PIN_PA28 (PIN_BASE + 0x00 + 28)
#define AT91_PIN_PA29 (PIN_BASE + 0x00 + 29)
-
#define AT91_PIN_PA30 (PIN_BASE + 0x00 + 30)
#define AT91_PIN_PA31 (PIN_BASE + 0x00 + 31)
@@ -65,37 +59,31 @@
#define AT91_PIN_PB2 (PIN_BASE + 0x20 + 2)
#define AT91_PIN_PB3 (PIN_BASE + 0x20 + 3)
#define AT91_PIN_PB4 (PIN_BASE + 0x20 + 4)
-
#define AT91_PIN_PB5 (PIN_BASE + 0x20 + 5)
#define AT91_PIN_PB6 (PIN_BASE + 0x20 + 6)
#define AT91_PIN_PB7 (PIN_BASE + 0x20 + 7)
#define AT91_PIN_PB8 (PIN_BASE + 0x20 + 8)
#define AT91_PIN_PB9 (PIN_BASE + 0x20 + 9)
-
#define AT91_PIN_PB10 (PIN_BASE + 0x20 + 10)
#define AT91_PIN_PB11 (PIN_BASE + 0x20 + 11)
#define AT91_PIN_PB12 (PIN_BASE + 0x20 + 12)
#define AT91_PIN_PB13 (PIN_BASE + 0x20 + 13)
#define AT91_PIN_PB14 (PIN_BASE + 0x20 + 14)
-
#define AT91_PIN_PB15 (PIN_BASE + 0x20 + 15)
#define AT91_PIN_PB16 (PIN_BASE + 0x20 + 16)
#define AT91_PIN_PB17 (PIN_BASE + 0x20 + 17)
#define AT91_PIN_PB18 (PIN_BASE + 0x20 + 18)
#define AT91_PIN_PB19 (PIN_BASE + 0x20 + 19)
-
#define AT91_PIN_PB20 (PIN_BASE + 0x20 + 20)
#define AT91_PIN_PB21 (PIN_BASE + 0x20 + 21)
#define AT91_PIN_PB22 (PIN_BASE + 0x20 + 22)
#define AT91_PIN_PB23 (PIN_BASE + 0x20 + 23)
#define AT91_PIN_PB24 (PIN_BASE + 0x20 + 24)
-
#define AT91_PIN_PB25 (PIN_BASE + 0x20 + 25)
#define AT91_PIN_PB26 (PIN_BASE + 0x20 + 26)
#define AT91_PIN_PB27 (PIN_BASE + 0x20 + 27)
#define AT91_PIN_PB28 (PIN_BASE + 0x20 + 28)
#define AT91_PIN_PB29 (PIN_BASE + 0x20 + 29)
-
#define AT91_PIN_PB30 (PIN_BASE + 0x20 + 30)
#define AT91_PIN_PB31 (PIN_BASE + 0x20 + 31)
@@ -104,37 +92,31 @@
#define AT91_PIN_PC2 (PIN_BASE + 0x40 + 2)
#define AT91_PIN_PC3 (PIN_BASE + 0x40 + 3)
#define AT91_PIN_PC4 (PIN_BASE + 0x40 + 4)
-
#define AT91_PIN_PC5 (PIN_BASE + 0x40 + 5)
#define AT91_PIN_PC6 (PIN_BASE + 0x40 + 6)
#define AT91_PIN_PC7 (PIN_BASE + 0x40 + 7)
#define AT91_PIN_PC8 (PIN_BASE + 0x40 + 8)
#define AT91_PIN_PC9 (PIN_BASE + 0x40 + 9)
-
#define AT91_PIN_PC10 (PIN_BASE + 0x40 + 10)
#define AT91_PIN_PC11 (PIN_BASE + 0x40 + 11)
#define AT91_PIN_PC12 (PIN_BASE + 0x40 + 12)
#define AT91_PIN_PC13 (PIN_BASE + 0x40 + 13)
#define AT91_PIN_PC14 (PIN_BASE + 0x40 + 14)
-
#define AT91_PIN_PC15 (PIN_BASE + 0x40 + 15)
#define AT91_PIN_PC16 (PIN_BASE + 0x40 + 16)
#define AT91_PIN_PC17 (PIN_BASE + 0x40 + 17)
#define AT91_PIN_PC18 (PIN_BASE + 0x40 + 18)
#define AT91_PIN_PC19 (PIN_BASE + 0x40 + 19)
-
#define AT91_PIN_PC20 (PIN_BASE + 0x40 + 20)
#define AT91_PIN_PC21 (PIN_BASE + 0x40 + 21)
#define AT91_PIN_PC22 (PIN_BASE + 0x40 + 22)
#define AT91_PIN_PC23 (PIN_BASE + 0x40 + 23)
#define AT91_PIN_PC24 (PIN_BASE + 0x40 + 24)
-
#define AT91_PIN_PC25 (PIN_BASE + 0x40 + 25)
#define AT91_PIN_PC26 (PIN_BASE + 0x40 + 26)
#define AT91_PIN_PC27 (PIN_BASE + 0x40 + 27)
#define AT91_PIN_PC28 (PIN_BASE + 0x40 + 28)
#define AT91_PIN_PC29 (PIN_BASE + 0x40 + 29)
-
#define AT91_PIN_PC30 (PIN_BASE + 0x40 + 30)
#define AT91_PIN_PC31 (PIN_BASE + 0x40 + 31)
@@ -143,40 +125,67 @@
#define AT91_PIN_PD2 (PIN_BASE + 0x60 + 2)
#define AT91_PIN_PD3 (PIN_BASE + 0x60 + 3)
#define AT91_PIN_PD4 (PIN_BASE + 0x60 + 4)
-
#define AT91_PIN_PD5 (PIN_BASE + 0x60 + 5)
#define AT91_PIN_PD6 (PIN_BASE + 0x60 + 6)
#define AT91_PIN_PD7 (PIN_BASE + 0x60 + 7)
#define AT91_PIN_PD8 (PIN_BASE + 0x60 + 8)
#define AT91_PIN_PD9 (PIN_BASE + 0x60 + 9)
-
#define AT91_PIN_PD10 (PIN_BASE + 0x60 + 10)
#define AT91_PIN_PD11 (PIN_BASE + 0x60 + 11)
#define AT91_PIN_PD12 (PIN_BASE + 0x60 + 12)
#define AT91_PIN_PD13 (PIN_BASE + 0x60 + 13)
#define AT91_PIN_PD14 (PIN_BASE + 0x60 + 14)
-
#define AT91_PIN_PD15 (PIN_BASE + 0x60 + 15)
#define AT91_PIN_PD16 (PIN_BASE + 0x60 + 16)
#define AT91_PIN_PD17 (PIN_BASE + 0x60 + 17)
#define AT91_PIN_PD18 (PIN_BASE + 0x60 + 18)
#define AT91_PIN_PD19 (PIN_BASE + 0x60 + 19)
-
#define AT91_PIN_PD20 (PIN_BASE + 0x60 + 20)
#define AT91_PIN_PD21 (PIN_BASE + 0x60 + 21)
#define AT91_PIN_PD22 (PIN_BASE + 0x60 + 22)
#define AT91_PIN_PD23 (PIN_BASE + 0x60 + 23)
#define AT91_PIN_PD24 (PIN_BASE + 0x60 + 24)
-
#define AT91_PIN_PD25 (PIN_BASE + 0x60 + 25)
#define AT91_PIN_PD26 (PIN_BASE + 0x60 + 26)
#define AT91_PIN_PD27 (PIN_BASE + 0x60 + 27)
#define AT91_PIN_PD28 (PIN_BASE + 0x60 + 28)
#define AT91_PIN_PD29 (PIN_BASE + 0x60 + 29)
-
#define AT91_PIN_PD30 (PIN_BASE + 0x60 + 30)
#define AT91_PIN_PD31 (PIN_BASE + 0x60 + 31)
+#define AT91_PIN_PE0 (PIN_BASE + 0x80 + 0)
+#define AT91_PIN_PE1 (PIN_BASE + 0x80 + 1)
+#define AT91_PIN_PE2 (PIN_BASE + 0x80 + 2)
+#define AT91_PIN_PE3 (PIN_BASE + 0x80 + 3)
+#define AT91_PIN_PE4 (PIN_BASE + 0x80 + 4)
+#define AT91_PIN_PE5 (PIN_BASE + 0x80 + 5)
+#define AT91_PIN_PE6 (PIN_BASE + 0x80 + 6)
+#define AT91_PIN_PE7 (PIN_BASE + 0x80 + 7)
+#define AT91_PIN_PE8 (PIN_BASE + 0x80 + 8)
+#define AT91_PIN_PE9 (PIN_BASE + 0x80 + 9)
+#define AT91_PIN_PE10 (PIN_BASE + 0x80 + 10)
+#define AT91_PIN_PE11 (PIN_BASE + 0x80 + 11)
+#define AT91_PIN_PE12 (PIN_BASE + 0x80 + 12)
+#define AT91_PIN_PE13 (PIN_BASE + 0x80 + 13)
+#define AT91_PIN_PE14 (PIN_BASE + 0x80 + 14)
+#define AT91_PIN_PE15 (PIN_BASE + 0x80 + 15)
+#define AT91_PIN_PE16 (PIN_BASE + 0x80 + 16)
+#define AT91_PIN_PE17 (PIN_BASE + 0x80 + 17)
+#define AT91_PIN_PE18 (PIN_BASE + 0x80 + 18)
+#define AT91_PIN_PE19 (PIN_BASE + 0x80 + 19)
+#define AT91_PIN_PE20 (PIN_BASE + 0x80 + 20)
+#define AT91_PIN_PE21 (PIN_BASE + 0x80 + 21)
+#define AT91_PIN_PE22 (PIN_BASE + 0x80 + 22)
+#define AT91_PIN_PE23 (PIN_BASE + 0x80 + 23)
+#define AT91_PIN_PE24 (PIN_BASE + 0x80 + 24)
+#define AT91_PIN_PE25 (PIN_BASE + 0x80 + 25)
+#define AT91_PIN_PE26 (PIN_BASE + 0x80 + 26)
+#define AT91_PIN_PE27 (PIN_BASE + 0x80 + 27)
+#define AT91_PIN_PE28 (PIN_BASE + 0x80 + 28)
+#define AT91_PIN_PE29 (PIN_BASE + 0x80 + 29)
+#define AT91_PIN_PE30 (PIN_BASE + 0x80 + 30)
+#define AT91_PIN_PE31 (PIN_BASE + 0x80 + 31)
+
#ifndef __ASSEMBLY__
/* setup setup routines, called from board init or driver probe() */
extern int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup);
diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91/hardware.h
index 9ea5bfe0632..eaaf1c12b75 100644
--- a/include/asm-arm/arch-at91rm9200/hardware.h
+++ b/include/asm-arm/arch-at91/hardware.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/hardware.h
+ * include/asm-arm/arch-at91/hardware.h
*
* Copyright (C) 2003 SAN People
* Copyright (C) 2003 ATMEL
@@ -22,21 +22,23 @@
#include <asm/arch/at91sam9260.h>
#elif defined(CONFIG_ARCH_AT91SAM9261)
#include <asm/arch/at91sam9261.h>
+#elif defined(CONFIG_ARCH_AT91SAM9263)
+#include <asm/arch/at91sam9263.h>
#else
#error "Unsupported AT91 processor"
#endif
/*
- * Remap the peripherals from address 0xFFFA0000 .. 0xFFFFFFFF
- * to 0xFEFA0000 .. 0xFF000000. (384Kb)
+ * Remap the peripherals from address 0xFFF78000 .. 0xFFFFFFFF
+ * to 0xFEF78000 .. 0xFF000000. (5444Kb)
*/
-#define AT91_IO_PHYS_BASE 0xFFFA0000
+#define AT91_IO_PHYS_BASE 0xFFF78000
#define AT91_IO_SIZE (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
#define AT91_IO_VIRT_BASE (0xFF000000 - AT91_IO_SIZE)
/* Convert a physical IO address to virtual IO address */
-#define AT91_IO_P2V(x) ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
+#define AT91_IO_P2V(x) ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
/*
* Virtual to Physical Address mapping for IO devices.
diff --git a/include/asm-arm/arch-at91rm9200/io.h b/include/asm-arm/arch-at91/io.h
index 88fd1bebcef..401f327ec04 100644
--- a/include/asm-arm/arch-at91rm9200/io.h
+++ b/include/asm-arm/arch-at91/io.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/io.h
+ * include/asm-arm/arch-at91/io.h
*
* Copyright (C) 2003 SAN People
*
diff --git a/include/asm-arm/arch-at91rm9200/irqs.h b/include/asm-arm/arch-at91/irqs.h
index c0679eaefaf..1ffa3bb9a9c 100644
--- a/include/asm-arm/arch-at91rm9200/irqs.h
+++ b/include/asm-arm/arch-at91/irqs.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/irqs.h
+ * include/asm-arm/arch-at91/irqs.h
*
* Copyright (C) 2004 SAN People
*
@@ -37,8 +37,8 @@
* IRQ interrupt symbols are the AT91xxx_ID_* symbols
* for IRQs handled directly through the AIC, or else the AT91_PIN_*
* symbols in gpio.h for ones handled indirectly as GPIOs.
- * We make provision for 4 banks of GPIO.
+ * We make provision for 5 banks of GPIO.
*/
-#define NR_IRQS (NR_AIC_IRQS + (4 * 32))
+#define NR_IRQS (NR_AIC_IRQS + (5 * 32))
#endif
diff --git a/include/asm-arm/arch-at91rm9200/memory.h b/include/asm-arm/arch-at91/memory.h
index f985069e6d0..4835d678450 100644
--- a/include/asm-arm/arch-at91rm9200/memory.h
+++ b/include/asm-arm/arch-at91/memory.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/memory.h
+ * include/asm-arm/arch-at91/memory.h
*
* Copyright (C) 2004 SAN People
*
diff --git a/include/asm-arm/arch-at91rm9200/system.h b/include/asm-arm/arch-at91/system.h
index 9c67130603b..6bf846098ea 100644
--- a/include/asm-arm/arch-at91rm9200/system.h
+++ b/include/asm-arm/arch-at91/system.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/system.h
+ * include/asm-arm/arch-at91/system.h
*
* Copyright (C) 2003 SAN People
*
diff --git a/include/asm-arm/arch-at91rm9200/timex.h b/include/asm-arm/arch-at91/timex.h
index faeca45a8d4..f41636d607a 100644
--- a/include/asm-arm/arch-at91rm9200/timex.h
+++ b/include/asm-arm/arch-at91/timex.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/timex.h
+ * include/asm-arm/arch-at91/timex.h
*
* Copyright (C) 2003 SAN People
*
@@ -32,6 +32,11 @@
#define AT91SAM9_MASTER_CLOCK 99300000
#define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16)
+#elif defined(CONFIG_ARCH_AT91SAM9263)
+
+#define AT91SAM9_MASTER_CLOCK 99959500
+#define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16)
+
#endif
#endif
diff --git a/include/asm-arm/arch-at91rm9200/uncompress.h b/include/asm-arm/arch-at91/uncompress.h
index 34b4b93fa01..a193d28304b 100644
--- a/include/asm-arm/arch-at91rm9200/uncompress.h
+++ b/include/asm-arm/arch-at91/uncompress.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/uncompress.h
+ * include/asm-arm/arch-at91/uncompress.h
*
* Copyright (C) 2003 SAN People
*
diff --git a/include/asm-arm/arch-at91rm9200/vmalloc.h b/include/asm-arm/arch-at91/vmalloc.h
index 0a23b8c562b..bb05e70e932 100644
--- a/include/asm-arm/arch-at91rm9200/vmalloc.h
+++ b/include/asm-arm/arch-at91/vmalloc.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-at91rm9200/vmalloc.h
+ * include/asm-arm/arch-at91/vmalloc.h
*
* Copyright (C) 2003 SAN People
*
diff --git a/include/asm-arm/arch-at91rm9200/at91_pdc.h b/include/asm-arm/arch-at91rm9200/at91_pdc.h
deleted file mode 100644
index 79d6e02fa45..00000000000
--- a/include/asm-arm/arch-at91rm9200/at91_pdc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_pdc.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Peripheral Data Controller (PDC) registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * 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.
- */
-
-#ifndef AT91_PDC_H
-#define AT91_PDC_H
-
-#define AT91_PDC_RPR 0x100 /* Receive Pointer Register */
-#define AT91_PDC_RCR 0x104 /* Receive Counter Register */
-#define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */
-#define AT91_PDC_TCR 0x10c /* Transmit Counter Register */
-#define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */
-#define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */
-#define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */
-#define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */
-
-#define AT91_PDC_PTCR 0x120 /* Transfer Control Register */
-#define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */
-#define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */
-#define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */
-#define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */
-
-#define AT91_PDC_PTSR 0x124 /* Transfer Status Register */
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/debug-macro.S b/include/asm-arm/arch-at91rm9200/debug-macro.S
deleted file mode 100644
index 85cdadf2663..00000000000
--- a/include/asm-arm/arch-at91rm9200/debug-macro.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/debug-macro.S
- *
- * Copyright (C) 2003-2005 SAN People
- *
- * Debugging macro include header
- *
- * 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/hardware.h>
-#include <asm/arch/at91_dbgu.h>
-
- .macro addruart,rx
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldreq \rx, =AT91_BASE_SYS @ System peripherals (phys address)
- ldrne \rx, =AT91_VA_BASE_SYS @ System peripherals (virt address)
- .endm
-
- .macro senduart,rd,rx
- strb \rd, [\rx, #AT91_DBGU_THR] @ Write to Transmitter Holding Register
- .endm
-
- .macro waituart,rd,rx
-1001: ldr \rd, [\rx, #AT91_DBGU_SR] @ Read Status Register
- tst \rd, #AT91_DBGU_TXRDY @ DBGU_TXRDY = 1 when ready to transmit
- beq 1001b
- .endm
-
- .macro busyuart,rd,rx
-1001: ldr \rd, [\rx, #AT91_DBGU_SR] @ Read Status Register
- tst \rd, #AT91_DBGU_TXEMPTY @ DBGU_TXEMPTY = 1 when transmission complete
- beq 1001b
- .endm
-
diff --git a/include/asm-arm/arch-at91rm9200/entry-macro.S b/include/asm-arm/arch-at91rm9200/entry-macro.S
deleted file mode 100644
index 57248a79647..00000000000
--- a/include/asm-arm/arch-at91rm9200/entry-macro.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/entry-macro.S
- *
- * Copyright (C) 2003-2005 SAN People
- *
- * Low-level IRQ helper macros for AT91RM9200 platforms
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <asm/hardware.h>
-#include <asm/arch/at91_aic.h>
-
- .macro disable_fiq
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- ldr \base, =(AT91_VA_BASE_SYS) @ base virtual address of SYS peripherals
- ldr \irqnr, [\base, #AT91_AIC_IVR] @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
- ldr \irqstat, [\base, #AT91_AIC_ISR] @ read interrupt source number
- teq \irqstat, #0 @ ISR is 0 when no current interrupt, or spurious interrupt
- streq \tmp, [\base, #AT91_AIC_EOICR] @ not going to be handled further, then ACK it now.
- .endm
-
diff --git a/include/asm-arm/arch-ep93xx/ep93xx-regs.h b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
index 593f562f85c..625c6f0abc0 100644
--- a/include/asm-arm/arch-ep93xx/ep93xx-regs.h
+++ b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
@@ -73,6 +73,11 @@
#define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000)
#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
+#define EP93XX_GPIO_F_INT_TYPE1 EP93XX_GPIO_REG(0x4c)
+#define EP93XX_GPIO_F_INT_TYPE2 EP93XX_GPIO_REG(0x50)
+#define EP93XX_GPIO_F_INT_ACK EP93XX_GPIO_REG(0x54)
+#define EP93XX_GPIO_F_INT_ENABLE EP93XX_GPIO_REG(0x58)
+#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)
#define EP93XX_GPIO_A_INT_TYPE1 EP93XX_GPIO_REG(0x90)
#define EP93XX_GPIO_A_INT_TYPE2 EP93XX_GPIO_REG(0x94)
#define EP93XX_GPIO_A_INT_ACK EP93XX_GPIO_REG(0x98)
diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h
index ae532e304bf..2a8c63638c5 100644
--- a/include/asm-arm/arch-ep93xx/irqs.h
+++ b/include/asm-arm/arch-ep93xx/irqs.h
@@ -67,9 +67,13 @@
#define IRQ_EP93XX_SAI 60
#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff
-#define IRQ_EP93XX_GPIO(x) (64 + (x))
+/*
+ * Map GPIO A0..A7 to irq 64..71, B0..B7 to 72..79, and
+ * F0..F7 to 80..87.
+ */
+#define IRQ_EP93XX_GPIO(x) (64 + (((x) + (((x) >> 2) & 8)) & 0x1f))
-#define NR_EP93XX_IRQS IRQ_EP93XX_GPIO(16)
+#define NR_EP93XX_IRQS (64 + 24)
#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x))
#define EP93XX_BOARD_IRQS 32
diff --git a/include/asm-arm/arch-ep93xx/platform.h b/include/asm-arm/arch-ep93xx/platform.h
index b4a8deb8bde..44eccec2cba 100644
--- a/include/asm-arm/arch-ep93xx/platform.h
+++ b/include/asm-arm/arch-ep93xx/platform.h
@@ -8,7 +8,6 @@ void ep93xx_map_io(void);
void ep93xx_init_irq(void);
void ep93xx_init_time(unsigned long);
void ep93xx_init_devices(void);
-void ep93xx_clock_init(void);
extern struct sys_timer ep93xx_timer;
struct ep93xx_eth_data
diff --git a/include/asm-arm/arch-imx/entry-macro.S b/include/asm-arm/arch-imx/entry-macro.S
index 3b9ef691462..61bb0bdc1b1 100644
--- a/include/asm-arm/arch-imx/entry-macro.S
+++ b/include/asm-arm/arch-imx/entry-macro.S
@@ -13,19 +13,13 @@
.endm
#define AITC_NIVECSR 0x40
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- ldr \irqstat, =IO_ADDRESS(IMX_AITC_BASE)
+ ldr \base, =IO_ADDRESS(IMX_AITC_BASE)
@ Load offset & priority of the highest priority
@ interrupt pending.
- ldr \irqnr, [\irqstat, #AITC_NIVECSR]
+ ldr \irqstat, [\base, #AITC_NIVECSR]
@ Shift off the priority leaving the offset or
- @ "interrupt number"
- mov \irqnr, \irqnr, lsr #16
- ldr \irqstat, =1 @ dummy compare
- ldr \base, =0xFFFF // invalid interrupt
- cmp \irqnr, \base
- bne 1001f
- ldr \irqstat, =0
-1001:
- tst \irqstat, #1 @ to make the condition code = TRUE
+ @ "interrupt number", use arithmetic shift to
+ @ transform illegal source (0xffff) as -1
+ mov \irqnr, \irqstat, asr #16
+ adds \tmp, \irqnr, #1
.endm
-
diff --git a/include/asm-arm/arch-iop32x/io.h b/include/asm-arm/arch-iop32x/io.h
index 12d9ee02cde..5f570a598a3 100644
--- a/include/asm-arm/arch-iop32x/io.h
+++ b/include/asm-arm/arch-iop32x/io.h
@@ -13,10 +13,16 @@
#include <asm/hardware.h>
-#define IO_SPACE_LIMIT 0xffffffff
+extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
+extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size,
+ unsigned long flags);
+extern void __iop3xx_iounmap(void __iomem *addr);
-#define __io(p) ((void __iomem *)(p))
+#define IO_SPACE_LIMIT 0xffffffff
+#define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
#define __mem_pci(a) (a)
+#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
+#define __arch_iounmap(a) __iop3xx_iounmap(a)
#endif
diff --git a/include/asm-arm/arch-iop33x/io.h b/include/asm-arm/arch-iop33x/io.h
index c017402bab9..1bb5071e1fa 100644
--- a/include/asm-arm/arch-iop33x/io.h
+++ b/include/asm-arm/arch-iop33x/io.h
@@ -13,9 +13,16 @@
#include <asm/hardware.h>
+extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
+extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size,
+ unsigned long flags);
+extern void __iop3xx_iounmap(void __iomem *addr);
+
#define IO_SPACE_LIMIT 0xffffffff
-#define __io(p) ((void __iomem *)(p))
+#define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
#define __mem_pci(a) (a)
+#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
+#define __arch_iounmap(a) __iop3xx_iounmap(a)
#endif
diff --git a/include/asm-arm/arch-ixp4xx/avila.h b/include/asm-arm/arch-ixp4xx/avila.h
new file mode 100644
index 00000000000..0dfea0ccd6b
--- /dev/null
+++ b/include/asm-arm/arch-ixp4xx/avila.h
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-ixp4xx/avila.h
+ *
+ * Gateworks Avila platform specific definitions
+ *
+ * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
+ *
+ * Based on ixdp425.h
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (c) MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H__
+#error "Do not include this directly, instead #include <asm/hardware.h>"
+#endif
+
+#define AVILA_SDA_PIN 7
+#define AVILA_SCL_PIN 6
+
+/*
+ * AVILA PCI IRQs
+ */
+#define AVILA_PCI_MAX_DEV 4
+#define LOFT_PCI_MAX_DEV 6
+#define AVILA_PCI_IRQ_LINES 4
+
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define AVILA_PCI_INTA_PIN 11
+#define AVILA_PCI_INTB_PIN 10
+#define AVILA_PCI_INTC_PIN 9
+#define AVILA_PCI_INTD_PIN 8
+
+
diff --git a/include/asm-arm/arch-ixp4xx/hardware.h b/include/asm-arm/arch-ixp4xx/hardware.h
index 6acb69c95ef..88fd0877dcc 100644
--- a/include/asm-arm/arch-ixp4xx/hardware.h
+++ b/include/asm-arm/arch-ixp4xx/hardware.h
@@ -42,6 +42,7 @@ extern unsigned int processor_id;
/* Platform specific details */
#include "ixdp425.h"
+#include "avila.h"
#include "coyote.h"
#include "prpmc1100.h"
#include "nslu2.h"
diff --git a/include/asm-arm/arch-ixp4xx/irqs.h b/include/asm-arm/arch-ixp4xx/irqs.h
index f24b763ca18..e44a563d00f 100644
--- a/include/asm-arm/arch-ixp4xx/irqs.h
+++ b/include/asm-arm/arch-ixp4xx/irqs.h
@@ -79,6 +79,15 @@
#define IRQ_IXDP425_PCI_INTD IRQ_IXP4XX_GPIO8
/*
+ * Gateworks Avila board IRQs
+ */
+#define IRQ_AVILA_PCI_INTA IRQ_IXP4XX_GPIO11
+#define IRQ_AVILA_PCI_INTB IRQ_IXP4XX_GPIO10
+#define IRQ_AVILA_PCI_INTC IRQ_IXP4XX_GPIO9
+#define IRQ_AVILA_PCI_INTD IRQ_IXP4XX_GPIO8
+
+
+/*
* PrPMC1100 Board IRQs
*/
#define IRQ_PRPMC1100_PCI_INTA IRQ_IXP4XX_GPIO11
diff --git a/include/asm-arm/arch-ixp4xx/udc.h b/include/asm-arm/arch-ixp4xx/udc.h
index dbdec36ff0d..79b850a3be4 100644
--- a/include/asm-arm/arch-ixp4xx/udc.h
+++ b/include/asm-arm/arch-ixp4xx/udc.h
@@ -6,3 +6,25 @@
extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info);
+static inline int udc_gpio_to_irq(unsigned gpio)
+{
+ return 0;
+}
+
+static inline void udc_gpio_init_vbus(unsigned gpio)
+{
+}
+
+static inline void udc_gpio_init_pullup(unsigned gpio)
+{
+}
+
+static inline int udc_gpio_get(unsigned gpio)
+{
+ return 0;
+}
+
+static inline void udc_gpio_set(unsigned gpio, int is_on)
+{
+}
+
diff --git a/include/asm-arm/arch-ns9xxx/board.h b/include/asm-arm/arch-ns9xxx/board.h
new file mode 100644
index 00000000000..91dc8fb1027
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/board.h
@@ -0,0 +1,18 @@
+/*
+ * include/asm-arm/arch-ns9xxx/board.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_BOARD_H
+#define __ASM_ARCH_BOARD_H
+
+#include <asm/mach-types.h>
+
+#define board_is_a9m9750dev() (machine_is_cc9p9360dev())
+
+#endif /* ifndef __ASM_ARCH_BOARD_H */
diff --git a/include/asm-arm/arch-ns9xxx/clock.h b/include/asm-arm/arch-ns9xxx/clock.h
new file mode 100644
index 00000000000..4371a485db4
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/clock.h
@@ -0,0 +1,37 @@
+/*
+ * include/asm-arm/arch-ns9xxx/clock.h
+ *
+ * Copyright (C) 2007 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_CLOCK_H
+#define __ASM_ARCH_CLOCK_H
+
+static inline u32 ns9xxx_systemclock(void)
+{
+ /*
+ * This should be a multiple of HZ * TIMERCLOCKSELECT (in time.c)
+ */
+ return 353894400;
+}
+
+static inline const u32 ns9xxx_cpuclock(void)
+{
+ return ns9xxx_systemclock() / 2;
+}
+
+static inline const u32 ns9xxx_ahbclock(void)
+{
+ return ns9xxx_systemclock() / 4;
+}
+
+static inline const u32 ns9xxx_bbusclock(void)
+{
+ return ns9xxx_systemclock() / 8;
+}
+
+#endif /* ifndef __ASM_ARCH_CLOCK_H */
diff --git a/include/asm-arm/arch-ns9xxx/debug-macro.S b/include/asm-arm/arch-ns9xxx/debug-macro.S
new file mode 100644
index 00000000000..b21b93eb2db
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/debug-macro.S
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-ns9xxx/debug-macro.S
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <asm/hardware.h>
+
+#include <asm/arch-ns9xxx/regs-board-a9m9750dev.h>
+
+ .macro addruart,rx
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1
+ ldreq \rx, =NS9XXX_CSxSTAT_PHYS(0)
+ ldrne \rx, =io_p2v(NS9XXX_CSxSTAT_PHYS(0))
+ .endm
+
+#define UART_SHIFT 2
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-ns9xxx/dma.h b/include/asm-arm/arch-ns9xxx/dma.h
new file mode 100644
index 00000000000..a67cbbe009c
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/dma.h
@@ -0,0 +1,14 @@
+/*
+ * include/asm-arm/arch-ns9xxx/dma.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#endif /* ifndef __ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-ns9xxx/entry-macro.S b/include/asm-arm/arch-ns9xxx/entry-macro.S
new file mode 100644
index 00000000000..467a1986d25
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/entry-macro.S
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-ns9xxx/entry-macro.S
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <asm/hardware.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \base, =SYS_ISRADDR
+ ldr \irqstat, [\base, #(SYS_ISA - SYS_ISRADDR)]
+ cmp \irqstat, #0
+ ldrne \irqnr, [\base]
+ .endm
+
+ .macro disable_fiq
+ .endm
diff --git a/include/asm-arm/arch-ns9xxx/hardware.h b/include/asm-arm/arch-ns9xxx/hardware.h
new file mode 100644
index 00000000000..6819da7c48d
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/hardware.h
@@ -0,0 +1,67 @@
+/*
+ * include/asm-arm/arch-ns9xxx/hardware.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/memory.h>
+
+/*
+ * NetSilicon NS9xxx internal mapping:
+ *
+ * physical <--> virtual
+ * 0x90000000 - 0x906fffff <--> 0xf9000000 - 0xf96fffff
+ * 0xa0100000 - 0xa0afffff <--> 0xfa100000 - 0xfaafffff
+ */
+#define io_p2v(x) (0xf0000000 \
+ + (((x) & 0xf0000000) >> 4) \
+ + ((x) & 0x00ffffff))
+
+#define io_v2p(x) ((((x) & 0x0f000000) << 4) \
+ + ((x) & 0x00ffffff))
+
+#define __REGBIT(bit) ((u32)1 << (bit))
+#define __REGBITS(hbit, lbit) ((((u32)1 << ((hbit) - (lbit) + 1)) - 1) << (lbit))
+#define __REGVAL(mask, value) (((value) * ((mask) & (-(mask))) & (mask)))
+
+#ifndef __ASSEMBLY__
+
+# define __REG(x) (*((volatile u32 *)io_p2v((x))))
+# define __REG2(x, y) (*((volatile u32 *)io_p2v((x)) + (y)))
+
+# define __REGB(x) (*((volatile u8 *)io_p2v((x))))
+# define __REGB2(x) (*((volatile u8 *)io_p2v((x)) + (y)))
+
+# define REGSET(var, reg, field, value) \
+ ((var) = (((var) \
+ & ~(reg ## _ ## field & \
+ ~ reg ## _ ## field ## _ ## value)) \
+ | (reg ## _ ## field ## _ ## value)))
+
+# define REGSETIM(var, reg, field, value) \
+ ((var) = (((var) \
+ & ~(reg ## _ ## field & \
+ ~(__REGVAL(reg ## _ ## field, value)))) \
+ | (__REGVAL(reg ## _ ## field, value))))
+
+# define REGGET(reg, field) \
+ ((reg & (reg ## _ ## field)) / (field & (-field)))
+
+#else
+
+# define __REG(x) io_p2v(x)
+# define __REG2(x, y) io_p2v((x) + (y))
+
+# define __REGB(x) __REG((x))
+# define __REGB2(x, y) __REG2((x), (y))
+
+#endif
+
+#endif /* ifndef __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-ns9xxx/io.h b/include/asm-arm/arch-ns9xxx/io.h
new file mode 100644
index 00000000000..6f82d28af12
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/io.h
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-ns9xxx/io.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_IO_H
+#define __ASM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff /* XXX */
+
+#define __io(a) ((void __iomem *)(a))
+#define __mem_pci(a) (a)
+#define __mem_isa(a) (IO_BASE + (a))
+
+#endif /* ifndef __ASM_ARCH_IO_H */
diff --git a/include/asm-arm/arch-ns9xxx/irqs.h b/include/asm-arm/arch-ns9xxx/irqs.h
new file mode 100644
index 00000000000..25d8d28b27f
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/irqs.h
@@ -0,0 +1,85 @@
+/*
+ * include/asm-arm/arch-ns9xxx/irqs.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define IRQ_WATCHDOG 0
+#define IRQ_AHBBUSERR 1
+#define IRQ_BBUSAGG 2
+/* irq 3 is reserved for NS9360 */
+#define IRQ_ETHRX 4
+#define IRQ_ETHTX 5
+#define IRQ_ETHPHY 6
+#define IRQ_LCD 7
+#define IRQ_SERBRX 8
+#define IRQ_SERBTX 9
+#define IRQ_SERARX 10
+#define IRQ_SERATX 11
+#define IRQ_SERCRX 12
+#define IRQ_SERCTX 13
+#define IRQ_I2C 14
+#define IRQ_BBUSDMA 15
+#define IRQ_TIMER0 16
+#define IRQ_TIMER1 17
+#define IRQ_TIMER2 18
+#define IRQ_TIMER3 19
+#define IRQ_TIMER4 20
+#define IRQ_TIMER5 21
+#define IRQ_TIMER6 22
+#define IRQ_TIMER7 23
+#define IRQ_RTC 24
+#define IRQ_USBHOST 25
+#define IRQ_USBDEVICE 26
+#define IRQ_IEEE1284 27
+#define IRQ_EXT0 28
+#define IRQ_EXT1 29
+#define IRQ_EXT2 30
+#define IRQ_EXT3 31
+
+#define BBUS_IRQ(irq) (32 + irq)
+
+#define IRQ_BBUS_DMA BBUS_IRQ(0)
+#define IRQ_BBUS_SERBRX BBUS_IRQ(2)
+#define IRQ_BBUS_SERBTX BBUS_IRQ(3)
+#define IRQ_BBUS_SERARX BBUS_IRQ(4)
+#define IRQ_BBUS_SERATX BBUS_IRQ(5)
+#define IRQ_BBUS_SERCRX BBUS_IRQ(6)
+#define IRQ_BBUS_SERCTX BBUS_IRQ(7)
+#define IRQ_BBUS_SERDRX BBUS_IRQ(8)
+#define IRQ_BBUS_SERDTX BBUS_IRQ(9)
+#define IRQ_BBUS_I2C BBUS_IRQ(10)
+#define IRQ_BBUS_1284 BBUS_IRQ(11)
+#define IRQ_BBUS_UTIL BBUS_IRQ(12)
+#define IRQ_BBUS_RTC BBUS_IRQ(13)
+#define IRQ_BBUS_USBHST BBUS_IRQ(14)
+#define IRQ_BBUS_USBDEV BBUS_IRQ(15)
+#define IRQ_BBUS_AHBDMA1 BBUS_IRQ(24)
+#define IRQ_BBUS_AHBDMA2 BBUS_IRQ(25)
+
+/*
+ * these Interrupts are specific for the a9m9750dev board.
+ * They are generated by an FPGA that interrupts the CPU on
+ * IRQ_EXT2
+ */
+#define FPGA_IRQ(irq) (64 + irq)
+
+#define IRQ_FPGA_UARTA FPGA_IRQ(0)
+#define IRQ_FPGA_UARTB FPGA_IRQ(1)
+#define IRQ_FPGA_UARTC FPGA_IRQ(2)
+#define IRQ_FPGA_UARTD FPGA_IRQ(3)
+#define IRQ_FPGA_TOUCH FPGA_IRQ(4)
+#define IRQ_FPGA_CF FPGA_IRQ(5)
+#define IRQ_FPGA_CAN0 FPGA_IRQ(6)
+#define IRQ_FPGA_CAN1 FPGA_IRQ(7)
+
+#define NR_IRQS 72
+
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/include/asm-arm/arch-ns9xxx/memory.h b/include/asm-arm/arch-ns9xxx/memory.h
new file mode 100644
index 00000000000..ce1343e593e
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/memory.h
@@ -0,0 +1,27 @@
+/*
+ * include/asm-arm/arch-ns9xxx/memory.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+*/
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/* x in [0..3] */
+#define NS9XXX_CSxSTAT_PHYS(x) UL(((x) + 4) << 28)
+
+#define NS9XXX_CS0STAT_LENGTH UL(0x1000)
+#define NS9XXX_CS1STAT_LENGTH UL(0x1000)
+#define NS9XXX_CS2STAT_LENGTH UL(0x1000)
+#define NS9XXX_CS3STAT_LENGTH UL(0x1000)
+
+#define PHYS_OFFSET UL(0x00000000)
+
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#endif
diff --git a/include/asm-arm/arch-ns9xxx/processor.h b/include/asm-arm/arch-ns9xxx/processor.h
new file mode 100644
index 00000000000..716c106ac0b
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/processor.h
@@ -0,0 +1,18 @@
+/*
+ * include/asm-arm/arch-ns9xxx/processor.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_PROCESSOR_H
+#define __ASM_ARCH_PROCESSOR_H
+
+#include <asm/mach-types.h>
+
+#define processor_is_ns9360() (machine_is_cc9p9360dev())
+
+#endif /* ifndef __ASM_ARCH_PROCESSOR_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-bbu.h b/include/asm-arm/arch-ns9xxx/regs-bbu.h
new file mode 100644
index 00000000000..e2626954624
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/regs-bbu.h
@@ -0,0 +1,21 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-bbu.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSBBU_H
+#define __ASM_ARCH_REGSBBU_H
+
+#include <asm/hardware.h>
+
+/* BBus Utility */
+
+/* GPIO Configuration Register */
+#define BBU_GC(x) __REG2(0x9060000c, (x))
+
+#endif /* ifndef __ASM_ARCH_REGSBBU_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h b/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h
new file mode 100644
index 00000000000..c3dc532dd20
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h
@@ -0,0 +1,24 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-board-a9m9750dev.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSBOARDA9M9750_H
+#define __ASM_ARCH_REGSBOARDA9M9750_H
+
+#include <asm/hardware.h>
+
+#define FPGA_UARTA_BASE io_p2v(NS9XXX_CSxSTAT_PHYS(0))
+#define FPGA_UARTB_BASE io_p2v(NS9XXX_CSxSTAT_PHYS(0) + 0x08)
+#define FPGA_UARTC_BASE io_p2v(NS9XXX_CSxSTAT_PHYS(0) + 0x10)
+#define FPGA_UARTD_BASE io_p2v(NS9XXX_CSxSTAT_PHYS(0) + 0x18)
+
+#define FPGA_IER __REGB(NS9XXX_CSxSTAT_PHYS(0) + 0x50)
+#define FPGA_ISR __REGB(NS9XXX_CSxSTAT_PHYS(0) + 0x60)
+
+#endif /* ifndef __ASM_ARCH_REGSBOARDA9M9750_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-mem.h b/include/asm-arm/arch-ns9xxx/regs-mem.h
new file mode 100644
index 00000000000..8ed8448767b
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/regs-mem.h
@@ -0,0 +1,135 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-mem.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSMEM_H
+#define __ASM_ARCH_REGSMEM_H
+
+#include <asm/hardware.h>
+
+/* Memory Module */
+
+/* Control register */
+#define MEM_CTRL __REG(0xa0700000)
+
+/* Status register */
+#define MEM_STAT __REG(0xa0700004)
+
+/* Configuration register */
+#define MEM_CONF __REG(0xa0700008)
+
+/* Dynamic Memory Control register */
+#define MEM_DMCTRL __REG(0xa0700020)
+
+/* Dynamic Memory Refresh Timer */
+#define MEM_DMRT __REG(0xa0700024)
+
+/* Dynamic Memory Read Configuration register */
+#define MEM_DMRC __REG(0xa0700028)
+
+/* Dynamic Memory Precharge Command Period (tRP) */
+#define MEM_DMPCP __REG(0xa0700030)
+
+/* Dynamic Memory Active to Precharge Command Period (tRAS) */
+#define MEM_DMAPCP __REG(0xa0700034)
+
+/* Dynamic Memory Self-Refresh Exit Time (tSREX) */
+#define MEM_DMSRET __REG(0xa0700038)
+
+/* Dynamic Memory Last Data Out to Active Time (tAPR) */
+#define MEM_DMLDOAT __REG(0xa070003c)
+
+/* Dynamic Memory Data-in to Active Command Time (tDAL or TAPW) */
+#define MEM_DMDIACT __REG(0xa0700040)
+
+/* Dynamic Memory Write Recovery Time (tWR, tDPL, tRWL, tRDL) */
+#define MEM_DMWRT __REG(0xa0700044)
+
+/* Dynamic Memory Active to Active Command Period (tRC) */
+#define MEM_DMAACP __REG(0xa0700048)
+
+/* Dynamic Memory Auto Refresh Period, and Auto Refresh to Active Command Period (tRFC) */
+#define MEM_DMARP __REG(0xa070004c)
+
+/* Dynamic Memory Exit Self-Refresh to Active Command (tXSR) */
+#define MEM_DMESRAC __REG(0xa0700050)
+
+/* Dynamic Memory Active Bank A to Active B Time (tRRD) */
+#define MEM_DMABAABT __REG(0xa0700054)
+
+/* Dynamic Memory Load Mode register to Active Command Time (tMRD) */
+#define MEM_DMLMACT __REG(0xa0700058)
+
+/* Static Memory Extended Wait */
+#define MEM_SMEW __REG(0xa0700080)
+
+/* Dynamic Memory Configuration Register x */
+#define MEM_DMCONF(x) __REG2(0xa0700100, (x) << 3)
+
+/* Dynamic Memory RAS and CAS Delay x */
+#define MEM_DMRCD(x) __REG2(0xa0700104, (x) << 3)
+
+/* Static Memory Configuration Register x */
+#define MEM_SMC(x) __REG2(0xa0700200, (x) << 3)
+
+/* Static Memory Configuration Register x: Write protect */
+#define MEM_SMC_WSMC __REGBIT(20)
+#define MEM_SMC_WSMC_OFF __REGVAL(MEM_SMC_WSMC, 0)
+#define MEM_SMC_WSMC_ON __REGVAL(MEM_SMC_WSMC, 1)
+
+/* Static Memory Configuration Register x: Buffer enable */
+#define MEM_SMC_BSMC __REGBIT(19)
+#define MEM_SMC_BSMC_OFF __REGVAL(MEM_SMC_BSMC, 0)
+#define MEM_SMC_BSMC_ON __REGVAL(MEM_SMC_BSMC, 1)
+
+/* Static Memory Configuration Register x: Extended Wait */
+#define MEM_SMC_EW __REGBIT(8)
+#define MEM_SMC_EW_OFF __REGVAL(MEM_SMC_EW, 0)
+#define MEM_SMC_EW_ON __REGVAL(MEM_SMC_EW, 1)
+
+/* Static Memory Configuration Register x: Byte lane state */
+#define MEM_SMC_PB __REGBIT(7)
+#define MEM_SMC_PB_0 __REGVAL(MEM_SMC_PB, 0)
+#define MEM_SMC_PB_1 __REGVAL(MEM_SMC_PB, 1)
+
+/* Static Memory Configuration Register x: Chip select polarity */
+#define MEM_SMC_PC __REGBIT(6)
+#define MEM_SMC_PC_AL __REGVAL(MEM_SMC_PC, 0)
+#define MEM_SMC_PC_AH __REGVAL(MEM_SMC_PC, 1)
+
+/* static memory configuration register x: page mode*/
+#define MEM_SMC_PM __REGBIT(3)
+#define MEM_SMC_PM_DIS __REGVAL(MEM_SMC_PM, 0)
+#define MEM_SMC_PM_ASYNC __REGVAL(MEM_SMC_PM, 1)
+
+/* static memory configuration register x: Memory width */
+#define MEM_SMC_MW __REGBITS(1, 0)
+#define MEM_SMC_MW_8 __REGVAL(MEM_SMC_MW, 0)
+#define MEM_SMC_MW_16 __REGVAL(MEM_SMC_MW, 1)
+#define MEM_SMC_MW_32 __REGVAL(MEM_SMC_MW, 2)
+
+/* Static Memory Write Enable Delay x */
+#define MEM_SMWED(x) __REG2(0xa0700204, (x) << 3)
+
+/* Static Memory Output Enable Delay x */
+#define MEM_SMOED(x) __REG2(0xa0700208, (x) << 3)
+
+/* Static Memory Read Delay x */
+#define MEM_SMRD(x) __REG2(0xa070020c, (x) << 3)
+
+/* Static Memory Page Mode Read Delay 0 */
+#define MEM_SMPMRD(x) __REG2(0xa0700210, (x) << 3)
+
+/* Static Memory Write Delay */
+#define MEM_SMWD(x) __REG2(0xa0700214, (x) << 3)
+
+/* Static Memory Turn Round Delay x */
+#define MEM_SWT(x) __REG2(0xa0700218, (x) << 3)
+
+#endif /* ifndef __ASM_ARCH_REGSMEM_H */
diff --git a/include/asm-arm/arch-ns9xxx/regs-sys.h b/include/asm-arm/arch-ns9xxx/regs-sys.h
new file mode 100644
index 00000000000..8162a50bb27
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/regs-sys.h
@@ -0,0 +1,157 @@
+/*
+ * include/asm-arm/arch-ns9xxx/regs-sys.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSSYS_H
+#define __ASM_ARCH_REGSSYS_H
+
+#include <asm/hardware.h>
+
+/* System Control Module */
+
+/* AHB Arbiter Gen Configuration */
+#define SYS_AHBAGENCONF __REG(0xa0900000)
+
+/* BRC */
+#define SYS_BRC(x) __REG2(0xa0900004, (x))
+
+/* Timer x Reload Count register */
+#define SYS_TRC(x) __REG2(0xa0900044, (x))
+
+/* Timer x Read register */
+#define SYS_TR(x) __REG2(0xa0900084, (x))
+
+/* Interrupt Vector Address Register Level x */
+#define SYS_IVA(x) __REG2(0xa09000c4, (x))
+
+/* Interrupt Configuration registers */
+#define SYS_IC(x) __REG2(0xa0900144, (x))
+
+/* ISRADDR */
+#define SYS_ISRADDR __REG(0xa0900164)
+
+/* Interrupt Status Active */
+#define SYS_ISA __REG(0xa0900168)
+
+/* Interrupt Status Raw */
+#define SYS_ISR __REG(0xa090016c)
+
+/* Timer Interrupt Status register */
+#define SYS_TIS __REG(0xa0900170)
+
+/* PLL Configuration register */
+#define SYS_PLL __REG(0xa0900188)
+
+/* PLL Configuration register: PLL SW change */
+#define SYS_PLL_SWC __REGBIT(15)
+#define SYS_PLL_SWC_NO __REGVAL(SYS_PLL_SWC, 0)
+#define SYS_PLL_SWC_YES __REGVAL(SYS_PLL_SWC, 1)
+
+/* Timer x Control register */
+#define SYS_TC(x) __REG2(0xa0900190, (x))
+
+/* Timer x Control register: Timer enable */
+#define SYS_TCx_TEN __REGBIT(15)
+#define SYS_TCx_TEN_DIS __REGVAL(SYS_TCx_TEN, 1)
+#define SYS_TCx_TEN_EN __REGVAL(SYS_TCx_TEN, 1)
+
+/* Timer x Control register: CPU debug mode */
+#define SYS_TCx_TDBG __REGBIT(10)
+#define SYS_TCx_TDBG_CONT __REGVAL(SYS_TCx_TDBG, 0)
+#define SYS_TCx_TDBG_STOP __REGVAL(SYS_TCx_TDBG, 1)
+
+/* Timer x Control register: Interrupt clear */
+#define SYS_TCx_INTC __REGBIT(9)
+#define SYS_TCx_INTC_UNSET __REGVAL(SYS_TCx_INTC, 0)
+#define SYS_TCx_INTC_SET __REGVAL(SYS_TCx_INTC, 1)
+
+/* Timer x Control register: Timer clock select */
+#define SYS_TCx_TLCS __REGBITS(8, 6)
+#define SYS_TCx_TLCS_CPU __REGVAL(SYS_TCx_TLCS, 0) /* CPU clock */
+#define SYS_TCx_TLCS_DIV2 __REGVAL(SYS_TCx_TLCS, 1) /* CPU clock / 2 */
+#define SYS_TCx_TLCS_DIV4 __REGVAL(SYS_TCx_TLCS, 2) /* CPU clock / 4 */
+#define SYS_TCx_TLCS_DIV8 __REGVAL(SYS_TCx_TLCS, 3) /* CPU clock / 8 */
+#define SYS_TCx_TLCS_DIV16 __REGVAL(SYS_TCx_TLCS, 4) /* CPU clock / 16 */
+#define SYS_TCx_TLCS_DIV32 __REGVAL(SYS_TCx_TLCS, 5) /* CPU clock / 32 */
+#define SYS_TCx_TLCS_DIV64 __REGVAL(SYS_TCx_TLCS, 6) /* CPU clock / 64 */
+#define SYS_TCx_TLCS_EXT __REGVAL(SYS_TCx_TLCS, 7)
+
+/* Timer x Control register: Timer mode */
+#define SYS_TCx_TM __REGBITS(5, 4)
+#define SYS_TCx_TM_IEE __REGVAL(SYS_TCx_TM, 0) /* Internal timer or external event */
+#define SYS_TCx_TM_ELL __REGVAL(SYS_TCx_TM, 1) /* External low-level, gated timer */
+#define SYS_TCx_TM_EHL __REGVAL(SYS_TCx_TM, 2) /* External high-level, gated timer */
+#define SYS_TCx_TM_CONCAT __REGVAL(SYS_TCx_TM, 3) /* Concatenate the lower timer. */
+
+/* Timer x Control register: Interrupt select */
+#define SYS_TCx_INTS __REGBIT(3)
+#define SYS_TCx_INTS_DIS __REGVAL(SYS_TCx_INTS, 0)
+#define SYS_TCx_INTS_EN __REGVAL(SYS_TCx_INTS, 1)
+
+/* Timer x Control register: Up/down select */
+#define SYS_TCx_UDS __REGBIT(2)
+#define SYS_TCx_UDS_UP __REGVAL(SYS_TCx_UDS, 0)
+#define SYS_TCx_UDS_DOWN __REGVAL(SYS_TCx_UDS, 1)
+
+/* Timer x Control register: 32- or 16-bit timer */
+#define SYS_TCx_TSZ __REGBIT(1)
+#define SYS_TCx_TSZ_16 __REGVAL(SYS_TCx_TSZ, 0)
+#define SYS_TCx_TSZ_32 __REGVAL(SYS_TCx_TSZ, 1)
+
+/* Timer x Control register: Reload enable */
+#define SYS_TCx_REN __REGBIT(0)
+#define SYS_TCx_REN_DIS __REGVAL(SYS_TCx_REN, 0)
+#define SYS_TCx_REN_EN __REGVAL(SYS_TCx_REN, 1)
+
+/* System Memory Chip Select x Dynamic Memory Base */
+#define SYS_SMCSDMB(x) __REG2(0xa09001d0, (x) << 1)
+
+/* System Memory Chip Select x Dynamic Memory Mask */
+#define SYS_SMCSDMM(x) __REG2(0xa09001d4, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Base */
+#define SYS_SMCSSMB(x) __REG2(0xa09001f0, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Base: Chip select x base */
+#define SYS_SMCSSMB_CSxB __REGBITS(31, 12)
+
+/* System Memory Chip Select x Static Memory Mask */
+#define SYS_SMCSSMM(x) __REG2(0xa09001f4, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Mask: Chip select x mask */
+#define SYS_SMCSSMM_CSxM __REGBITS(31, 12)
+
+/* System Memory Chip Select x Static Memory Mask: Chip select x enable */
+#define SYS_SMCSSMM_CSEx __REGBIT(0)
+#define SYS_SMCSSMM_CSEx_DIS __REGVAL(SYS_SMCSSMM_CSEx, 0)
+#define SYS_SMCSSMM_CSEx_EN __REGVAL(SYS_SMCSSMM_CSEx, 1)
+
+/* General purpose, user-defined ID register */
+#define SYS_GENID __REG(0xa0900210)
+
+/* External Interrupt x Control register */
+#define SYS_EIC(x) __REG2(0xa0900214, (x))
+
+/* External Interrupt x Control register: Status */
+#define SYS_EIC_STS __REGBIT(3)
+
+/* External Interrupt x Control register: Clear */
+#define SYS_EIC_CLR __REGBIT(2)
+
+/* External Interrupt x Control register: Polarity */
+#define SYS_EIC_PLTY __REGBIT(1)
+#define SYS_EIC_PLTY_AH __REGVAL(SYS_EIC_PLTY, 0)
+#define SYS_EIC_PLTY_AL __REGVAL(SYS_EIC_PLTY, 1)
+
+/* External Interrupt x Control register: Level edge */
+#define SYS_EIC_LVEDG __REGBIT(0)
+#define SYS_EIC_LVEDG_LEVEL __REGVAL(SYS_EIC_LVEDG, 0)
+#define SYS_EIC_LVEDG_EDGE __REGVAL(SYS_EIC_LVEDG, 1)
+
+#endif /* ifndef __ASM_ARCH_REGSSYS_H */
diff --git a/include/asm-arm/arch-ns9xxx/system.h b/include/asm-arm/arch-ns9xxx/system.h
new file mode 100644
index 00000000000..e3cd4d31b3f
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/system.h
@@ -0,0 +1,34 @@
+/*
+ * include/asm-arm/arch-ns9xxx/system.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/proc-fns.h>
+#include <asm/arch-ns9xxx/regs-sys.h>
+#include <asm/mach-types.h>
+
+static inline void arch_idle(void)
+{
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+ u32 reg;
+
+ reg = SYS_PLL >> 16;
+ REGSET(reg, SYS_PLL, SWC, YES);
+ SYS_PLL = reg;
+
+ BUG();
+}
+
+#endif /* ifndef __ASM_ARCH_SYSTEM_H */
diff --git a/include/asm-arm/arch-ns9xxx/timex.h b/include/asm-arm/arch-ns9xxx/timex.h
new file mode 100644
index 00000000000..f776cbd2622
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/timex.h
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-ns9xxx/timex.h
+ *
+ * Copyright (C) 2005-2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+/*
+ * value for CLOCK_TICK_RATE stolen from include/asm-arm/arch-s3c2410/timex.h.
+ * See there for an explanation.
+ */
+#define CLOCK_TICK_RATE 12000000
+
+#endif /* ifndef __ASM_ARCH_TIMEX_H */
diff --git a/include/asm-arm/arch-ns9xxx/uncompress.h b/include/asm-arm/arch-ns9xxx/uncompress.h
new file mode 100644
index 00000000000..961ca7dc995
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/uncompress.h
@@ -0,0 +1,35 @@
+/*
+ * include/asm-arm/arch-ns9xxx/uncompress.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+static void putc(char c)
+{
+ volatile u8 *base = (volatile u8 *)0x40000000;
+ int t = 0x10000;
+
+ do {
+ if (base[5] & 0x20) {
+ base[0] = c;
+ break;
+ }
+ } while (--t);
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+static void flush(void)
+{
+ /* nothing */
+}
+
+#endif /* ifndef __ASM_ARCH_UNCOMPRESS_H */
diff --git a/include/asm-arm/arch-ns9xxx/vmalloc.h b/include/asm-arm/arch-ns9xxx/vmalloc.h
new file mode 100644
index 00000000000..2f3cb6f6be2
--- /dev/null
+++ b/include/asm-arm/arch-ns9xxx/vmalloc.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-arm/arch-ns9xxx/vmalloc.h
+ *
+ * Copyright (C) 2006 by Digi International 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 License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END (0xf0000000)
+
+#endif /* ifndef __ASM_ARCH_VMALLOC_H */
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index e24f6b6c79a..aec835b6f05 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -463,9 +463,6 @@
* Serial Audio Controller
*/
-/* FIXME: This clash with SA1111 defines */
-#ifndef _ASM_ARCH_SA1111
-
#define SACR0 __REG(0x40400000) /* Global Control Register */
#define SACR1 __REG(0x40400004) /* Serial Audio I 2 S/MSB-Justified Control Register */
#define SASR0 __REG(0x4040000C) /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
@@ -474,8 +471,8 @@
#define SADIV __REG(0x40400060) /* Audio Clock Divider Register. */
#define SADR __REG(0x40400080) /* Serial Audio Data Register (TX and RX FIFO access Register). */
-#define SACR0_RFTH(x) (x << 12) /* Rx FIFO Interrupt or DMA Trigger Threshold */
-#define SACR0_TFTH(x) (x << 8) /* Tx FIFO Interrupt or DMA Trigger Threshold */
+#define SACR0_RFTH(x) ((x) << 12) /* Rx FIFO Interrupt or DMA Trigger Threshold */
+#define SACR0_TFTH(x) ((x) << 8) /* Tx FIFO Interrupt or DMA Trigger Threshold */
#define SACR0_STRF (1 << 5) /* FIFO Select for EFWR Special Function */
#define SACR0_EFWR (1 << 4) /* Enable EFWR Function */
#define SACR0_RST (1 << 3) /* FIFO, i2s Register Reset */
@@ -503,8 +500,6 @@
#define SAIMR_RFS (1 << 4) /* Enable Rx FIFO Service Interrupt */
#define SAIMR_TFS (1 << 3) /* Enable Tx FIFO Service Interrupt */
-#endif
-
/*
* AC97 Controller registers
*/
@@ -1682,15 +1677,18 @@
#define SSSR_PINT (1 << 18) /* Peripheral Trailing Byte Interrupt */
#define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */
-#define SSPSP_DMYSTOP(x) (x << 23) /* Dummy Stop */
-#define SSPSP_SFRMWDTH(x) (x << 16) /* Serial Frame Width */
-#define SSPSP_SFRMDLY(x) (x << 9) /* Serial Frame Delay */
-#define SSPSP_DMYSTRT(x) (x << 7) /* Dummy Start */
-#define SSPSP_STRTDLY(x) (x << 4) /* Start Delay */
+#define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */
+#define SSPSP_SFRMWDTH(x) ((x) << 16) /* Serial Frame Width */
+#define SSPSP_SFRMDLY(x) ((x) << 9) /* Serial Frame Delay */
+#define SSPSP_DMYSTRT(x) ((x) << 7) /* Dummy Start */
+#define SSPSP_STRTDLY(x) ((x) << 4) /* Start Delay */
#define SSPSP_ETDS (1 << 3) /* End of Transfer data State */
#define SSPSP_SFRMP (1 << 2) /* Serial Frame Polarity */
-#define SSPSP_SCMODE(x) (x << 0) /* Serial Bit Rate Clock Mode */
+#define SSPSP_SCMODE(x) ((x) << 0) /* Serial Bit Rate Clock Mode */
+#define SSACD_SCDB (1 << 3) /* SSPSYSCLK Divider Bypass */
+#define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */
+#define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */
#define SSCR0_P1 __REG(0x41000000) /* SSP Port 1 Control Register 0 */
#define SSCR1_P1 __REG(0x41000004) /* SSP Port 1 Control Register 1 */
diff --git a/include/asm-arm/arch-pxa/udc.h b/include/asm-arm/arch-pxa/udc.h
index 646480d3725..8bc6f9c3e3e 100644
--- a/include/asm-arm/arch-pxa/udc.h
+++ b/include/asm-arm/arch-pxa/udc.h
@@ -9,3 +9,33 @@
extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
+static inline int udc_gpio_to_irq(unsigned gpio)
+{
+ return IRQ_GPIO(gpio & GPIO_MD_MASK_NR);
+}
+
+static inline void udc_gpio_init_vbus(unsigned gpio)
+{
+ pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_IN);
+}
+
+static inline void udc_gpio_init_pullup(unsigned gpio)
+{
+ pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_OUT | GPIO_DFLT_LOW);
+}
+
+static inline int udc_gpio_get(unsigned gpio)
+{
+ return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
+}
+
+static inline void udc_gpio_set(unsigned gpio, int is_on)
+{
+ int mask = GPIO_bit(gpio);
+
+ if (is_on)
+ GPSR(gpio) = mask;
+ else
+ GPCR(gpio) = mask;
+}
+
diff --git a/include/asm-arm/arch-realview/hardware.h b/include/asm-arm/arch-realview/hardware.h
index 9ca76dc3a7a..aa78fe087ab 100644
--- a/include/asm-arm/arch-realview/hardware.h
+++ b/include/asm-arm/arch-realview/hardware.h
@@ -26,7 +26,7 @@
#include <asm/arch/platform.h>
/* macro to get at IO space when running virtually */
-#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
+#define IO_ADDRESS(x) ((((x) & 0x0effffff) | (((x) >> 4) & 0x0f000000)) + 0xf0000000)
#define __io_address(n) __io(IO_ADDRESS(n))
#endif
diff --git a/include/asm-arm/arch-realview/irqs.h b/include/asm-arm/arch-realview/irqs.h
index c16223c9588..5a5db56f86b 100644
--- a/include/asm-arm/arch-realview/irqs.h
+++ b/include/asm-arm/arch-realview/irqs.h
@@ -65,6 +65,21 @@
#define IRQ_AACI (IRQ_GIC_START + INT_AACI)
#define IRQ_ETH (IRQ_GIC_START + INT_ETH)
#define IRQ_USB (IRQ_GIC_START + INT_USB)
+#define IRQ_PMU_CPU0 (IRQ_GIC_START + INT_PMU_CPU0)
+#define IRQ_PMU_CPU1 (IRQ_GIC_START + INT_PMU_CPU1)
+#define IRQ_PMU_CPU2 (IRQ_GIC_START + INT_PMU_CPU2)
+#define IRQ_PMU_CPU3 (IRQ_GIC_START + INT_PMU_CPU3)
+#define IRQ_PMU_SCU0 (IRQ_GIC_START + INT_PMU_SCU0)
+#define IRQ_PMU_SCU1 (IRQ_GIC_START + INT_PMU_SCU1)
+#define IRQ_PMU_SCU2 (IRQ_GIC_START + INT_PMU_SCU2)
+#define IRQ_PMU_SCU3 (IRQ_GIC_START + INT_PMU_SCU3)
+#define IRQ_PMU_SCU4 (IRQ_GIC_START + INT_PMU_SCU4)
+#define IRQ_PMU_SCU5 (IRQ_GIC_START + INT_PMU_SCU5)
+#define IRQ_PMU_SCU6 (IRQ_GIC_START + INT_PMU_SCU6)
+#define IRQ_PMU_SCU7 (IRQ_GIC_START + INT_PMU_SCU7)
+
+#define IRQ_EB_IRQ1 (IRQ_GIC_START + INT_EB_IRQ1)
+#define IRQ_EB_IRQ2 (IRQ_GIC_START + INT_EB_IRQ2)
#define IRQMASK_WDOGINT INTMASK_WDOGINT
#define IRQMASK_SOFTINT INTMASK_SOFTINT
@@ -103,4 +118,4 @@
#define IRQMASK_ETH INTMASK_ETH
#define IRQMASK_USB INTMASK_USB
-#define NR_IRQS (IRQ_GIC_START + 64)
+#define NR_IRQS (IRQ_GIC_START + 96)
diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h
index 18d7c18b738..6e0eab95a3a 100644
--- a/include/asm-arm/arch-realview/platform.h
+++ b/include/asm-arm/arch-realview/platform.h
@@ -207,11 +207,25 @@
#define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */
#define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */
#else
+#ifdef CONFIG_REALVIEW_MPCORE_REVB
#define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */
#define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */
#define REALVIEW_TWD_BASE 0x10100700
#define REALVIEW_TWD_SIZE 0x00000100
#define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */
+#define REALVIEW_MPCORE_L220_BASE 0x10102000 /* L220 registers */
+#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */
+#else
+#define REALVIEW_MPCORE_SCU_BASE 0x1F000000 /* SCU registers */
+#define REALVIEW_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */
+#define REALVIEW_TWD_BASE 0x1F000700
+#define REALVIEW_TWD_SIZE 0x00000100
+#define REALVIEW_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */
+#define REALVIEW_MPCORE_L220_BASE 0x1F002000 /* L220 registers */
+#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */
+#endif
+#define REALVIEW_GIC1_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */
+#define REALVIEW_GIC1_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */
#endif
#define REALVIEW_SMC_BASE 0x10080000 /* SMC */
/* Reserved 0x10090000 - 0x100EFFFF */
@@ -306,7 +320,11 @@
#define INT_USB 29 /* USB controller */
#define INT_TSPENINT 30 /* Touchscreen pen */
#define INT_TSKPADINT 31 /* Touchscreen keypad */
+
#else
+
+#define MAX_GIC_NR 2
+
#define INT_AACI 0
#define INT_TIMERINT0_1 1
#define INT_TIMERINT2_3 2
diff --git a/include/asm-arm/arch-realview/scu.h b/include/asm-arm/arch-realview/scu.h
new file mode 100644
index 00000000000..cc293640178
--- /dev/null
+++ b/include/asm-arm/arch-realview/scu.h
@@ -0,0 +1,8 @@
+#ifndef __ASMARM_ARCH_SCU_H
+#define __ASMARM_ARCH_SCU_H
+
+#include <asm/arch/platform.h>
+
+#define SCU_BASE REALVIEW_MPCORE_SCU_BASE
+
+#endif
diff --git a/include/asm-arm/arch-s3c2410/dma.h b/include/asm-arm/arch-s3c2410/dma.h
index 58ffa7ba3c8..c6e8d8f6493 100644
--- a/include/asm-arm/arch-s3c2410/dma.h
+++ b/include/asm-arm/arch-s3c2410/dma.h
@@ -51,13 +51,19 @@ enum dma_ch {
DMACH_UART0_SRC2, /* s3c2412 second uart sources */
DMACH_UART1_SRC2,
DMACH_UART2_SRC2,
+ DMACH_UART3, /* s3c2443 has extra uart */
+ DMACH_UART3_SRC2,
DMACH_MAX, /* the end entry */
};
#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
/* we have 4 dma channels */
-#define S3C2410_DMA_CHANNELS (4)
+#ifndef CONFIG_CPU_S3C2443
+#define S3C2410_DMA_CHANNELS (4)
+#else
+#define S3C2410_DMA_CHANNELS (6)
+#endif
/* types */
@@ -321,6 +327,7 @@ extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
#define S3C2410_DMA_DCDST (0x1C)
#define S3C2410_DMA_DMASKTRIG (0x20)
#define S3C2412_DMA_DMAREQSEL (0x24)
+#define S3C2443_DMA_DMAREQSEL (0x24)
#define S3C2410_DISRCC_INC (1<<0)
#define S3C2410_DISRCC_APB (1<<1)
@@ -415,4 +422,31 @@ extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
#define S3C2412_DMAREQSEL_UART2_1 S3C2412_DMAREQSEL_SRC(24)
#endif
+
+#define S3C2443_DMAREQSEL_SRC(x) ((x)<<1)
+
+#define S3C2443_DMAREQSEL_HW (1)
+
+#define S3C2443_DMAREQSEL_SPI0TX S3C2443_DMAREQSEL_SRC(0)
+#define S3C2443_DMAREQSEL_SPI0RX S3C2443_DMAREQSEL_SRC(1)
+#define S3C2443_DMAREQSEL_SPI1TX S3C2443_DMAREQSEL_SRC(2)
+#define S3C2443_DMAREQSEL_SPI1RX S3C2443_DMAREQSEL_SRC(3)
+#define S3C2443_DMAREQSEL_I2STX S3C2443_DMAREQSEL_SRC(4)
+#define S3C2443_DMAREQSEL_I2SRX S3C2443_DMAREQSEL_SRC(5)
+#define S3C2443_DMAREQSEL_TIMER S3C2443_DMAREQSEL_SRC(9)
+#define S3C2443_DMAREQSEL_SDI S3C2443_DMAREQSEL_SRC(10)
+#define S3C2443_DMAREQSEL_XDREQ0 S3C2443_DMAREQSEL_SRC(17)
+#define S3C2443_DMAREQSEL_XDREQ1 S3C2443_DMAREQSEL_SRC(18)
+#define S3C2443_DMAREQSEL_UART0_0 S3C2443_DMAREQSEL_SRC(19)
+#define S3C2443_DMAREQSEL_UART0_1 S3C2443_DMAREQSEL_SRC(20)
+#define S3C2443_DMAREQSEL_UART1_0 S3C2443_DMAREQSEL_SRC(21)
+#define S3C2443_DMAREQSEL_UART1_1 S3C2443_DMAREQSEL_SRC(22)
+#define S3C2443_DMAREQSEL_UART2_0 S3C2443_DMAREQSEL_SRC(23)
+#define S3C2443_DMAREQSEL_UART2_1 S3C2443_DMAREQSEL_SRC(24)
+#define S3C2443_DMAREQSEL_UART3_0 S3C2443_DMAREQSEL_SRC(25)
+#define S3C2443_DMAREQSEL_UART3_1 S3C2443_DMAREQSEL_SRC(26)
+#define S3C2443_DMAREQSEL_PCMOUT S3C2443_DMAREQSEL_SRC(27)
+#define S3C2443_DMAREQSEL_PCMIN S3C2443_DMAREQSEL_SRC(28)
+#define S3C2443_DMAREQSEL_MICIN S3C2443_DMAREQSEL_SRC(29)
+
#endif /* __ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h
index 4b7cff456c4..c79cb181991 100644
--- a/include/asm-arm/arch-s3c2410/irqs.h
+++ b/include/asm-arm/arch-s3c2410/irqs.h
@@ -34,10 +34,10 @@
#define IRQ_EINT4t7 S3C2410_IRQ(4) /* 20 */
#define IRQ_EINT8t23 S3C2410_IRQ(5)
#define IRQ_RESERVED6 S3C2410_IRQ(6) /* for s3c2410 */
-#define IRQ_CAM S3C2410_IRQ(6) /* for s3c2440 */
+#define IRQ_CAM S3C2410_IRQ(6) /* for s3c2440,s3c2443 */
#define IRQ_BATT_FLT S3C2410_IRQ(7)
#define IRQ_TICK S3C2410_IRQ(8) /* 24 */
-#define IRQ_WDT S3C2410_IRQ(9)
+#define IRQ_WDT S3C2410_IRQ(9) /* WDT/AC97 for s3c2443 */
#define IRQ_TIMER0 S3C2410_IRQ(10)
#define IRQ_TIMER1 S3C2410_IRQ(11)
#define IRQ_TIMER2 S3C2410_IRQ(12)
@@ -45,7 +45,7 @@
#define IRQ_TIMER4 S3C2410_IRQ(14)
#define IRQ_UART2 S3C2410_IRQ(15)
#define IRQ_LCD S3C2410_IRQ(16) /* 32 */
-#define IRQ_DMA0 S3C2410_IRQ(17)
+#define IRQ_DMA0 S3C2410_IRQ(17) /* IRQ_DMA for s3c2443 */
#define IRQ_DMA1 S3C2410_IRQ(18)
#define IRQ_DMA2 S3C2410_IRQ(19)
#define IRQ_DMA3 S3C2410_IRQ(20)
@@ -94,29 +94,63 @@
* these need to be ordered in number of appearance in the
* SUBSRC mask register
*/
-#define IRQ_S3CUART_RX0 S3C2410_IRQ(54) /* 70 */
-#define IRQ_S3CUART_TX0 S3C2410_IRQ(55) /* 71 */
-#define IRQ_S3CUART_ERR0 S3C2410_IRQ(56)
-#define IRQ_S3CUART_RX1 S3C2410_IRQ(57)
-#define IRQ_S3CUART_TX1 S3C2410_IRQ(58)
-#define IRQ_S3CUART_ERR1 S3C2410_IRQ(59)
+#define S3C2410_IRQSUB(x) S3C2410_IRQ((x)+54)
-#define IRQ_S3CUART_RX2 S3C2410_IRQ(60)
-#define IRQ_S3CUART_TX2 S3C2410_IRQ(61)
-#define IRQ_S3CUART_ERR2 S3C2410_IRQ(62)
+#define IRQ_S3CUART_RX0 S3C2410_IRQSUB(0) /* 70 */
+#define IRQ_S3CUART_TX0 S3C2410_IRQSUB(1)
+#define IRQ_S3CUART_ERR0 S3C2410_IRQSUB(2)
-#define IRQ_TC S3C2410_IRQ(63)
-#define IRQ_ADC S3C2410_IRQ(64)
+#define IRQ_S3CUART_RX1 S3C2410_IRQSUB(3) /* 73 */
+#define IRQ_S3CUART_TX1 S3C2410_IRQSUB(4)
+#define IRQ_S3CUART_ERR1 S3C2410_IRQSUB(5)
-/* extra irqs for s3c2440 */
+#define IRQ_S3CUART_RX2 S3C2410_IRQSUB(6) /* 76 */
+#define IRQ_S3CUART_TX2 S3C2410_IRQSUB(7)
+#define IRQ_S3CUART_ERR2 S3C2410_IRQSUB(8)
-#define IRQ_S3C2440_CAM_C S3C2410_IRQ(65)
-#define IRQ_S3C2440_CAM_P S3C2410_IRQ(66)
-#define IRQ_S3C2440_WDT S3C2410_IRQ(67)
-#define IRQ_S3C2440_AC97 S3C2410_IRQ(68)
+#define IRQ_TC S3C2410_IRQSUB(9)
+#define IRQ_ADC S3C2410_IRQSUB(10)
-#define NR_IRQS (IRQ_S3C2440_AC97+1)
+/* extra irqs for s3c2440 */
+#define IRQ_S3C2440_CAM_C S3C2410_IRQSUB(11) /* S3C2443 too */
+#define IRQ_S3C2440_CAM_P S3C2410_IRQSUB(12) /* S3C2443 too */
+#define IRQ_S3C2440_WDT S3C2410_IRQSUB(13)
+#define IRQ_S3C2440_AC97 S3C2410_IRQSUB(14)
+
+/* irqs for s3c2443 */
+
+#define IRQ_S3C2443_DMA S3C2410_IRQ(17) /* IRQ_DMA1 */
+#define IRQ_S3C2443_UART3 S3C2410_IRQ(18) /* IRQ_DMA2 */
+#define IRQ_S3C2443_CFCON S3C2410_IRQ(19) /* IRQ_DMA3 */
+#define IRQ_S3C2443_SDI1 S3C2410_IRQ(20) /* IRQ_SDI */
+#define IRQ_S3C2443_NAND S3C2410_IRQ(24) /* reserved */
+
+#define IRQ_S3C2443_LCD1 S3C2410_IRQSUB(14)
+#define IRQ_S3C2443_LCD2 S3C2410_IRQSUB(15)
+#define IRQ_S3C2443_LCD3 S3C2410_IRQSUB(16)
+#define IRQ_S3C2443_LCD4 S3C2410_IRQSUB(17)
+
+#define IRQ_S3C2443_DMA0 S3C2410_IRQSUB(18)
+#define IRQ_S3C2443_DMA1 S3C2410_IRQSUB(19)
+#define IRQ_S3C2443_DMA2 S3C2410_IRQSUB(20)
+#define IRQ_S3C2443_DMA3 S3C2410_IRQSUB(21)
+#define IRQ_S3C2443_DMA4 S3C2410_IRQSUB(22)
+#define IRQ_S3C2443_DMA5 S3C2410_IRQSUB(23)
+
+/* UART3 */
+#define IRQ_S3C2443_RX3 S3C2410_IRQSUB(24)
+#define IRQ_S3C2443_TX3 S3C2410_IRQSUB(25)
+#define IRQ_S3C2443_ERR3 S3C2410_IRQSUB(26)
+
+#define IRQ_S3C2443_WDT S3C2410_IRQSUB(27)
+#define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28)
+
+#ifdef CONFIG_CPU_S3C2443
+#define NR_IRQS (IRQ_S3C2443_AC97+1)
+#else
+#define NR_IRQS (IRQ_S3C2440_AC97+1)
+#endif
#endif /* __ASM_ARCH_IRQ_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-adc.h b/include/asm-arm/arch-s3c2410/regs-adc.h
index 3196a2849e8..c7f231963e7 100644
--- a/include/asm-arm/arch-s3c2410/regs-adc.h
+++ b/include/asm-arm/arch-s3c2410/regs-adc.h
@@ -41,7 +41,7 @@
#define S3C2410_ADCTSC_XP_SEN (1<<4)
#define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3)
#define S3C2410_ADCTSC_AUTO_PST (1<<2)
-#define S3C2410_ADCTSC_XY_PST (0x3<<0)
+#define S3C2410_ADCTSC_XY_PST(x) (((x)&0x3)<<0)
/* ADCDAT0 Bits */
#define S3C2410_ADCDAT0_UPDOWN (1<<15)
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index eae91694edc..dea578b8f7f 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -201,7 +201,7 @@
#define S3C2400_GPBDAT S3C2410_GPIOREG(0x0C)
#define S3C2400_GPBUP S3C2410_GPIOREG(0x10)
-/* no i/o pin in port b can have value 3! */
+/* no i/o pin in port b can have value 3 (unless it is a s3c2443) ! */
#define S3C2410_GPB0 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 0)
#define S3C2410_GPB0_INP (0x00 << 0)
@@ -242,6 +242,7 @@
#define S3C2410_GPB5_INP (0x00 << 10)
#define S3C2410_GPB5_OUTP (0x01 << 10)
#define S3C2410_GPB5_nXBACK (0x02 << 10)
+#define S3C2443_GPB5_XBACK (0x03 << 10)
#define S3C2400_GPB5_DATA21 (0x02 << 10)
#define S3C2400_GPB5_nCTS1 (0x03 << 10)
@@ -249,6 +250,7 @@
#define S3C2410_GPB6_INP (0x00 << 12)
#define S3C2410_GPB6_OUTP (0x01 << 12)
#define S3C2410_GPB6_nXBREQ (0x02 << 12)
+#define S3C2443_GPB6_XBREQ (0x03 << 12)
#define S3C2400_GPB6_DATA22 (0x02 << 12)
#define S3C2400_GPB6_nRTS1 (0x03 << 12)
@@ -256,6 +258,7 @@
#define S3C2410_GPB7_INP (0x00 << 14)
#define S3C2410_GPB7_OUTP (0x01 << 14)
#define S3C2410_GPB7_nXDACK1 (0x02 << 14)
+#define S3C2443_GPB7_XDACK1 (0x03 << 14)
#define S3C2400_GPB7_DATA23 (0x02 << 14)
#define S3C2410_GPB8 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 8)
@@ -268,6 +271,7 @@
#define S3C2410_GPB9_INP (0x00 << 18)
#define S3C2410_GPB9_OUTP (0x01 << 18)
#define S3C2410_GPB9_nXDACK0 (0x02 << 18)
+#define S3C2443_GPB9_XDACK0 (0x03 << 18)
#define S3C2400_GPB9_DATA25 (0x02 << 18)
#define S3C2400_GPB9_I2SSDI (0x03 << 18)
@@ -275,6 +279,7 @@
#define S3C2410_GPB10_INP (0x00 << 20)
#define S3C2410_GPB10_OUTP (0x01 << 20)
#define S3C2410_GPB10_nXDRE0 (0x02 << 20)
+#define S3C2443_GPB10_XDREQ0 (0x03 << 20)
#define S3C2400_GPB10_DATA26 (0x02 << 20)
#define S3C2400_GPB10_nSS (0x03 << 20)
@@ -556,6 +561,7 @@
#define S3C2410_GPE0_INP (0x00 << 0)
#define S3C2410_GPE0_OUTP (0x01 << 0)
#define S3C2410_GPE0_I2SLRCK (0x02 << 0)
+#define S3C2443_GPE0_AC_nRESET (0x03 << 0)
#define S3C2400_GPE0_EINT0 (0x02 << 0)
#define S3C2410_GPE0_MASK (0x03 << 0)
@@ -563,6 +569,7 @@
#define S3C2410_GPE1_INP (0x00 << 2)
#define S3C2410_GPE1_OUTP (0x01 << 2)
#define S3C2410_GPE1_I2SSCLK (0x02 << 2)
+#define S3C2443_GPE1_AC_SYNC (0x03 << 2)
#define S3C2400_GPE1_EINT1 (0x02 << 2)
#define S3C2400_GPE1_nSS (0x03 << 2)
#define S3C2410_GPE1_MASK (0x03 << 2)
@@ -571,6 +578,7 @@
#define S3C2410_GPE2_INP (0x00 << 4)
#define S3C2410_GPE2_OUTP (0x01 << 4)
#define S3C2410_GPE2_CDCLK (0x02 << 4)
+#define S3C2443_GPE2_AC_BITCLK (0x03 << 4)
#define S3C2400_GPE2_EINT2 (0x02 << 4)
#define S3C2400_GPE2_I2SSDI (0x03 << 4)
@@ -578,6 +586,7 @@
#define S3C2410_GPE3_INP (0x00 << 6)
#define S3C2410_GPE3_OUTP (0x01 << 6)
#define S3C2410_GPE3_I2SSDI (0x02 << 6)
+#define S3C2443_GPE3_AC_SDI (0x03 << 6)
#define S3C2400_GPE3_EINT3 (0x02 << 6)
#define S3C2400_GPE3_nCTS1 (0x03 << 6)
#define S3C2410_GPE3_nSS0 (0x03 << 6)
@@ -587,6 +596,7 @@
#define S3C2410_GPE4_INP (0x00 << 8)
#define S3C2410_GPE4_OUTP (0x01 << 8)
#define S3C2410_GPE4_I2SSDO (0x02 << 8)
+#define S3C2443_GPE4_AC_SDO (0x03 << 8)
#define S3C2400_GPE4_EINT4 (0x02 << 8)
#define S3C2400_GPE4_nRTS1 (0x03 << 8)
#define S3C2410_GPE4_I2SSDI (0x03 << 8)
@@ -596,6 +606,7 @@
#define S3C2410_GPE5_INP (0x00 << 10)
#define S3C2410_GPE5_OUTP (0x01 << 10)
#define S3C2410_GPE5_SDCLK (0x02 << 10)
+#define S3C2443_GPE5_SD1_CLK (0x02 << 10)
#define S3C2400_GPE5_EINT5 (0x02 << 10)
#define S3C2400_GPE5_TCLK1 (0x03 << 10)
@@ -603,24 +614,32 @@
#define S3C2410_GPE6_INP (0x00 << 12)
#define S3C2410_GPE6_OUTP (0x01 << 12)
#define S3C2410_GPE6_SDCMD (0x02 << 12)
+#define S3C2443_GPE6_SD1_CMD (0x02 << 12)
+#define S3C2443_GPE6_AC_BITCLK (0x03 << 12)
#define S3C2400_GPE6_EINT6 (0x02 << 12)
#define S3C2410_GPE7 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 7)
#define S3C2410_GPE7_INP (0x00 << 14)
#define S3C2410_GPE7_OUTP (0x01 << 14)
#define S3C2410_GPE7_SDDAT0 (0x02 << 14)
+#define S3C2443_GPE5_SD1_DAT0 (0x02 << 14)
+#define S3C2443_GPE7_AC_SDI (0x03 << 14)
#define S3C2400_GPE7_EINT7 (0x02 << 14)
#define S3C2410_GPE8 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 8)
#define S3C2410_GPE8_INP (0x00 << 16)
#define S3C2410_GPE8_OUTP (0x01 << 16)
#define S3C2410_GPE8_SDDAT1 (0x02 << 16)
+#define S3C2443_GPE8_SD1_DAT1 (0x02 << 16)
+#define S3C2443_GPE8_AC_SDO (0x03 << 16)
#define S3C2400_GPE8_nXDACK0 (0x02 << 16)
#define S3C2410_GPE9 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 9)
#define S3C2410_GPE9_INP (0x00 << 18)
#define S3C2410_GPE9_OUTP (0x01 << 18)
#define S3C2410_GPE9_SDDAT2 (0x02 << 18)
+#define S3C2443_GPE9_SD1_DAT2 (0x02 << 18)
+#define S3C2443_GPE9_AC_SYNC (0x03 << 18)
#define S3C2400_GPE9_nXDACK1 (0x02 << 18)
#define S3C2400_GPE9_nXBACK (0x03 << 18)
@@ -628,6 +647,8 @@
#define S3C2410_GPE10_INP (0x00 << 20)
#define S3C2410_GPE10_OUTP (0x01 << 20)
#define S3C2410_GPE10_SDDAT3 (0x02 << 20)
+#define S3C2443_GPE10_SD1_DAT3 (0x02 << 20)
+#define S3C2443_GPE10_AC_nRESET (0x03 << 20)
#define S3C2400_GPE10_nXDREQ0 (0x02 << 20)
#define S3C2410_GPE11 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 11)
@@ -796,6 +817,7 @@
#define S3C2400_GPG4_MMCCLK (0x02 << 8)
#define S3C2400_GPG4_I2SSDI (0x03 << 8)
#define S3C2410_GPG4_LCDPWREN (0x03 << 8)
+#define S3C2443_GPG4_LCDPWRDN (0x03 << 8)
#define S3C2410_GPG5 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 5)
#define S3C2410_GPG5_INP (0x00 << 10)
@@ -803,7 +825,7 @@
#define S3C2410_GPG5_EINT13 (0x02 << 10)
#define S3C2400_GPG5_MMCCMD (0x02 << 10)
#define S3C2400_GPG5_IICSDA (0x03 << 10)
-#define S3C2410_GPG5_SPIMISO1 (0x03 << 10)
+#define S3C2410_GPG5_SPIMISO1 (0x03 << 10) /* not s3c2443 */
#define S3C2410_GPG6 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 6)
#define S3C2410_GPG6_INP (0x00 << 12)
@@ -845,6 +867,7 @@
#define S3C2410_GPG11_OUTP (0x01 << 22)
#define S3C2410_GPG11_EINT19 (0x02 << 22)
#define S3C2410_GPG11_TCLK1 (0x03 << 22)
+#define S3C2443_GPG11_CF_nIREQ (0x03 << 22)
#define S3C2410_GPG12 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 12)
#define S3C2410_GPG12_INP (0x00 << 24)
@@ -852,25 +875,28 @@
#define S3C2410_GPG12_EINT20 (0x02 << 24)
#define S3C2410_GPG12_XMON (0x03 << 24)
#define S3C2442_GPG12_nSPICS0 (0x03 << 24)
+#define S3C2443_GPG12_nINPACK (0x03 << 24)
#define S3C2410_GPG13 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 13)
#define S3C2410_GPG13_INP (0x00 << 26)
#define S3C2410_GPG13_OUTP (0x01 << 26)
#define S3C2410_GPG13_EINT21 (0x02 << 26)
#define S3C2410_GPG13_nXPON (0x03 << 26)
+#define S3C2443_GPG13_CF_nREG (0x03 << 26)
#define S3C2410_GPG14 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 14)
#define S3C2410_GPG14_INP (0x00 << 28)
#define S3C2410_GPG14_OUTP (0x01 << 28)
#define S3C2410_GPG14_EINT22 (0x02 << 28)
#define S3C2410_GPG14_YMON (0x03 << 28)
+#define S3C2443_GPG14_CF_RESET (0x03 << 28)
#define S3C2410_GPG15 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 15)
#define S3C2410_GPG15_INP (0x00 << 30)
#define S3C2410_GPG15_OUTP (0x01 << 30)
#define S3C2410_GPG15_EINT23 (0x02 << 30)
#define S3C2410_GPG15_nYPON (0x03 << 30)
-
+#define S3C2443_GPG15_CF_PWR (0x03 << 30)
#define S3C2410_GPG_PUPDIS(x) (1<<(x))
diff --git a/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h b/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h
new file mode 100644
index 00000000000..ff0536d2de4
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h
@@ -0,0 +1,194 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-clock.h
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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.
+ *
+ * S3C2443 clock register definitions
+*/
+
+#ifndef __ASM_ARM_REGS_S3C2443_CLOCK
+#define __ASM_ARM_REGS_S3C2443_CLOCK
+
+#define S3C2443_CLKREG(x) ((x) + S3C24XX_VA_CLKPWR)
+
+#define S3C2443_PLLCON_MDIVSHIFT 16
+#define S3C2443_PLLCON_PDIVSHIFT 8
+#define S3C2443_PLLCON_SDIVSHIFT 0
+#define S3C2443_PLLCON_MDIVMASK ((1<<(1+(23-16)))-1)
+#define S3C2443_PLLCON_PDIVMASK ((1<<(1+(9-8)))-1)
+#define S3C2443_PLLCON_SDIVMASK (3)
+
+#define S3C2443_MPLLCON S3C2443_CLKREG(0x10)
+#define S3C2443_EPLLCON S3C2443_CLKREG(0x18)
+#define S3C2443_CLKSRC S3C2443_CLKREG(0x20)
+#define S3C2443_CLKDIV0 S3C2443_CLKREG(0x24)
+#define S3C2443_CLKDIV1 S3C2443_CLKREG(0x28)
+#define S3C2443_HCLKCON S3C2443_CLKREG(0x30)
+#define S3C2443_PCLKCON S3C2443_CLKREG(0x34)
+#define S3C2443_SCLKCON S3C2443_CLKREG(0x38)
+#define S3C2443_PWRMODE S3C2443_CLKREG(0x40)
+#define S3C2443_SWRST S3C2443_CLKREG(0x44)
+#define S3C2443_BUSPRI0 S3C2443_CLKREG(0x50)
+#define S3C2443_SYSID S3C2443_CLKREG(0x5C)
+#define S3C2443_PWRCFG S3C2443_CLKREG(0x60)
+#define S3C2443_RSTCON S3C2443_CLKREG(0x64)
+
+#define S3C2443_SWRST_RESET (0x533c2443)
+
+#define S3C2443_PLLCON_OFF (1<<24)
+
+#define S3C2443_CLKSRC_I2S_EXT (1<<14)
+#define S3C2443_CLKSRC_I2S_EPLLDIV (0<<14)
+#define S3C2443_CLKSRC_I2S_EPLLREF (2<<14)
+#define S3C2443_CLKSRC_I2S_EPLLREF3 (3<<14)
+#define S3C2443_CLKSRC_I2S_MASK (3<<14)
+
+#define S3C2443_CLKSRC_EPLLREF_XTAL (2<<8)
+#define S3C2443_CLKSRC_EPLLREF_EXTCLK (3<<8)
+#define S3C2443_CLKSRC_EPLLREF_MPLLREF (0<<8)
+#define S3C2443_CLKSRC_EPLLREF_MPLLREF2 (1<<8)
+#define S3C2443_CLKSRC_EPLLREF_MASK (3<<8)
+
+#define S3C2443_CLKSRC_ESYSCLK_EPLL (1<<6)
+#define S3C2443_CLKSRC_MSYSCLK_MPLL (1<<4)
+#define S3C2443_CLKSRC_EXTCLK_DIV (1<<3)
+
+#define S3C2443_CLKDIV0_DVS (1<<13)
+#define S3C2443_CLKDIV0_HALF_HCLK (1<<3)
+#define S3C2443_CLKDIV0_HALF_PCLK (1<<2)
+
+#define S3C2443_CLKDIV0_HCLKDIV_MASK (3<<0)
+
+#define S3C2443_CLKDIV0_EXTDIV_MASK (3<<6)
+#define S3C2443_CLKDIV0_EXTDIV_SHIFT (6)
+
+#define S3C2443_CLKDIV0_PREDIV_MASK (3<<4)
+#define S3C2443_CLKDIV0_PREDIV_SHIFT (4)
+
+#define S3C2443_CLKDIV0_ARMDIV_MASK (15<<9)
+#define S3C2443_CLKDIV0_ARMDIV_SHIFT (9)
+#define S3C2443_CLKDIV0_ARMDIV_1 (0<<9)
+#define S3C2443_CLKDIV0_ARMDIV_2 (8<<9)
+#define S3C2443_CLKDIV0_ARMDIV_3 (2<<9)
+#define S3C2443_CLKDIV0_ARMDIV_4 (9<<9)
+#define S3C2443_CLKDIV0_ARMDIV_6 (10<<9)
+#define S3C2443_CLKDIV0_ARMDIV_8 (11<<9)
+#define S3C2443_CLKDIV0_ARMDIV_12 (13<<9)
+#define S3C2443_CLKDIV0_ARMDIV_16 (15<<9)
+
+/* S3C2443_CLKDIV1 */
+
+#define S3C2443_CLKDIV1_CAMDIV_MASK (15<<26)
+#define S3C2443_CLKDIV1_CAMDIV_SHIFT (26)
+
+#define S3C2443_CLKDIV1_HSSPIDIV_MASK (3<<24)
+#define S3C2443_CLKDIV1_HSSPIDIV_SHIFT (24)
+
+#define S3C2443_CLKDIV1_DISPDIV_MASK (0xff<<16)
+#define S3C2443_CLKDIV1_DISPDIV_SHIFT (16)
+
+#define S3C2443_CLKDIV1_I2SDIV_MASK (15<<12)
+#define S3C2443_CLKDIV1_I2SDIV_SHIFT (12)
+
+#define S3C2443_CLKDIV1_UARTDIV_MASK (15<<8)
+#define S3C2443_CLKDIV1_UARTDIV_SHIFT (8)
+
+#define S3C2443_CLKDIV1_HSMMCDIV_MASK (3<<6)
+#define S3C2443_CLKDIV1_HSMMCDIV_SHIFT (6)
+
+#define S3C2443_CLKDIV1_USBHOSTDIV_MASK (3<<4)
+#define S3C2443_CLKDIV1_USBHOSTDIV_SHIFT (4)
+
+#define S3C2443_CLKCON_NAND
+
+#define S3C2443_HCLKCON_DMA0 (1<<0)
+#define S3C2443_HCLKCON_DMA1 (1<<1)
+#define S3C2443_HCLKCON_DMA2 (1<<2)
+#define S3C2443_HCLKCON_DMA3 (1<<3)
+#define S3C2443_HCLKCON_DMA4 (1<<4)
+#define S3C2443_HCLKCON_DMA5 (1<<5)
+#define S3C2443_HCLKCON_CAMIF (1<<8)
+#define S3C2443_HCLKCON_DISP (1<<9)
+#define S3C2443_HCLKCON_LCDC (1<<10)
+#define S3C2443_HCLKCON_USBH (1<<11)
+#define S3C2443_HCLKCON_USBD (1<<12)
+#define S3C2443_HCLKCON_HSMMC (1<<16)
+#define S3C2443_HCLKCON_CFC (1<<17)
+#define S3C2443_HCLKCON_SSMC (1<<18)
+#define S3C2443_HCLKCON_DRAMC (1<<19)
+
+#define S3C2443_PCLKCON_UART0 (1<<0)
+#define S3C2443_PCLKCON_UART1 (1<<1)
+#define S3C2443_PCLKCON_UART2 (1<<2)
+#define S3C2443_PCLKCON_UART3 (1<<3)
+#define S3C2443_PCLKCON_IIC (1<<4)
+#define S3C2443_PCLKCON_SDI (1<<5)
+#define S3C2443_PCLKCON_ADC (1<<7)
+#define S3C2443_PCLKCON_IIS (1<<9)
+#define S3C2443_PCLKCON_PWMT (1<<10)
+#define S3C2443_PCLKCON_WDT (1<<11)
+#define S3C2443_PCLKCON_RTC (1<<12)
+#define S3C2443_PCLKCON_GPIO (1<<13)
+#define S3C2443_PCLKCON_SPI0 (1<<14)
+#define S3C2443_PCLKCON_SPI1 (1<<15)
+
+#define S3C2443_SCLKCON_DDRCLK (1<<16)
+#define S3C2443_SCLKCON_SSMCCLK (1<<15)
+#define S3C2443_SCLKCON_HSSPICLK (1<<14)
+#define S3C2443_SCLKCON_HSMMCCLK_EXT (1<<13)
+#define S3C2443_SCLKCON_HSMMCCLK_EPLL (1<<12)
+#define S3C2443_SCLKCON_CAMCLK (1<<11)
+#define S3C2443_SCLKCON_DISPCLK (1<<10)
+#define S3C2443_SCLKCON_I2SCLK (1<<9)
+#define S3C2443_SCLKCON_UARTCLK (1<<8)
+#define S3C2443_SCLKCON_USBHOST (1<<1)
+
+#include <asm/div64.h>
+
+static inline unsigned int
+s3c2443_get_mpll(unsigned int pllval, unsigned int baseclk)
+{
+ unsigned int mdiv, pdiv, sdiv;
+ uint64_t fvco;
+
+ mdiv = pllval >> S3C2443_PLLCON_MDIVSHIFT;
+ pdiv = pllval >> S3C2443_PLLCON_PDIVSHIFT;
+ sdiv = pllval >> S3C2443_PLLCON_SDIVSHIFT;
+
+ mdiv &= S3C2443_PLLCON_MDIVMASK;
+ pdiv &= S3C2443_PLLCON_PDIVMASK;
+ sdiv &= S3C2443_PLLCON_SDIVMASK;
+
+ fvco = (uint64_t)baseclk * (2 * (mdiv + 8));
+ do_div(fvco, pdiv << sdiv);
+
+ return (unsigned int)fvco;
+}
+
+static inline unsigned int
+s3c2443_get_epll(unsigned int pllval, unsigned int baseclk)
+{
+ unsigned int mdiv, pdiv, sdiv;
+ uint64_t fvco;
+
+ mdiv = pllval >> S3C2443_PLLCON_MDIVSHIFT;
+ pdiv = pllval >> S3C2443_PLLCON_PDIVSHIFT;
+ sdiv = pllval >> S3C2443_PLLCON_SDIVSHIFT;
+
+ mdiv &= S3C2443_PLLCON_MDIVMASK;
+ pdiv &= S3C2443_PLLCON_PDIVMASK;
+ sdiv &= S3C2443_PLLCON_SDIVMASK;
+
+ fvco = (uint64_t)baseclk * (mdiv + 8);
+ do_div(fvco, (pdiv + 2) << sdiv);
+
+ return (unsigned int)fvco;
+}
+
+#endif /* __ASM_ARM_REGS_S3C2443_CLOCK */
+
diff --git a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h
index 46f52401d13..8946702a87f 100644
--- a/include/asm-arm/arch-s3c2410/regs-serial.h
+++ b/include/asm-arm/arch-s3c2410/regs-serial.h
@@ -35,10 +35,12 @@
#define S3C24XX_VA_UART0 (S3C24XX_VA_UART)
#define S3C24XX_VA_UART1 (S3C24XX_VA_UART + 0x4000 )
#define S3C24XX_VA_UART2 (S3C24XX_VA_UART + 0x8000 )
+#define S3C24XX_VA_UART3 (S3C24XX_VA_UART + 0xC000 )
#define S3C2410_PA_UART0 (S3C24XX_PA_UART)
#define S3C2410_PA_UART1 (S3C24XX_PA_UART + 0x4000 )
#define S3C2410_PA_UART2 (S3C24XX_PA_UART + 0x8000 )
+#define S3C2443_PA_UART3 (S3C24XX_PA_UART + 0xC000 )
#define S3C2410_URXH (0x24)
#define S3C2410_UTXH (0x20)
@@ -73,6 +75,8 @@
#define S3C2440_UCON_UCLK (1<<10)
#define S3C2440_UCON_PCLK2 (2<<10)
#define S3C2440_UCON_FCLK (3<<10)
+#define S3C2443_UCON_EPLL (3<<10)
+
#define S3C2440_UCON2_FCLK_EN (1<<15)
#define S3C2440_UCON0_DIVMASK (15 << 12)
#define S3C2440_UCON1_DIVMASK (15 << 12)
@@ -93,6 +97,8 @@
#define S3C2410_UCON_TXIRQMODE (1<<2)
#define S3C2410_UCON_RXIRQMODE (1<<0)
#define S3C2410_UCON_RXFIFO_TOI (1<<7)
+#define S3C2443_UCON_RXERR_IRQEN (1<<6)
+#define S3C2443_UCON_LOOPBACK (1<<5)
#define S3C2410_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
S3C2410_UCON_RXILEVEL | \
@@ -127,7 +133,7 @@
#define S3C2410_UMCOM_AFC (1<<4)
#define S3C2410_UMCOM_RTS_LOW (1<<0)
-#define S3C2412_UMCON_AFC_63 (0<<5)
+#define S3C2412_UMCON_AFC_63 (0<<5) /* same as s3c2443 */
#define S3C2412_UMCON_AFC_56 (1<<5)
#define S3C2412_UMCON_AFC_48 (2<<5)
#define S3C2412_UMCON_AFC_40 (3<<5)
@@ -143,6 +149,7 @@
#define S3C2410_UFSTAT_RXMASK (15<<0)
#define S3C2410_UFSTAT_RXSHIFT (0)
+/* UFSTAT S3C2443 same as S3C2440 */
#define S3C2440_UFSTAT_TXFULL (1<<14)
#define S3C2440_UFSTAT_RXFULL (1<<6)
#define S3C2440_UFSTAT_TXSHIFT (8)
@@ -157,6 +164,8 @@
#define S3C2410_UERSTAT_OVERRUN (1<<0)
#define S3C2410_UERSTAT_FRAME (1<<2)
#define S3C2410_UERSTAT_BREAK (1<<3)
+#define S3C2443_UERSTAT_PARITY (1<<1)
+
#define S3C2410_UERSTAT_ANY (S3C2410_UERSTAT_OVERRUN | \
S3C2410_UERSTAT_FRAME | \
S3C2410_UERSTAT_BREAK)
@@ -164,6 +173,8 @@
#define S3C2410_UMSTAT_CTS (1<<0)
#define S3C2410_UMSTAT_DeltaCTS (1<<2)
+#define S3C2443_DIVSLOT (0x2C)
+
#ifndef __ASSEMBLY__
/* struct s3c24xx_uart_clksrc
diff --git a/include/asm-arm/arch-s3c2410/reset.h b/include/asm-arm/arch-s3c2410/reset.h
new file mode 100644
index 00000000000..4f866cdecab
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/reset.h
@@ -0,0 +1,22 @@
+/* linux/include/asm-arm/arch-s3c2410/reset.h
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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.
+ *
+ * S3C2410 CPU reset controls
+*/
+
+#ifndef __ASM_ARCH_RESET_H
+#define __ASM_ARCH_RESET_H __FILE__
+
+/* This allows the over-ride of the default reset code
+*/
+
+extern void (*s3c24xx_reset_hook)(void);
+
+#endif /* __ASM_ARCH_RESET_H */
diff --git a/include/asm-arm/arch-s3c2410/system.h b/include/asm-arm/arch-s3c2410/system.h
index ecf250db45f..1c74ef17da3 100644
--- a/include/asm-arm/arch-s3c2410/system.h
+++ b/include/asm-arm/arch-s3c2410/system.h
@@ -15,15 +15,16 @@
#include <asm/arch/map.h>
#include <asm/arch/idle.h>
+#include <asm/arch/reset.h>
#include <asm/arch/regs-watchdog.h>
#include <asm/arch/regs-clock.h>
void (*s3c24xx_idle)(void);
+void (*s3c24xx_reset_hook)(void);
void s3c24xx_default_idle(void)
{
- void __iomem *reg = S3C2410_CLKCON;
unsigned long tmp;
int i;
@@ -33,16 +34,18 @@ void s3c24xx_default_idle(void)
/* Warning: going into idle state upsets jtag scanning */
- __raw_writel(__raw_readl(reg) | (1<<2), reg);
+ __raw_writel(__raw_readl(S3C2410_CLKCON) | S3C2410_CLKCON_IDLE,
+ S3C2410_CLKCON);
/* the samsung port seems to do a loop and then unset idle.. */
for (i = 0; i < 50; i++) {
- tmp += __raw_readl(reg); /* ensure loop not optimised out */
+ tmp += __raw_readl(S3C2410_CLKCON); /* ensure loop not optimised out */
}
/* this bit is not cleared on re-start... */
- __raw_writel(__raw_readl(reg) & ~(1<<2), reg);
+ __raw_writel(__raw_readl(S3C2410_CLKCON) & ~S3C2410_CLKCON_IDLE,
+ S3C2410_CLKCON);
}
static void arch_idle(void)
@@ -53,7 +56,6 @@ static void arch_idle(void)
s3c24xx_default_idle();
}
-
static void
arch_reset(char mode)
{
@@ -61,6 +63,9 @@ arch_reset(char mode)
cpu_reset(0);
}
+ if (s3c24xx_reset_hook)
+ s3c24xx_reset_hook();
+
printk("arch_reset: attempting watchdog reset\n");
__raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */
diff --git a/include/asm-arm/arch-s3c2410/udc.h b/include/asm-arm/arch-s3c2410/udc.h
new file mode 100644
index 00000000000..e59ec339d61
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/udc.h
@@ -0,0 +1,36 @@
+/* linux/include/asm/arch-s3c2410/udc.h
+ *
+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.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.
+ *
+ *
+ * Changelog:
+ * 14-Mar-2005 RTP Created file
+ * 02-Aug-2005 RTP File rename
+ * 07-Sep-2005 BJD Minor cleanups, changed cmd to enum
+ * 18-Jan-2007 HMW Add per-platform vbus_draw function
+*/
+
+#ifndef __ASM_ARM_ARCH_UDC_H
+#define __ASM_ARM_ARCH_UDC_H
+
+enum s3c2410_udc_cmd_e {
+ S3C2410_UDC_P_ENABLE = 1, /* Pull-up enable */
+ S3C2410_UDC_P_DISABLE = 2, /* Pull-up disable */
+ S3C2410_UDC_P_RESET = 3, /* UDC reset, in case of */
+};
+
+struct s3c2410_udc_mach_info {
+ void (*udc_command)(enum s3c2410_udc_cmd_e);
+ void (*vbus_draw)(unsigned int ma);
+ unsigned int vbus_pin;
+ unsigned char vbus_pin_inverted;
+};
+
+extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
+
+#endif /* __ASM_ARM_ARCH_UDC_H */
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 5f531ea0305..afad32c76e6 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -185,9 +185,15 @@ struct cpu_cache_fns {
void (*coherent_user_range)(unsigned long, unsigned long);
void (*flush_kern_dcache_page)(void *);
- void (*dma_inv_range)(unsigned long, unsigned long);
- void (*dma_clean_range)(unsigned long, unsigned long);
- void (*dma_flush_range)(unsigned long, unsigned long);
+ void (*dma_inv_range)(const void *, const void *);
+ void (*dma_clean_range)(const void *, const void *);
+ void (*dma_flush_range)(const void *, const void *);
+};
+
+struct outer_cache_fns {
+ void (*inv_range)(unsigned long, unsigned long);
+ void (*clean_range)(unsigned long, unsigned long);
+ void (*flush_range)(unsigned long, unsigned long);
};
/*
@@ -240,9 +246,40 @@ extern void __cpuc_flush_dcache_page(void *);
#define dmac_clean_range __glue(_CACHE,_dma_clean_range)
#define dmac_flush_range __glue(_CACHE,_dma_flush_range)
-extern void dmac_inv_range(unsigned long, unsigned long);
-extern void dmac_clean_range(unsigned long, unsigned long);
-extern void dmac_flush_range(unsigned long, unsigned long);
+extern void dmac_inv_range(const void *, const void *);
+extern void dmac_clean_range(const void *, const void *);
+extern void dmac_flush_range(const void *, const void *);
+
+#endif
+
+#ifdef CONFIG_OUTER_CACHE
+
+extern struct outer_cache_fns outer_cache;
+
+static inline void outer_inv_range(unsigned long start, unsigned long end)
+{
+ if (outer_cache.inv_range)
+ outer_cache.inv_range(start, end);
+}
+static inline void outer_clean_range(unsigned long start, unsigned long end)
+{
+ if (outer_cache.clean_range)
+ outer_cache.clean_range(start, end);
+}
+static inline void outer_flush_range(unsigned long start, unsigned long end)
+{
+ if (outer_cache.flush_range)
+ outer_cache.flush_range(start, end);
+}
+
+#else
+
+static inline void outer_inv_range(unsigned long start, unsigned long end)
+{ }
+static inline void outer_clean_range(unsigned long start, unsigned long end)
+{ }
+static inline void outer_flush_range(unsigned long start, unsigned long end)
+{ }
#endif
diff --git a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h
index 8c0bb5bb14e..eaa0efd8d0d 100644
--- a/include/asm-arm/checksum.h
+++ b/include/asm-arm/checksum.h
@@ -40,13 +40,27 @@ __wsum
csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr);
/*
+ * Fold a partial checksum without adding pseudo headers
+ */
+static inline __sum16 csum_fold(__wsum sum)
+{
+ __asm__(
+ "add %0, %1, %1, ror #16 @ csum_fold"
+ : "=r" (sum)
+ : "r" (sum)
+ : "cc");
+ return (__force __sum16)(~(__force u32)sum >> 16);
+}
+
+/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
static inline __sum16
ip_fast_csum(const void *iph, unsigned int ihl)
{
- unsigned int sum, tmp1;
+ unsigned int tmp1;
+ __wsum sum;
__asm__ __volatile__(
"ldr %0, [%1], #4 @ ip_fast_csum \n\
@@ -62,29 +76,11 @@ ip_fast_csum(const void *iph, unsigned int ihl)
subne %2, %2, #1 @ without destroying \n\
bne 1b @ the carry flag \n\
adcs %0, %0, %3 \n\
- adc %0, %0, #0 \n\
- adds %0, %0, %0, lsl #16 \n\
- addcs %0, %0, #0x10000 \n\
- mvn %0, %0 \n\
- mov %0, %0, lsr #16"
+ adc %0, %0, #0"
: "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1)
: "1" (iph), "2" (ihl)
: "cc", "memory");
- return (__force __sum16)sum;
-}
-
-/*
- * Fold a partial checksum without adding pseudo headers
- */
-static inline __sum16 csum_fold(__wsum sum)
-{
- __asm__(
- "adds %0, %1, %1, lsl #16 @ csum_fold \n\
- addcs %0, %0, #0x10000"
- : "=r" (sum)
- : "r" (sum)
- : "cc");
- return (__force __sum16)(~(__force u32)sum >> 16);
+ return csum_fold(sum);
}
static inline __wsum
@@ -114,23 +110,7 @@ static inline __sum16
csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
unsigned short proto, __wsum sum)
{
- __asm__(
- "adds %0, %1, %2 @ csum_tcpudp_magic \n\
- adcs %0, %0, %3 \n"
-#ifdef __ARMEB__
- "adcs %0, %0, %4 \n"
-#else
- "adcs %0, %0, %4, lsl #8 \n"
-#endif
- "adcs %0, %0, %5 \n\
- adc %0, %0, #0 \n\
- adds %0, %0, %0, lsl #16 \n\
- addcs %0, %0, #0x10000 \n\
- mvn %0, %0"
- : "=&r"(sum)
- : "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto))
- : "cc");
- return (__force __sum16)((__force u32)sum >> 16);
+ return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
}
diff --git a/include/asm-arm/device.h b/include/asm-arm/device.h
index d8f9872b0e2..c61642b4060 100644
--- a/include/asm-arm/device.h
+++ b/include/asm-arm/device.h
@@ -3,5 +3,13 @@
*
* This file is released under the GPLv2
*/
-#include <asm-generic/device.h>
+#ifndef ASMARM_DEVICE_H
+#define ASMARM_DEVICE_H
+struct dev_archdata {
+#ifdef CONFIG_DMABOUNCE
+ struct dmabounce_device_info *dmabounce;
+#endif
+};
+
+#endif
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index 9bc46b486af..abfb75b654c 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -17,7 +17,7 @@
* platforms with CONFIG_DMABOUNCE.
* Use the driver DMA support - see dma-mapping.h (dma_sync_*)
*/
-extern void consistent_sync(void *kaddr, size_t size, int rw);
+extern void consistent_sync(const void *kaddr, size_t size, int rw);
/*
* Return whether the given device DMA address mask can be supported
@@ -61,6 +61,22 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
return dma_addr == ~0;
}
+/*
+ * Dummy noncoherent implementation. We don't provide a dma_cache_sync
+ * function so drivers using this API are highlighted with build warnings.
+ */
+static inline void *
+dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+{
+ return NULL;
+}
+
+static inline void
+dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t handle)
+{
+}
+
/**
* dma_alloc_coherent - allocate consistent memory for DMA
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
diff --git a/include/asm-arm/domain.h b/include/asm-arm/domain.h
index 4c2885abbe6..3c12a762530 100644
--- a/include/asm-arm/domain.h
+++ b/include/asm-arm/domain.h
@@ -57,6 +57,7 @@
__asm__ __volatile__( \
"mcr p15, 0, %0, c3, c0 @ set domain" \
: : "r" (x)); \
+ isb(); \
} while (0)
#define modify_domain(dom,type) \
diff --git a/include/asm-arm/hardware/arm_scu.h b/include/asm-arm/hardware/arm_scu.h
index 9903f60c84b..7d28eb5a175 100644
--- a/include/asm-arm/hardware/arm_scu.h
+++ b/include/asm-arm/hardware/arm_scu.h
@@ -1,6 +1,8 @@
#ifndef ASMARM_HARDWARE_ARM_SCU_H
#define ASMARM_HARDWARE_ARM_SCU_H
+#include <asm/arch/scu.h>
+
/*
* SCU registers
*/
diff --git a/include/asm-arm/hardware/cache-l2x0.h b/include/asm-arm/hardware/cache-l2x0.h
new file mode 100644
index 00000000000..54029a74039
--- /dev/null
+++ b/include/asm-arm/hardware/cache-l2x0.h
@@ -0,0 +1,56 @@
+/*
+ * include/asm-arm/hardware/cache-l2x0.h
+ *
+ * Copyright (C) 2007 ARM Limited
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_ARM_HARDWARE_L2X0_H
+#define __ASM_ARM_HARDWARE_L2X0_H
+
+#define L2X0_CACHE_ID 0x000
+#define L2X0_CACHE_TYPE 0x004
+#define L2X0_CTRL 0x100
+#define L2X0_AUX_CTRL 0x104
+#define L2X0_EVENT_CNT_CTRL 0x200
+#define L2X0_EVENT_CNT1_CFG 0x204
+#define L2X0_EVENT_CNT0_CFG 0x208
+#define L2X0_EVENT_CNT1_VAL 0x20C
+#define L2X0_EVENT_CNT0_VAL 0x210
+#define L2X0_INTR_MASK 0x214
+#define L2X0_MASKED_INTR_STAT 0x218
+#define L2X0_RAW_INTR_STAT 0x21C
+#define L2X0_INTR_CLEAR 0x220
+#define L2X0_CACHE_SYNC 0x730
+#define L2X0_INV_LINE_PA 0x770
+#define L2X0_INV_WAY 0x77C
+#define L2X0_CLEAN_LINE_PA 0x7B0
+#define L2X0_CLEAN_LINE_IDX 0x7B8
+#define L2X0_CLEAN_WAY 0x7BC
+#define L2X0_CLEAN_INV_LINE_PA 0x7F0
+#define L2X0_CLEAN_INV_LINE_IDX 0x7F8
+#define L2X0_CLEAN_INV_WAY 0x7FC
+#define L2X0_LOCKDOWN_WAY_D 0x900
+#define L2X0_LOCKDOWN_WAY_I 0x904
+#define L2X0_TEST_OPERATION 0xF00
+#define L2X0_LINE_DATA 0xF10
+#define L2X0_LINE_TAG 0xF30
+#define L2X0_DEBUG_CTRL 0xF40
+
+#ifndef __ASSEMBLY__
+extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
+#endif
+
+#endif
diff --git a/include/asm-arm/hardware/gic.h b/include/asm-arm/hardware/gic.h
index 3fa5eb70f64..966e428ad32 100644
--- a/include/asm-arm/hardware/gic.h
+++ b/include/asm-arm/hardware/gic.h
@@ -33,8 +33,9 @@
#define GIC_DIST_SOFTINT 0xf00
#ifndef __ASSEMBLY__
-void gic_dist_init(void __iomem *base);
-void gic_cpu_init(void __iomem *base);
+void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start);
+void gic_cpu_init(unsigned int gic_nr, void __iomem *base);
+void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
void gic_raise_softirq(cpumask_t cpumask, unsigned int irq);
#endif
diff --git a/include/asm-arm/hardware/iop3xx.h b/include/asm-arm/hardware/iop3xx.h
index 13ac8a4cd01..c91b546e20e 100644
--- a/include/asm-arm/hardware/iop3xx.h
+++ b/include/asm-arm/hardware/iop3xx.h
@@ -37,6 +37,13 @@ extern void gpio_line_set(int line, int value);
#define IOP3XX_PERIPHERAL_PHYS_BASE 0xffffe000
#define IOP3XX_PERIPHERAL_VIRT_BASE 0xfeffe000
#define IOP3XX_PERIPHERAL_SIZE 0x00002000
+#define IOP3XX_PERIPHERAL_UPPER_PA (IOP3XX_PERIPHERAL_PHYS_BASE +\
+ IOP3XX_PERIPHERAL_SIZE - 1)
+#define IOP3XX_PERIPHERAL_UPPER_VA (IOP3XX_PERIPHERAL_VIRT_BASE +\
+ IOP3XX_PERIPHERAL_SIZE - 1)
+#define IOP3XX_PMMR_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\
+ (IOP3XX_PERIPHERAL_PHYS_BASE\
+ - IOP3XX_PERIPHERAL_VIRT_BASE))
#define IOP3XX_REG_ADDR(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + (reg))
/* Address Translation Unit */
@@ -258,12 +265,20 @@ extern void gpio_line_set(int line, int value);
#define IOP3XX_PCI_LOWER_IO_PA 0x90000000
#define IOP3XX_PCI_LOWER_IO_VA 0xfe000000
#define IOP3XX_PCI_LOWER_IO_BA (*IOP3XX_OIOWTVR)
+#define IOP3XX_PCI_UPPER_IO_PA (IOP3XX_PCI_LOWER_IO_PA +\
+ IOP3XX_PCI_IO_WINDOW_SIZE - 1)
+#define IOP3XX_PCI_UPPER_IO_VA (IOP3XX_PCI_LOWER_IO_VA +\
+ IOP3XX_PCI_IO_WINDOW_SIZE - 1)
+#define IOP3XX_PCI_IO_PHYS_TO_VIRT(addr) (((u32) addr -\
+ IOP3XX_PCI_LOWER_IO_PA) +\
+ IOP3XX_PCI_LOWER_IO_VA)
#ifndef __ASSEMBLY__
void iop3xx_map_io(void);
void iop3xx_init_time(unsigned long);
unsigned long iop3xx_gettimeoffset(void);
+void iop_init_cp6_handler(void);
extern struct platform_device iop3xx_i2c0_device;
extern struct platform_device iop3xx_i2c1_device;
diff --git a/include/asm-arm/hardware/sa1111.h b/include/asm-arm/hardware/sa1111.h
index 6aa0a5b75b6..61b1d05c7df 100644
--- a/include/asm-arm/hardware/sa1111.h
+++ b/include/asm-arm/hardware/sa1111.h
@@ -29,6 +29,9 @@
#define _SA1111(x) ((x) + sa1111->resource.start)
#endif
+#define sa1111_writel(val,addr) __raw_writel(val, addr)
+#define sa1111_readl(addr) __raw_readl(addr)
+
/*
* 26 bits of the SA-1110 address bus are available to the SA-1111.
* Use these when feeding target addresses to the DMA engines.
@@ -45,14 +48,6 @@
#define SA1111_SAC_DMA_MIN_XFER (0x800)
/*
- * SA1111 register definitions.
- */
-#define __CCREG(x) __REGP(SA1111_VBASE + (x))
-
-#define sa1111_writel(val,addr) __raw_writel(val, addr)
-#define sa1111_readl(addr) __raw_readl(addr)
-
-/*
* System Bus Interface (SBI)
*
* Registers
@@ -194,55 +189,37 @@
* SADR Serial Audio Data Register (16 x 32-bit)
*/
-#define _SACR0 _SA1111( 0x0600 )
-#define _SACR1 _SA1111( 0x0604 )
-#define _SACR2 _SA1111( 0x0608 )
-#define _SASR0 _SA1111( 0x060c )
-#define _SASR1 _SA1111( 0x0610 )
-#define _SASCR _SA1111( 0x0618 )
-#define _L3_CAR _SA1111( 0x061c )
-#define _L3_CDR _SA1111( 0x0620 )
-#define _ACCAR _SA1111( 0x0624 )
-#define _ACCDR _SA1111( 0x0628 )
-#define _ACSAR _SA1111( 0x062c )
-#define _ACSDR _SA1111( 0x0630 )
-#define _SADTCS _SA1111( 0x0634 )
-#define _SADTSA _SA1111( 0x0638 )
-#define _SADTCA _SA1111( 0x063c )
-#define _SADTSB _SA1111( 0x0640 )
-#define _SADTCB _SA1111( 0x0644 )
-#define _SADRCS _SA1111( 0x0648 )
-#define _SADRSA _SA1111( 0x064c )
-#define _SADRCA _SA1111( 0x0650 )
-#define _SADRSB _SA1111( 0x0654 )
-#define _SADRCB _SA1111( 0x0658 )
-#define _SAITR _SA1111( 0x065c )
-#define _SADR _SA1111( 0x0680 )
-
-#define SACR0 __CCREG(0x0600)
-#define SACR1 __CCREG(0x0604)
-#define SACR2 __CCREG(0x0608)
-#define SASR0 __CCREG(0x060c)
-#define SASR1 __CCREG(0x0610)
-#define SASCR __CCREG(0x0618)
-#define L3_CAR __CCREG(0x061c)
-#define L3_CDR __CCREG(0x0620)
-#define ACCAR __CCREG(0x0624)
-#define ACCDR __CCREG(0x0628)
-#define ACSAR __CCREG(0x062c)
-#define ACSDR __CCREG(0x0630)
-#define SADTCS __CCREG(0x0634)
-#define SADTSA __CCREG(0x0638)
-#define SADTCA __CCREG(0x063c)
-#define SADTSB __CCREG(0x0640)
-#define SADTCB __CCREG(0x0644)
-#define SADRCS __CCREG(0x0648)
-#define SADRSA __CCREG(0x064c)
-#define SADRCA __CCREG(0x0650)
-#define SADRSB __CCREG(0x0654)
-#define SADRCB __CCREG(0x0658)
-#define SAITR __CCREG(0x065c)
-#define SADR __CCREG(0x0680)
+#define SA1111_SERAUDIO 0x0600
+
+/*
+ * These are offsets from the above base.
+ */
+#define SA1111_SACR0 0x00
+#define SA1111_SACR1 0x04
+#define SA1111_SACR2 0x08
+#define SA1111_SASR0 0x0c
+#define SA1111_SASR1 0x10
+#define SA1111_SASCR 0x18
+#define SA1111_L3_CAR 0x1c
+#define SA1111_L3_CDR 0x20
+#define SA1111_ACCAR 0x24
+#define SA1111_ACCDR 0x28
+#define SA1111_ACSAR 0x2c
+#define SA1111_ACSDR 0x30
+#define SA1111_SADTCS 0x34
+#define SA1111_SADTSA 0x38
+#define SA1111_SADTCA 0x3c
+#define SA1111_SADTSB 0x40
+#define SA1111_SADTCB 0x44
+#define SA1111_SADRCS 0x48
+#define SA1111_SADRSA 0x4c
+#define SA1111_SADRCA 0x50
+#define SA1111_SADRSB 0x54
+#define SA1111_SADRCB 0x58
+#define SA1111_SAITR 0x5c
+#define SA1111_SADR 0x80
+
+#ifndef CONFIG_ARCH_PXA
#define SACR0_ENB (1<<0)
#define SACR0_BCKD (1<<2)
@@ -330,6 +307,8 @@
#define SAITR_RDBDA (1<<10)
#define SAITR_RDBDB (1<<11)
+#endif /* !CONFIG_ARCH_PXA */
+
/*
* General-Purpose I/O Interface
*
diff --git a/include/asm-arm/kexec.h b/include/asm-arm/kexec.h
new file mode 100644
index 00000000000..8c1c6162a80
--- /dev/null
+++ b/include/asm-arm/kexec.h
@@ -0,0 +1,30 @@
+#ifndef _ARM_KEXEC_H
+#define _ARM_KEXEC_H
+
+#ifdef CONFIG_KEXEC
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
+
+#define KEXEC_CONTROL_CODE_SIZE 4096
+
+#define KEXEC_ARCH KEXEC_ARCH_ARM
+
+#ifndef __ASSEMBLY__
+
+#define MAX_NOTE_BYTES 1024
+
+struct kimage;
+/* Provide a dummy definition to avoid build failures. */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+ struct pt_regs *oldregs) { }
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_KEXEC */
+
+#endif /* _ARM_KEXEC_H */
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index b8cf2d5ec30..7b2bafce21a 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -175,19 +175,29 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#ifndef __ASSEMBLY__
/*
- * The following macros handle the cache and bufferable bits...
+ * The pgprot_* and protection_map entries will be fixed up in runtime
+ * to include the cachable and bufferable bits based on memory policy,
+ * as well as any architecture dependent bits like global/ASID and SMP
+ * shared mapping bits.
*/
#define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_CACHEABLE | L_PTE_BUFFERABLE
#define _L_PTE_READ L_PTE_USER | L_PTE_EXEC
+extern pgprot_t pgprot_user;
extern pgprot_t pgprot_kernel;
-#define PAGE_NONE __pgprot(_L_PTE_DEFAULT)
-#define PAGE_COPY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
-#define PAGE_SHARED __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE)
-#define PAGE_READONLY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+#define PAGE_NONE pgprot_user
+#define PAGE_COPY __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ)
+#define PAGE_SHARED __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ | \
+ L_PTE_WRITE)
+#define PAGE_READONLY __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ)
#define PAGE_KERNEL pgprot_kernel
+#define __PAGE_NONE __pgprot(_L_PTE_DEFAULT)
+#define __PAGE_COPY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+#define __PAGE_SHARED __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE)
+#define __PAGE_READONLY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+
#endif /* __ASSEMBLY__ */
/*
@@ -198,23 +208,23 @@ extern pgprot_t pgprot_kernel;
* 2) If we could do execute protection, then read is implied
* 3) write implies read permissions
*/
-#define __P000 PAGE_NONE
-#define __P001 PAGE_READONLY
-#define __P010 PAGE_COPY
-#define __P011 PAGE_COPY
-#define __P100 PAGE_READONLY
-#define __P101 PAGE_READONLY
-#define __P110 PAGE_COPY
-#define __P111 PAGE_COPY
-
-#define __S000 PAGE_NONE
-#define __S001 PAGE_READONLY
-#define __S010 PAGE_SHARED
-#define __S011 PAGE_SHARED
-#define __S100 PAGE_READONLY
-#define __S101 PAGE_READONLY
-#define __S110 PAGE_SHARED
-#define __S111 PAGE_SHARED
+#define __P000 __PAGE_NONE
+#define __P001 __PAGE_READONLY
+#define __P010 __PAGE_COPY
+#define __P011 __PAGE_COPY
+#define __P100 __PAGE_READONLY
+#define __P101 __PAGE_READONLY
+#define __P110 __PAGE_COPY
+#define __P111 __PAGE_COPY
+
+#define __S000 __PAGE_NONE
+#define __S001 __PAGE_READONLY
+#define __S010 __PAGE_SHARED
+#define __S011 __PAGE_SHARED
+#define __S100 __PAGE_READONLY
+#define __S101 __PAGE_READONLY
+#define __S110 __PAGE_SHARED
+#define __S111 __PAGE_SHARED
#ifndef __ASSEMBLY__
/*
diff --git a/arch/arm/mach-s3c2410/clock.h b/include/asm-arm/plat-s3c24xx/clock.h
index 7f0ea03e1d4..f6135dbb9fa 100644
--- a/arch/arm/mach-s3c2410/clock.h
+++ b/include/asm-arm/plat-s3c24xx/clock.h
@@ -1,4 +1,4 @@
-/*
+/* linux/include/asm-arm/plat-s3c24xx/clock.h
* linux/arch/arm/mach-s3c2410/clock.h
*
* Copyright (c) 2004-2005 Simtec Electronics
diff --git a/arch/arm/mach-s3c2410/common-smdk.h b/include/asm-arm/plat-s3c24xx/common-smdk.h
index 0e3a3be330a..58d9094c935 100644
--- a/arch/arm/mach-s3c2410/common-smdk.h
+++ b/include/asm-arm/plat-s3c24xx/common-smdk.h
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/common-smdk.h
+/* linux/include/asm-arm/plat-s3c24xx/common-smdk.h
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/cpu.h b/include/asm-arm/plat-s3c24xx/cpu.h
index be42e4032a6..15dd1881090 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/include/asm-arm/plat-s3c24xx/cpu.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/cpu.h
+/* linux/include/asm-arm/plat-s3c24xx/cpu.h
*
* Copyright (c) 2004-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -67,3 +67,4 @@ extern struct sysdev_class s3c2410_sysclass;
extern struct sysdev_class s3c2412_sysclass;
extern struct sysdev_class s3c2440_sysclass;
extern struct sysdev_class s3c2442_sysclass;
+extern struct sysdev_class s3c2443_sysclass;
diff --git a/arch/arm/mach-s3c2410/devs.h b/include/asm-arm/plat-s3c24xx/devs.h
index 14fb0bade71..dddf485fc06 100644
--- a/arch/arm/mach-s3c2410/devs.h
+++ b/include/asm-arm/plat-s3c24xx/devs.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/devs.h
+/* linux/include/asm-arm/plat-s3c24xx/devs.h
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/dma.h b/include/asm-arm/plat-s3c24xx/dma.h
index 0ebfe0aab80..2c59406435e 100644
--- a/arch/arm/mach-s3c2410/dma.h
+++ b/include/asm-arm/plat-s3c24xx/dma.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/dma.h
+/* linux/include/asm-arm/plat-s3c24xx/dma.h
*
* Copyright (C) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
@@ -14,6 +14,7 @@ extern struct sysdev_class dma_sysclass;
extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
#define DMA_CH_VALID (1<<31)
+#define DMA_CH_NEVER (1<<30)
struct s3c24xx_dma_addr {
unsigned long from;
@@ -43,3 +44,34 @@ struct s3c24xx_dma_selection {
};
extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
+
+/* struct s3c24xx_dma_order_ch
+ *
+ * channel map for one of the `enum dma_ch` dma channels. the list
+ * entry contains a set of low-level channel numbers, orred with
+ * DMA_CH_VALID, which are checked in the order in the array.
+*/
+
+struct s3c24xx_dma_order_ch {
+ unsigned int list[S3C2410_DMA_CHANNELS]; /* list of channels */
+ unsigned int flags; /* flags */
+};
+
+/* struct s3c24xx_dma_order
+ *
+ * information provided by either the core or the board to give the
+ * dma system a hint on how to allocate channels
+*/
+
+struct s3c24xx_dma_order {
+ struct s3c24xx_dma_order_ch channels[DMACH_MAX];
+};
+
+extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
+
+/* DMA init code, called from the cpu support code */
+
+extern int s3c2410_dma_init(void);
+
+extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
+ unsigned int stride);
diff --git a/arch/arm/mach-s3c2410/irq.h b/include/asm-arm/plat-s3c24xx/irq.h
index e5913da3b91..8af6d9579b3 100644
--- a/arch/arm/mach-s3c2410/irq.h
+++ b/include/asm-arm/plat-s3c24xx/irq.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/irq.h
+/* linux/include/asm-arm/plat-s3c24xx/irq.h
*
* Copyright (c) 2004-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/pm.h b/include/asm-arm/plat-s3c24xx/pm.h
index ffe197a119f..cc623667e48 100644
--- a/arch/arm/mach-s3c2410/pm.h
+++ b/include/asm-arm/plat-s3c24xx/pm.h
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/pm.h
+/* linux/include/asm-arm/plat-s3c24xx/pm.h
*
* Copyright (c) 2004 Simtec Electronics
* Written by Ben Dooks, <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/s3c2400.h b/include/asm-arm/plat-s3c24xx/s3c2400.h
index 8b2394e1ed4..3a5a16821af 100644
--- a/arch/arm/mach-s3c2410/s3c2400.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2400.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2400.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2400.h
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/include/asm-arm/plat-s3c24xx/s3c2410.h
index fbed084f26d..36de0b83587 100644
--- a/arch/arm/mach-s3c2410/s3c2410.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2410.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2410.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2410.h
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/include/asm-arm/plat-s3c24xx/s3c2412.h
index c6e56032a6e..3ec97685e78 100644
--- a/arch/arm/mach-s3c2410/s3c2412.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2412.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2412.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2412.h
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/s3c2440.h b/include/asm-arm/plat-s3c24xx/s3c2440.h
index dcd316076c5..107853bf948 100644
--- a/arch/arm/mach-s3c2410/s3c2440.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2440.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2440.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2440.h
*
* Copyright (c) 2004-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/s3c2442.h b/include/asm-arm/plat-s3c24xx/s3c2442.h
index 0ae37d24866..451a23a2092 100644
--- a/arch/arm/mach-s3c2410/s3c2442.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2442.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2442.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2442.h
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/include/asm-arm/plat-s3c24xx/s3c2443.h b/include/asm-arm/plat-s3c24xx/s3c2443.h
new file mode 100644
index 00000000000..11d83b5c84e
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/s3c2443.h
@@ -0,0 +1,32 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2443 cpu support
+ *
+ * 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2443
+
+struct s3c2410_uartcfg;
+
+extern int s3c2443_init(void);
+
+extern void s3c2443_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2443_init_clocks(int xtal);
+
+extern int s3c2443_baseclk_add(void);
+
+#else
+#define s3c2443_init_clocks NULL
+#define s3c2443_init_uarts NULL
+#define s3c2443_map_io NULL
+#define s3c2443_init NULL
+#endif
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index aa223fc546a..f4386906b20 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -140,6 +140,40 @@ static inline int cpu_is_xsc3(void)
#define cpu_is_xscale() 1
#endif
+#define UDBG_UNDEFINED (1 << 0)
+#define UDBG_SYSCALL (1 << 1)
+#define UDBG_BADABORT (1 << 2)
+#define UDBG_SEGV (1 << 3)
+#define UDBG_BUS (1 << 4)
+
+extern unsigned int user_debug;
+
+#if __LINUX_ARM_ARCH__ >= 4
+#define vectors_high() (cr_alignment & CR_V)
+#else
+#define vectors_high() (0)
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 6
+#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
+ : : "r" (0) : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+ : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
+ : : "r" (0) : "memory")
+#else
+#define isb() __asm__ __volatile__ ("" : : : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+ : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+#endif
+#define mb() dmb()
+#define rmb() mb()
+#define wmb() mb()
+#define read_barrier_depends() do { } while(0)
+#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
+
extern unsigned long cr_no_alignment; /* defined in entry-armv.S */
extern unsigned long cr_alignment; /* defined in entry-armv.S */
@@ -154,6 +188,7 @@ static inline void set_cr(unsigned int val)
{
asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR"
: : "r" (val) : "cc");
+ isb();
}
#ifndef CONFIG_SMP
@@ -176,34 +211,9 @@ static inline void set_copro_access(unsigned int val)
{
asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access"
: : "r" (val) : "cc");
+ isb();
}
-#define UDBG_UNDEFINED (1 << 0)
-#define UDBG_SYSCALL (1 << 1)
-#define UDBG_BADABORT (1 << 2)
-#define UDBG_SEGV (1 << 3)
-#define UDBG_BUS (1 << 4)
-
-extern unsigned int user_debug;
-
-#if __LINUX_ARM_ARCH__ >= 4
-#define vectors_high() (cr_alignment & CR_V)
-#else
-#define vectors_high() (0)
-#endif
-
-#if __LINUX_ARM_ARCH__ >= 6
-#define mb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
- : : "r" (0) : "memory")
-#else
-#define mb() __asm__ __volatile__ ("" : : : "memory")
-#endif
-#define rmb() mb()
-#define wmb() mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
-
/*
* switch_mm() may do a full cache flush over the context switch,
* so enable interrupts over the context switch to avoid high
diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h
index cd10a0b5f8a..08c6991dc9c 100644
--- a/include/asm-arm/tlbflush.h
+++ b/include/asm-arm/tlbflush.h
@@ -247,7 +247,7 @@ static inline void local_flush_tlb_all(void)
const unsigned int __tlb_flag = __cpu_tlb_flags;
if (tlb_flag(TLB_WB))
- asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+ dsb();
if (tlb_flag(TLB_V3_FULL))
asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
@@ -257,6 +257,15 @@ static inline void local_flush_tlb_all(void)
asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
+
+ if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+ TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+ TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+ /* flush the branch target cache */
+ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+ dsb();
+ isb();
+ }
}
static inline void local_flush_tlb_mm(struct mm_struct *mm)
@@ -266,7 +275,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
const unsigned int __tlb_flag = __cpu_tlb_flags;
if (tlb_flag(TLB_WB))
- asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+ dsb();
if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) {
if (tlb_flag(TLB_V3_FULL))
@@ -285,6 +294,14 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc");
if (tlb_flag(TLB_V6_I_ASID))
asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
+
+ if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+ TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+ TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+ /* flush the branch target cache */
+ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+ dsb();
+ }
}
static inline void
@@ -296,7 +313,7 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
if (tlb_flag(TLB_WB))
- asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero));
+ dsb();
if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
if (tlb_flag(TLB_V3_PAGE))
@@ -317,6 +334,14 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
if (tlb_flag(TLB_V6_I_PAGE))
asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
+
+ if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+ TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+ TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+ /* flush the branch target cache */
+ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+ dsb();
+ }
}
static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
@@ -327,7 +352,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
kaddr &= PAGE_MASK;
if (tlb_flag(TLB_WB))
- asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+ dsb();
if (tlb_flag(TLB_V3_PAGE))
asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (kaddr) : "cc");
@@ -347,11 +372,14 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
if (tlb_flag(TLB_V6_I_PAGE))
asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
- /* The ARM ARM states that the completion of a TLB maintenance
- * operation is only guaranteed by a DSB instruction
- */
- if (tlb_flag(TLB_V6_U_PAGE | TLB_V6_D_PAGE | TLB_V6_I_PAGE))
- asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc");
+ if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
+ TLB_V6_I_PAGE | TLB_V6_D_PAGE |
+ TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+ /* flush the branch target cache */
+ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+ dsb();
+ isb();
+ }
}
/*
@@ -369,15 +397,13 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
*/
static inline void flush_pmd_entry(pmd_t *pmd)
{
- const unsigned int zero = 0;
const unsigned int __tlb_flag = __cpu_tlb_flags;
if (tlb_flag(TLB_DCLEAN))
asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pmd"
: : "r" (pmd) : "cc");
if (tlb_flag(TLB_WB))
- asm("mcr p15, 0, %0, c7, c10, 4 @ flush_pmd"
- : : "r" (zero) : "cc");
+ dsb();
}
static inline void clean_pmd_entry(pmd_t *pmd)
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index 97e7060000c..0991b7bc3f7 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -372,6 +372,7 @@
#define __NR_move_pages (__NR_SYSCALL_BASE+344)
#define __NR_getcpu (__NR_SYSCALL_BASE+345)
/* 346 for epoll_pwait */
+#define __NR_sys_kexec_load (__NR_SYSCALL_BASE+347)
/*
* The following SWIs are ARM private.
diff --git a/include/asm-avr32/arch-at32ap/at91_pdc.h b/include/asm-avr32/arch-at32ap/at91_pdc.h
deleted file mode 100644
index 79d6e02fa45..00000000000
--- a/include/asm-avr32/arch-at32ap/at91_pdc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/at91_pdc.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Peripheral Data Controller (PDC) registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * 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.
- */
-
-#ifndef AT91_PDC_H
-#define AT91_PDC_H
-
-#define AT91_PDC_RPR 0x100 /* Receive Pointer Register */
-#define AT91_PDC_RCR 0x104 /* Receive Counter Register */
-#define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */
-#define AT91_PDC_TCR 0x10c /* Transmit Counter Register */
-#define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */
-#define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */
-#define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */
-#define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */
-
-#define AT91_PDC_PTCR 0x120 /* Transfer Control Register */
-#define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */
-#define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */
-#define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */
-#define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */
-
-#define AT91_PDC_PTSR 0x124 /* Transfer Status Register */
-
-#endif
diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h
index 5e657eb8946..449f3f272e0 100644
--- a/include/asm-i386/acpi.h
+++ b/include/asm-i386/acpi.h
@@ -127,6 +127,7 @@ extern int acpi_irq_balance_set(char *str);
#define acpi_ioapic 0
static inline void acpi_noirq_set(void) { }
static inline void acpi_disable_pci(void) { }
+static inline void disable_acpi(void) { }
#endif /* !CONFIG_ACPI */
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h
index f038e33e6d4..2ce4b6b7b34 100644
--- a/include/asm-powerpc/atomic.h
+++ b/include/asm-powerpc/atomic.h
@@ -165,7 +165,8 @@ static __inline__ int atomic_dec_return(atomic_t *v)
return t;
}
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_cmpxchg(v, o, n) \
+ ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
@@ -413,6 +414,43 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
return t;
}
+#define atomic64_cmpxchg(v, o, n) \
+ ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+/**
+ * atomic64_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic64_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+ long t;
+
+ __asm__ __volatile__ (
+ LWSYNC_ON_SMP
+"1: ldarx %0,0,%1 # atomic_add_unless\n\
+ cmpd 0,%0,%3 \n\
+ beq- 2f \n\
+ add %0,%2,%0 \n"
+" stdcx. %0,0,%1 \n\
+ bne- 1b \n"
+ ISYNC_ON_SMP
+" subf %0,%2,%0 \n\
+2:"
+ : "=&r" (t)
+ : "r" (&v->counter), "r" (a), "r" (u)
+ : "cc", "memory");
+
+ return t != u;
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
#endif /* __powerpc64__ */
#include <asm-generic/atomic.h>
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
index d7a1bc1551c..05af081222f 100644
--- a/include/asm-powerpc/dcr-native.h
+++ b/include/asm-powerpc/dcr-native.h
@@ -26,8 +26,8 @@ typedef struct {} dcr_host_t;
#define DCR_MAP_OK(host) (1)
-#define dcr_map(dev, dcr_n, dcr_c) {}
-#define dcr_unmap(host, dcr_n, dcr_c) {}
+#define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){})
+#define dcr_unmap(host, dcr_n, dcr_c) do {} while (0)
#define dcr_read(host, dcr_n) mfdcr(dcr_n)
#define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value)
diff --git a/include/asm-powerpc/pmi.h b/include/asm-powerpc/pmi.h
new file mode 100644
index 00000000000..cb0f8aa4308
--- /dev/null
+++ b/include/asm-powerpc/pmi.h
@@ -0,0 +1,67 @@
+#ifndef _POWERPC_PMI_H
+#define _POWERPC_PMI_H
+
+/*
+ * Definitions for talking with PMI device on PowerPC
+ *
+ * PMI (Platform Management Interrupt) is a way to communicate
+ * with the BMC (Baseboard Management Controller) via interrupts.
+ * Unlike IPMI it is bidirectional and has a low latency.
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Christian Krafft <krafft@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __KERNEL__
+
+#include <asm/of_device.h>
+
+#define PMI_TYPE_FREQ_CHANGE 0x01
+#define PMI_READ_TYPE 0
+#define PMI_READ_DATA0 1
+#define PMI_READ_DATA1 2
+#define PMI_READ_DATA2 3
+#define PMI_WRITE_TYPE 4
+#define PMI_WRITE_DATA0 5
+#define PMI_WRITE_DATA1 6
+#define PMI_WRITE_DATA2 7
+
+#define PMI_ACK 0x80
+
+#define PMI_TIMEOUT 100
+
+typedef struct {
+ u8 type;
+ u8 data0;
+ u8 data1;
+ u8 data2;
+} pmi_message_t;
+
+struct pmi_handler {
+ struct list_head node;
+ u8 type;
+ void (*handle_pmi_message) (struct of_device *, pmi_message_t);
+};
+
+void pmi_register_handler(struct of_device *, struct pmi_handler *);
+void pmi_unregister_handler(struct of_device *, struct pmi_handler *);
+
+void pmi_send_message(struct of_device *, pmi_message_t);
+
+#endif /* __KERNEL__ */
+#endif /* _POWERPC_PMI_H */
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 0afee17f33b..020ed015a94 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -255,6 +255,8 @@ extern void kdump_move_device_tree(void);
/* CPU OF node matching */
struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
+/* Get the MAC address */
+extern const void *of_get_mac_address(struct device_node *np);
/*
* OF interrupt mapping
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
index e5982ad4657..821581a8b64 100644
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -355,13 +355,7 @@ extern struct bus_type ps3_system_bus_type;
/* vuart routines */
-struct ps3_vuart_stats {
- unsigned long bytes_written;
- unsigned long bytes_read;
- unsigned long tx_interrupts;
- unsigned long rx_interrupts;
- unsigned long disconnect_interrupts;
-};
+struct ps3_vuart_port_priv;
/**
* struct ps3_vuart_port_device - a device on a vuart port
@@ -370,24 +364,17 @@ struct ps3_vuart_stats {
struct ps3_vuart_port_device {
enum ps3_match_id match_id;
struct device core;
+ struct ps3_vuart_port_priv* priv; /* private driver variables */
- /* private driver variables */
- unsigned int port_number;
- u64 interrupt_mask;
- struct {
- spinlock_t lock;
- struct list_head head;
- } tx_list;
- struct {
- unsigned long bytes_held;
- spinlock_t lock;
- struct list_head head;
- } rx_list;
- struct ps3_vuart_stats stats;
};
int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
+/* system manager */
+
+void ps3_sys_manager_restart(void);
+void ps3_sys_manager_power_off(void);
+
struct ps3_prealloc {
const char *name;
void *address;
diff --git a/include/asm-powerpc/ucc_slow.h b/include/asm-powerpc/ucc_slow.h
index 1babad99c71..fdaac9d762b 100644
--- a/include/asm-powerpc/ucc_slow.h
+++ b/include/asm-powerpc/ucc_slow.h
@@ -150,7 +150,7 @@ struct ucc_slow_info {
int ucc_num;
enum qe_clock rx_clock;
enum qe_clock tx_clock;
- struct ucc_slow *regs;
+ u32 regs;
int irq;
u16 uccm_mask;
int data_mem_part;
@@ -199,9 +199,9 @@ struct ucc_slow_private {
and length for first BD in a frame */
u32 tx_base_offset; /* first BD in Tx BD table offset (In MURAM) */
u32 rx_base_offset; /* first BD in Rx BD table offset (In MURAM) */
- u8 *confBd; /* next BD for confirm after Tx */
- u8 *tx_bd; /* next BD for new Tx request */
- u8 *rx_bd; /* next BD to collect after Rx */
+ struct qe_bd *confBd; /* next BD for confirm after Tx */
+ struct qe_bd *tx_bd; /* next BD for new Tx request */
+ struct qe_bd *rx_bd; /* next BD to collect after Rx */
void *p_rx_frame; /* accumulating receive frame */
u16 *p_ucce; /* a pointer to the event register in memory.
*/
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 815f1fb4ce2..8bcfaa4c66a 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -75,7 +75,7 @@ enum acpi_address_range_id {
typedef int (*acpi_table_handler) (struct acpi_table_header *table);
-typedef int (*acpi_madt_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
+typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
unsigned long acpi_find_rsdp (void);
@@ -85,8 +85,10 @@ int acpi_numa_init (void);
int acpi_table_init (void);
int acpi_table_parse (char *id, acpi_table_handler handler);
-int acpi_table_parse_madt (enum acpi_madt_type id, acpi_madt_entry_handler handler, unsigned int max_entries);
-int acpi_table_parse_srat (enum acpi_srat_type id, acpi_madt_entry_handler handler, unsigned int max_entries);
+int __init acpi_table_parse_entries(char *id, unsigned long table_size,
+ int entry_id, acpi_table_entry_handler handler, unsigned int max_entries);
+int acpi_table_parse_madt (enum acpi_madt_type id, acpi_table_entry_handler handler, unsigned int max_entries);
+int acpi_table_parse_srat (enum acpi_srat_type id, acpi_table_entry_handler handler, unsigned int max_entries);
int acpi_parse_mcfg (struct acpi_table_header *header);
void acpi_table_print_madt_entry (struct acpi_subtable_header *madt);
void acpi_table_print_srat_entry (struct acpi_subtable_header *srat);
diff --git a/include/linux/atmel_pdc.h b/include/linux/atmel_pdc.h
new file mode 100644
index 00000000000..5058a31d2ce
--- /dev/null
+++ b/include/linux/atmel_pdc.h
@@ -0,0 +1,36 @@
+/*
+ * include/linux/atmel_pdc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Peripheral Data Controller (PDC) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * 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.
+ */
+
+#ifndef ATMEL_PDC_H
+#define ATMEL_PDC_H
+
+#define ATMEL_PDC_RPR 0x100 /* Receive Pointer Register */
+#define ATMEL_PDC_RCR 0x104 /* Receive Counter Register */
+#define ATMEL_PDC_TPR 0x108 /* Transmit Pointer Register */
+#define ATMEL_PDC_TCR 0x10c /* Transmit Counter Register */
+#define ATMEL_PDC_RNPR 0x110 /* Receive Next Pointer Register */
+#define ATMEL_PDC_RNCR 0x114 /* Receive Next Counter Register */
+#define ATMEL_PDC_TNPR 0x118 /* Transmit Next Pointer Register */
+#define ATMEL_PDC_TNCR 0x11c /* Transmit Next Counter Register */
+
+#define ATMEL_PDC_PTCR 0x120 /* Transfer Control Register */
+#define ATMEL_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */
+#define ATMEL_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */
+#define ATMEL_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */
+#define ATMEL_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */
+
+#define ATMEL_PDC_PTSR 0x124 /* Transfer Status Register */
+
+#endif
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 047567d34ca..9fa0983d1aa 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -33,6 +33,9 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode,
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
+struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
+ const char *dest);
+
void debugfs_remove(struct dentry *dentry);
struct dentry *debugfs_create_u8(const char *name, mode_t mode,
@@ -70,6 +73,13 @@ static inline struct dentry *debugfs_create_dir(const char *name,
return ERR_PTR(-ENODEV);
}
+static inline struct dentry *debugfs_create_symlink(const char *name,
+ struct dentry *parent,
+ const char *dest)
+{
+ return ERR_PTR(-ENODEV);
+}
+
static inline void debugfs_remove(struct dentry *dentry)
{ }
diff --git a/include/linux/device.h b/include/linux/device.h
index 4cc6c935864..d1a3a27c398 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -2,6 +2,7 @@
* device.h - generic, centralized driver model
*
* Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
+ * Copyright (c) 2004-2007 Greg Kroah-Hartman <gregkh@suse.de>
*
* This file is released under the GPLv2
*
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 04e0fa97ac9..79c028251c7 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -636,7 +636,6 @@ typedef struct ide_drive_s {
unsigned int bios_cyl; /* BIOS/fdisk/LILO number of cyls */
unsigned int cyl; /* "real" number of cyls */
unsigned int drive_data; /* use by tuneproc/selectproc */
- unsigned int usage; /* current "open()" count for drive */
unsigned int failures; /* current failure count */
unsigned int max_failures; /* maximum allowed failure count */
u64 probed_capacity;/* initial reported media capacity (ide-cd only currently) */
@@ -736,23 +735,22 @@ typedef struct hwif_s {
int (*ide_dma_end)(ide_drive_t *drive);
int (*ide_dma_check)(ide_drive_t *drive);
int (*ide_dma_on)(ide_drive_t *drive);
- int (*ide_dma_off_quietly)(ide_drive_t *drive);
+ void (*dma_off_quietly)(ide_drive_t *drive);
int (*ide_dma_test_irq)(ide_drive_t *drive);
- int (*ide_dma_host_on)(ide_drive_t *drive);
- int (*ide_dma_host_off)(ide_drive_t *drive);
+ void (*ide_dma_clear_irq)(ide_drive_t *drive);
+ void (*dma_host_on)(ide_drive_t *drive);
+ void (*dma_host_off)(ide_drive_t *drive);
int (*ide_dma_lostirq)(ide_drive_t *drive);
int (*ide_dma_timeout)(ide_drive_t *drive);
void (*OUTB)(u8 addr, unsigned long port);
void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port);
void (*OUTW)(u16 addr, unsigned long port);
- void (*OUTL)(u32 addr, unsigned long port);
void (*OUTSW)(unsigned long port, void *addr, u32 count);
void (*OUTSL)(unsigned long port, void *addr, u32 count);
u8 (*INB)(unsigned long port);
u16 (*INW)(unsigned long port);
- u32 (*INL)(unsigned long port);
void (*INSW)(unsigned long port, void *addr, u32 count);
void (*INSL)(unsigned long port, void *addr, u32 count);
@@ -774,7 +772,6 @@ typedef struct hwif_s {
unsigned int cursg;
unsigned int cursg_ofs;
- int mmio; /* hosts iomio (0) or custom (2) select */
int rqsize; /* max sectors per request */
int irq; /* our irq number */
@@ -802,12 +799,11 @@ typedef struct hwif_s {
unsigned udma_four : 1; /* 1=ATA-66 capable, 0=default */
unsigned no_lba48 : 1; /* 1 = cannot do LBA48 */
unsigned no_lba48_dma : 1; /* 1 = cannot do LBA48 DMA */
- unsigned no_dsc : 1; /* 0 default, 1 dsc_overlap disabled */
unsigned auto_poll : 1; /* supports nop auto-poll */
unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */
unsigned no_io_32bit : 1; /* 1 = can not do 32-bit IO ops */
unsigned err_stops_fifo : 1; /* 1=data FIFO is cleared by an error */
- unsigned atapi_irq_bogon : 1; /* Generates spurious DMA interrupts in PIO mode */
+ unsigned mmio : 1; /* host uses MMIO */
struct device gendev;
struct completion gendev_rel_comp; /* To deal with device release() */
@@ -1280,8 +1276,9 @@ int ide_in_drive_list(struct hd_driveid *, const struct drive_list_entry *);
int __ide_dma_bad_drive(ide_drive_t *);
int __ide_dma_good_drive(ide_drive_t *);
int ide_use_dma(ide_drive_t *);
-int __ide_dma_off(ide_drive_t *);
+void ide_dma_off(ide_drive_t *);
void ide_dma_verbose(ide_drive_t *);
+int ide_set_dma(ide_drive_t *);
ide_startstop_t ide_dma_intr(ide_drive_t *);
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -1291,9 +1288,9 @@ extern void ide_destroy_dmatable(ide_drive_t *);
extern int ide_release_dma(ide_hwif_t *);
extern void ide_setup_dma(ide_hwif_t *, unsigned long, unsigned int);
-extern int __ide_dma_host_off(ide_drive_t *);
-extern int __ide_dma_off_quietly(ide_drive_t *);
-extern int __ide_dma_host_on(ide_drive_t *);
+void ide_dma_host_off(ide_drive_t *);
+void ide_dma_off_quietly(ide_drive_t *);
+void ide_dma_host_on(ide_drive_t *);
extern int __ide_dma_on(ide_drive_t *);
extern int __ide_dma_check(ide_drive_t *);
extern int ide_dma_setup(ide_drive_t *);
@@ -1305,8 +1302,9 @@ extern int __ide_dma_timeout(ide_drive_t *);
#else
static inline int ide_use_dma(ide_drive_t *drive) { return 0; }
-static inline int __ide_dma_off(ide_drive_t *drive) { return 0; }
+static inline void ide_dma_off(ide_drive_t *drive) { ; }
static inline void ide_dma_verbose(ide_drive_t *drive) { ; }
+static inline int ide_set_dma(ide_drive_t *drive) { return 1; }
#endif /* CONFIG_BLK_DEV_IDEDMA */
#ifndef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -1354,6 +1352,7 @@ extern int ide_dma_enable(ide_drive_t *drive);
extern char *ide_xfer_verbose(u8 xfer_rate);
extern void ide_toggle_bounce(ide_drive_t *drive, int on);
extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
+int ide_use_fast_pio(ide_drive_t *);
u8 ide_dump_status(ide_drive_t *, const char *, u8);
@@ -1367,7 +1366,6 @@ typedef struct ide_pio_data_s {
u8 pio_mode;
u8 use_iordy;
u8 overridden;
- u8 blacklisted;
unsigned int cycle_time;
} ide_pio_data_t;
diff --git a/include/linux/jffs.h b/include/linux/jffs.h
deleted file mode 100644
index 92213215277..00000000000
--- a/include/linux/jffs.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * JFFS -- Journalling Flash File System, Linux implementation.
- *
- * Copyright (C) 1999, 2000 Axis Communications AB.
- *
- * Created by Finn Hakansson <finn@axis.com>.
- *
- * 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.
- *
- * $Id: jffs.h,v 1.20 2001/09/18 21:33:37 dwmw2 Exp $
- *
- * Ported to Linux 2.3.x and MTD:
- * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
- *
- */
-
-#ifndef __LINUX_JFFS_H__
-#define __LINUX_JFFS_H__
-
-#include <linux/types.h>
-#include <linux/completion.h>
-
-#define JFFS_VERSION_STRING "1.0"
-
-/* This is a magic number that is used as an identification number for
- this file system. It is written to the super_block structure. */
-#define JFFS_MAGIC_SB_BITMASK 0x07c0 /* 1984 */
-
-/* This is a magic number that every on-flash raw inode begins with. */
-#define JFFS_MAGIC_BITMASK 0x34383931 /* "1984" */
-
-/* These two bitmasks are the valid ones for the flash memories we have
- for the moment. */
-#define JFFS_EMPTY_BITMASK 0xffffffff
-#define JFFS_DIRTY_BITMASK 0x00000000
-
-/* This is the inode number of the root node. */
-#define JFFS_MIN_INO 1
-
-/* How many slots in the file hash table should we have? */
-#define JFFS_HASH_SIZE 40
-
-/* Don't use more than 254 bytes as the maximum allowed length of a file's
- name due to errors that could occur during the scanning of the flash
- memory. In fact, a name length of 255 or 0xff, could be the result of
- an uncompleted write. For instance, if a raw inode is written to the
- flash memory and there is a power lossage just before the length of
- the name is written, the length 255 would be interpreted as an illegal
- value. */
-#define JFFS_MAX_NAME_LEN 254
-
-/* Commands for ioctl(). */
-#define JFFS_IOCTL_MAGIC 't'
-#define JFFS_PRINT_HASH _IO(JFFS_IOCTL_MAGIC, 90)
-#define JFFS_PRINT_TREE _IO(JFFS_IOCTL_MAGIC, 91)
-#define JFFS_GET_STATUS _IO(JFFS_IOCTL_MAGIC, 92)
-
-/* XXX: This is something that we should try to get rid of in the future. */
-#define JFFS_MODIFY_INODE 0x01
-#define JFFS_MODIFY_NAME 0x02
-#define JFFS_MODIFY_DATA 0x04
-#define JFFS_MODIFY_EXIST 0x08
-
-struct jffs_control;
-
-/* The JFFS raw inode structure: Used for storage on physical media. */
-/* Perhaps the uid, gid, atime, mtime and ctime members should have
- more space due to future changes in the Linux kernel. Anyhow, since
- a user of this filesystem probably have to fix a large number of
- other things, we have decided to not be forward compatible. */
-struct jffs_raw_inode
-{
- __u32 magic; /* A constant magic number. */
- __u32 ino; /* Inode number. */
- __u32 pino; /* Parent's inode number. */
- __u32 version; /* Version number. */
- __u32 mode; /* The file's type or mode. */
- __u16 uid; /* The file's owner. */
- __u16 gid; /* The file's group. */
- __u32 atime; /* Last access time. */
- __u32 mtime; /* Last modification time. */
- __u32 ctime; /* Creation time. */
- __u32 offset; /* Where to begin to write. */
- __u32 dsize; /* Size of the node's data. */
- __u32 rsize; /* How much are going to be replaced? */
- __u8 nsize; /* Name length. */
- __u8 nlink; /* Number of links. */
- __u8 spare : 6; /* For future use. */
- __u8 rename : 1; /* Rename to a name of an already existing file? */
- __u8 deleted : 1; /* Has this file been deleted? */
- __u8 accurate; /* The inode is obsolete if accurate == 0. */
- __u32 dchksum; /* Checksum for the data. */
- __u16 nchksum; /* Checksum for the name. */
- __u16 chksum; /* Checksum for the raw inode. */
-};
-
-/* Define the offset of the accurate byte in struct jffs_raw_inode. */
-#define JFFS_RAW_INODE_ACCURATE_OFFSET (sizeof(struct jffs_raw_inode) \
- - 2 * sizeof(__u32) - sizeof(__u8))
-
-/* Define the offset of the chksum member in struct jffs_raw_inode. */
-#define JFFS_RAW_INODE_CHKSUM_OFFSET (sizeof(struct jffs_raw_inode) \
- - sizeof(__u16))
-
-/* Define the offset of the dchksum member in struct jffs_raw_inode. */
-#define JFFS_RAW_INODE_DCHKSUM_OFFSET (sizeof(struct jffs_raw_inode) \
- - sizeof(__u16) - sizeof(__u16) \
- - sizeof(__u32))
-
-
-/* The RAM representation of the node. The names of pointers to
- jffs_nodes are very often just called `n' in the source code. */
-struct jffs_node
-{
- __u32 ino; /* Inode number. */
- __u32 version; /* Version number. */
- __u32 data_offset; /* Logic location of the data to insert. */
- __u32 data_size; /* The amount of data this node inserts. */
- __u32 removed_size; /* The amount of data that this node removes. */
- __u32 fm_offset; /* Physical location of the data in the actual
- flash memory data chunk. */
- __u8 name_size; /* Size of the name. */
- struct jffs_fm *fm; /* Physical memory information. */
- struct jffs_node *version_prev;
- struct jffs_node *version_next;
- struct jffs_node *range_prev;
- struct jffs_node *range_next;
-};
-
-
-/* The RAM representation of a file (plain files, directories,
- links, etc.). Pointers to jffs_files are normally named `f'
- in the JFFS source code. */
-struct jffs_file
-{
- __u32 ino; /* Inode number. */
- __u32 pino; /* Parent's inode number. */
- __u32 mode; /* file_type, mode */
- __u16 uid; /* owner */
- __u16 gid; /* group */
- __u32 atime; /* Last access time. */
- __u32 mtime; /* Last modification time. */
- __u32 ctime; /* Creation time. */
- __u8 nsize; /* Name length. */
- __u8 nlink; /* Number of links. */
- __u8 deleted; /* Has this file been deleted? */
- char *name; /* The name of this file; NULL-terminated. */
- __u32 size; /* The total size of the file's data. */
- __u32 highest_version; /* The highest version number of this file. */
- struct jffs_control *c;
- struct jffs_file *parent; /* Reference to the parent directory. */
- struct jffs_file *children; /* Always NULL for plain files. */
- struct jffs_file *sibling_prev; /* Siblings in the same directory. */
- struct jffs_file *sibling_next;
- struct list_head hash; /* hash list. */
- struct jffs_node *range_head; /* The final data. */
- struct jffs_node *range_tail; /* The first data. */
- struct jffs_node *version_head; /* The youngest node. */
- struct jffs_node *version_tail; /* The oldest node. */
-};
-
-
-/* This is just a definition of a simple list used for keeping track of
- files deleted due to a rename. This list is only used during the
- mounting of the file system and only if there have been rename operations
- earlier. */
-struct jffs_delete_list
-{
- __u32 ino;
- struct jffs_delete_list *next;
-};
-
-
-/* A struct for the overall file system control. Pointers to
- jffs_control structs are named `c' in the source code. */
-struct jffs_control
-{
- struct super_block *sb; /* Reference to the VFS super block. */
- struct jffs_file *root; /* The root directory file. */
- struct list_head *hash; /* Hash table for finding files by ino. */
- struct jffs_fmcontrol *fmc; /* Flash memory control structure. */
- __u32 hash_len; /* The size of the hash table. */
- __u32 next_ino; /* Next inode number to use for new files. */
- __u16 building_fs; /* Is the file system being built right now? */
- struct jffs_delete_list *delete_list; /* Track deleted files. */
- pid_t thread_pid; /* GC thread's PID */
- struct task_struct *gc_task; /* GC task struct */
- struct completion gc_thread_comp; /* GC thread exit mutex */
- __u32 gc_minfree_threshold; /* GC trigger thresholds */
- __u32 gc_maxdirty_threshold;
-};
-
-
-/* Used to inform about flash status. */
-struct jffs_flash_status
-{
- __u32 size;
- __u32 used;
- __u32 dirty;
- __u32 begin;
- __u32 end;
-};
-
-/* This stuff could be used for finding memory leaks. */
-#define JFFS_MEMORY_DEBUG 0
-
-extern long no_jffs_node;
-#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
-extern long no_jffs_control;
-extern long no_jffs_raw_inode;
-extern long no_jffs_node_ref;
-extern long no_jffs_fm;
-extern long no_jffs_fmcontrol;
-extern long no_hash;
-extern long no_name;
-#define DJM(x) x
-#else
-#define DJM(x)
-#endif
-
-#endif /* __LINUX_JFFS_H__ */
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index d02425cdd80..696e5ec63f7 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -125,6 +125,7 @@ extern struct kimage *kexec_crash_image;
#define KEXEC_ARCH_PPC (20 << 16)
#define KEXEC_ARCH_PPC64 (21 << 16)
#define KEXEC_ARCH_IA_64 (50 << 16)
+#define KEXEC_ARCH_ARM (40 << 16)
#define KEXEC_ARCH_S390 (22 << 16)
#define KEXEC_ARCH_SH (42 << 16)
#define KEXEC_ARCH_MIPS_LE (10 << 16)
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 10f505c8431..cc8e674ae27 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -28,8 +28,10 @@
#ifdef CONFIG_KMOD
/* modprobe exit status on success, -ve on error. Return value
* usually useless though. */
+extern void kmod_sysfs_init(void);
extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2)));
#else
+static inline void kmod_sysfs_init(void) {};
static inline int request_module(const char * name, ...) { return -ENOSYS; }
#endif
diff --git a/include/linux/libata.h b/include/linux/libata.h
index b870b20df43..86762a9f52b 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -35,6 +35,7 @@
#include <linux/ata.h>
#include <linux/workqueue.h>
#include <scsi/scsi_host.h>
+#include <linux/acpi.h>
/*
* Define if arch has non-standard setup. This is a _PCI_ standard
@@ -495,6 +496,10 @@ struct ata_device {
/* error history */
struct ata_ering ering;
unsigned int horkage; /* List of broken features */
+#ifdef CONFIG_SATA_ACPI
+ /* ACPI objects info */
+ acpi_handle obj_handle;
+#endif
};
/* Offset into struct ata_device. Fields above it are maintained
diff --git a/include/linux/module.h b/include/linux/module.h
index 419d3ef293d..95679eb8571 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -76,8 +76,6 @@ void sort_extable(struct exception_table_entry *start,
struct exception_table_entry *finish);
void sort_main_extable(void);
-extern struct subsystem module_subsys;
-
#ifdef MODULE
#define MODULE_GENERIC_TABLE(gtype,name) \
extern const struct gtype##_id __mod_##gtype##_table \
@@ -467,10 +465,6 @@ int unregister_module_notifier(struct notifier_block * nb);
extern void print_modules(void);
-struct device_driver;
-void module_add_driver(struct module *, struct device_driver *);
-void module_remove_driver(struct device_driver *);
-
#else /* !CONFIG_MODULES... */
#define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym)
@@ -568,18 +562,59 @@ static inline void print_modules(void)
{
}
+#endif /* CONFIG_MODULES */
+
struct device_driver;
+#ifdef CONFIG_SYSFS
struct module;
-static inline void module_add_driver(struct module *module, struct device_driver *driver)
+extern struct subsystem module_subsys;
+
+int mod_sysfs_init(struct module *mod);
+int mod_sysfs_setup(struct module *mod,
+ struct kernel_param *kparam,
+ unsigned int num_params);
+int module_add_modinfo_attrs(struct module *mod);
+void module_remove_modinfo_attrs(struct module *mod);
+
+#else /* !CONFIG_SYSFS */
+
+static inline int mod_sysfs_init(struct module *mod)
{
+ return 0;
}
-static inline void module_remove_driver(struct device_driver *driver)
+static inline int mod_sysfs_setup(struct module *mod,
+ struct kernel_param *kparam,
+ unsigned int num_params)
{
+ return 0;
}
-#endif /* CONFIG_MODULES */
+static inline int module_add_modinfo_attrs(struct module *mod)
+{
+ return 0;
+}
+
+static inline void module_remove_modinfo_attrs(struct module *mod)
+{ }
+
+#endif /* CONFIG_SYSFS */
+
+#if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES)
+
+void module_add_driver(struct module *mod, struct device_driver *drv);
+void module_remove_driver(struct device_driver *drv);
+
+#else /* not both CONFIG_SYSFS && CONFIG_MODULES */
+
+static inline void module_add_driver(struct module *mod, struct device_driver *drv)
+{ }
+
+static inline void module_remove_driver(struct device_driver *drv)
+{ }
+
+#endif
#define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index bb151bcaad4..c83588c8d08 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -169,10 +169,22 @@ extern int param_get_string(char *buffer, struct kernel_param *kp);
struct module;
+#if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES)
extern int module_param_sysfs_setup(struct module *mod,
struct kernel_param *kparam,
unsigned int num_params);
extern void module_param_sysfs_remove(struct module *mod);
+#else
+static inline int module_param_sysfs_setup(struct module *mod,
+ struct kernel_param *kparam,
+ unsigned int num_params)
+{
+ return 0;
+}
+
+static inline void module_param_sysfs_remove(struct module *mod)
+{ }
+#endif
#endif /* _LINUX_MODULE_PARAMS_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 98c8765a488..2c4b6842dfb 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -854,5 +854,8 @@ extern int pci_pci_problems;
#define PCIPCI_ALIMAGIK 32 /* Need low latency setting */
#define PCIAGP_FAIL 64 /* No PCI to AGP DMA */
+extern unsigned long pci_cardbus_io_size;
+extern unsigned long pci_cardbus_mem_size;
+
#endif /* __KERNEL__ */
#endif /* LINUX_PCI_H */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 182a96f77c8..600308fdf9c 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2089,6 +2089,7 @@
#define PCI_VENDOR_ID_PASEMI 0x1959
#define PCI_VENDOR_ID_ATTANSIC 0x1969
+#define PCI_DEVICE_ID_ATTANSIC_L1 0x1048
#define PCI_VENDOR_ID_JMICRON 0x197B
#define PCI_DEVICE_ID_JMICRON_JMB360 0x2360
diff --git a/include/linux/usb.h b/include/linux/usb.h
index b5c226a87ed..a8e8d1ecebb 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -935,7 +935,7 @@ struct usb_iso_packet_descriptor {
unsigned int offset;
unsigned int length; /* expected length */
unsigned int actual_length;
- unsigned int status;
+ int status;
};
struct urb;
diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
index ba617c37245..956edf3bbec 100644
--- a/include/linux/usb/cdc.h
+++ b/include/linux/usb/cdc.h
@@ -73,6 +73,13 @@ struct usb_cdc_acm_descriptor {
__u8 bmCapabilities;
} __attribute__ ((packed));
+/* capabilities from 5.2.3.3 */
+
+#define USB_CDC_COMM_FEATURE 0x01
+#define USB_CDC_CAP_LINE 0x02
+#define USB_CDC_CAP_BRK 0x04
+#define USB_CDC_CAP_NOTIFY 0x08
+
/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
struct usb_cdc_union_desc {
__u8 bLength;
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index ae7833749fa..245c7253122 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -367,7 +367,7 @@ struct usb_debug_descriptor {
/* bulk endpoints with 8 byte maxpacket */
__u8 bDebugInEndpoint;
__u8 bDebugOutEndpoint;
-};
+} __attribute__((packed));
/*-------------------------------------------------------------------------*/
@@ -396,7 +396,7 @@ struct usb_security_descriptor {
__le16 wTotalLength;
__u8 bNumEncryptionTypes;
-};
+} __attribute__((packed));
/*-------------------------------------------------------------------------*/
@@ -410,7 +410,7 @@ struct usb_key_descriptor {
__u8 tTKID[3];
__u8 bReserved;
__u8 bKeyData[0];
-};
+} __attribute__((packed));
/*-------------------------------------------------------------------------*/
@@ -426,7 +426,7 @@ struct usb_encryption_descriptor {
#define USB_ENC_TYPE_RSA_1 3 /* rsa3072/sha1 auth */
__u8 bEncryptionValue; /* use in SET_ENCRYPTION */
__u8 bAuthKeyIndex;
-};
+} __attribute__((packed));
/*-------------------------------------------------------------------------*/
@@ -438,7 +438,7 @@ struct usb_bos_descriptor {
__le16 wTotalLength;
__u8 bNumDeviceCaps;
-};
+} __attribute__((packed));
/*-------------------------------------------------------------------------*/
@@ -447,7 +447,7 @@ struct usb_dev_cap_header {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDevCapabilityType;
-};
+} __attribute__((packed));
#define USB_CAP_TYPE_WIRELESS_USB 1
@@ -475,7 +475,7 @@ struct usb_wireless_cap_descriptor { /* Ultra Wide Band */
__u8 bmFFITXPowerInfo; /* FFI power levels */
__le16 bmBandGroup;
__u8 bReserved;
-};
+} __attribute__((packed));
/*-------------------------------------------------------------------------*/
@@ -496,7 +496,7 @@ struct usb_wireless_ep_comp_descriptor {
#define USB_ENDPOINT_SWITCH_NO 0
#define USB_ENDPOINT_SWITCH_SWITCH 1
#define USB_ENDPOINT_SWITCH_SCALE 2
-};
+} __attribute__((packed));
/*-------------------------------------------------------------------------*/
@@ -512,7 +512,7 @@ struct usb_handshake {
__u8 CDID[16];
__u8 nonce[16];
__u8 MIC[8];
-};
+} __attribute__((packed));
/*-------------------------------------------------------------------------*/
@@ -524,7 +524,7 @@ struct usb_connection_context {
__u8 CHID[16]; /* persistent host id */
__u8 CDID[16]; /* device id (unique w/in host context) */
__u8 CK[16]; /* connection key */
-};
+} __attribute__((packed));
/*-------------------------------------------------------------------------*/
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 33dcd857669..32acbae28d2 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -54,6 +54,8 @@
* @write_wait: a wait_queue_head_t used by the port.
* @work: work queue entry for the line discipline waking up.
* @open_count: number of times this port has been opened.
+ * @throttled: nonzero if the read urb is inactive to throttle the device
+ * @throttle_req: nonzero if the tty wants to throttle us
*
* This structure is used by the usb-serial core and drivers for the specific
* ports of a device.
@@ -88,6 +90,8 @@ struct usb_serial_port {
wait_queue_head_t write_wait;
struct work_struct work;
int open_count;
+ char throttled;
+ char throttle_req;
struct device dev;
};
#define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
@@ -269,6 +273,8 @@ extern int usb_serial_generic_write_room (struct usb_serial_port *port);
extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
extern void usb_serial_generic_read_bulk_callback (struct urb *urb);
extern void usb_serial_generic_write_bulk_callback (struct urb *urb);
+extern void usb_serial_generic_throttle (struct usb_serial_port *port);
+extern void usb_serial_generic_unthrottle (struct usb_serial_port *port);
extern void usb_serial_generic_shutdown (struct usb_serial *serial);
extern int usb_serial_generic_register (int debug);
extern void usb_serial_generic_deregister (void);
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index 2ae76fe52ff..1b792b9286b 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -46,7 +46,9 @@
US_FLAG(MAX_SECTORS_64, 0x00000400) \
/* Sets max_sectors to 64 */ \
US_FLAG(IGNORE_DEVICE, 0x00000800) \
- /* Don't claim device */
+ /* Don't claim device */ \
+ US_FLAG(CAPACITY_HEURISTICS, 0x00001000) \
+ /* sometimes sizes is too big */
#define US_FLAG(name, value) US_FL_##name = value ,
enum { US_DO_ALL_FLAGS };
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index 617d8a1c59a..342dd5a7e8b 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -159,9 +159,9 @@ struct usbdevfs_ioctl32 {
#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32)
#define USBDEVFS_DISCARDURB _IO('U', 11)
#define USBDEVFS_REAPURB _IOW('U', 12, void *)
-#define USBDEVFS_REAPURB32 _IOW('U', 12, u32)
+#define USBDEVFS_REAPURB32 _IOW('U', 12, __u32)
#define USBDEVFS_REAPURBNDELAY _IOW('U', 13, void *)
-#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32)
+#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, __u32)
#define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal)
#define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int)
#define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int)
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index c1da8558339..eae7e2e8449 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -95,6 +95,7 @@
#define PRODID_QUATECH_DUAL_RS232 0x0012
#define PRODID_QUATECH_DUAL_RS232_D1 0x0007
#define PRODID_QUATECH_DUAL_RS232_D2 0x0052
+#define PRODID_QUATECH_DUAL_RS232_G 0x004d
#define PRODID_QUATECH_QUAD_RS232 0x001b
#define PRODID_QUATECH_DUAL_RS422 0x000e
#define PRODID_QUATECH_QUAD_RS422 0x0045
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h
index c094e501286..c36750ff6ae 100644
--- a/include/rdma/ib_addr.h
+++ b/include/rdma/ib_addr.h
@@ -110,6 +110,12 @@ static inline void ib_addr_set_pkey(struct rdma_dev_addr *dev_addr, u16 pkey)
dev_addr->broadcast[9] = (unsigned char) pkey;
}
+static inline void ib_addr_get_mgid(struct rdma_dev_addr *dev_addr,
+ union ib_gid *gid)
+{
+ memcpy(gid, dev_addr->broadcast + 4, sizeof *gid);
+}
+
static inline void ib_addr_get_sgid(struct rdma_dev_addr *dev_addr,
union ib_gid *gid)
{
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index 97715b0c20b..5e26b2f53f8 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -285,18 +285,6 @@ int ib_sa_path_rec_get(struct ib_sa_client *client,
void *context,
struct ib_sa_query **query);
-int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
- struct ib_device *device, u8 port_num,
- u8 method,
- struct ib_sa_mcmember_rec *rec,
- ib_sa_comp_mask comp_mask,
- int timeout_ms, gfp_t gfp_mask,
- void (*callback)(int status,
- struct ib_sa_mcmember_rec *resp,
- void *context),
- void *context,
- struct ib_sa_query **query);
-
int ib_sa_service_rec_query(struct ib_sa_client *client,
struct ib_device *device, u8 port_num,
u8 method,
@@ -309,93 +297,82 @@ int ib_sa_service_rec_query(struct ib_sa_client *client,
void *context,
struct ib_sa_query **sa_query);
+struct ib_sa_multicast {
+ struct ib_sa_mcmember_rec rec;
+ ib_sa_comp_mask comp_mask;
+ int (*callback)(int status,
+ struct ib_sa_multicast *multicast);
+ void *context;
+};
+
/**
- * ib_sa_mcmember_rec_set - Start an MCMember set query
- * @client:SA client
- * @device:device to send query on
- * @port_num: port number to send query on
- * @rec:MCMember Record to send in query
- * @comp_mask:component mask to send in query
- * @timeout_ms:time to wait for response
- * @gfp_mask:GFP mask to use for internal allocations
- * @callback:function called when query completes, times out or is
- * canceled
- * @context:opaque user context passed to callback
- * @sa_query:query context, used to cancel query
+ * ib_sa_join_multicast - Initiates a join request to the specified multicast
+ * group.
+ * @client: SA client
+ * @device: Device associated with the multicast group.
+ * @port_num: Port on the specified device to associate with the multicast
+ * group.
+ * @rec: SA multicast member record specifying group attributes.
+ * @comp_mask: Component mask indicating which group attributes of %rec are
+ * valid.
+ * @gfp_mask: GFP mask for memory allocations.
+ * @callback: User callback invoked once the join operation completes.
+ * @context: User specified context stored with the ib_sa_multicast structure.
*
- * Send an MCMember Set query to the SA (eg to join a multicast
- * group). The callback function will be called when the query
- * completes (or fails); status is 0 for a successful response, -EINTR
- * if the query is canceled, -ETIMEDOUT is the query timed out, or
- * -EIO if an error occurred sending the query. The resp parameter of
- * the callback is only valid if status is 0.
+ * This call initiates a multicast join request with the SA for the specified
+ * multicast group. If the join operation is started successfully, it returns
+ * an ib_sa_multicast structure that is used to track the multicast operation.
+ * Users must free this structure by calling ib_free_multicast, even if the
+ * join operation later fails. (The callback status is non-zero.)
*
- * If the return value of ib_sa_mcmember_rec_set() is negative, it is
- * an error code. Otherwise it is a query ID that can be used to
- * cancel the query.
+ * If the join operation fails; status will be non-zero, with the following
+ * failures possible:
+ * -ETIMEDOUT: The request timed out.
+ * -EIO: An error occurred sending the query.
+ * -EINVAL: The MCMemberRecord values differed from the existing group's.
+ * -ENETRESET: Indicates that an fatal error has occurred on the multicast
+ * group, and the user must rejoin the group to continue using it.
*/
-static inline int
-ib_sa_mcmember_rec_set(struct ib_sa_client *client,
- struct ib_device *device, u8 port_num,
- struct ib_sa_mcmember_rec *rec,
- ib_sa_comp_mask comp_mask,
- int timeout_ms, gfp_t gfp_mask,
- void (*callback)(int status,
- struct ib_sa_mcmember_rec *resp,
- void *context),
- void *context,
- struct ib_sa_query **query)
-{
- return ib_sa_mcmember_rec_query(client, device, port_num,
- IB_MGMT_METHOD_SET,
- rec, comp_mask,
- timeout_ms, gfp_mask, callback,
- context, query);
-}
+struct ib_sa_multicast *ib_sa_join_multicast(struct ib_sa_client *client,
+ struct ib_device *device, u8 port_num,
+ struct ib_sa_mcmember_rec *rec,
+ ib_sa_comp_mask comp_mask, gfp_t gfp_mask,
+ int (*callback)(int status,
+ struct ib_sa_multicast
+ *multicast),
+ void *context);
/**
- * ib_sa_mcmember_rec_delete - Start an MCMember delete query
- * @client:SA client
- * @device:device to send query on
- * @port_num: port number to send query on
- * @rec:MCMember Record to send in query
- * @comp_mask:component mask to send in query
- * @timeout_ms:time to wait for response
- * @gfp_mask:GFP mask to use for internal allocations
- * @callback:function called when query completes, times out or is
- * canceled
- * @context:opaque user context passed to callback
- * @sa_query:query context, used to cancel query
- *
- * Send an MCMember Delete query to the SA (eg to leave a multicast
- * group). The callback function will be called when the query
- * completes (or fails); status is 0 for a successful response, -EINTR
- * if the query is canceled, -ETIMEDOUT is the query timed out, or
- * -EIO if an error occurred sending the query. The resp parameter of
- * the callback is only valid if status is 0.
+ * ib_free_multicast - Frees the multicast tracking structure, and releases
+ * any reference on the multicast group.
+ * @multicast: Multicast tracking structure allocated by ib_join_multicast.
*
- * If the return value of ib_sa_mcmember_rec_delete() is negative, it
- * is an error code. Otherwise it is a query ID that can be used to
- * cancel the query.
+ * This call blocks until the multicast identifier is destroyed. It may
+ * not be called from within the multicast callback; however, returning a non-
+ * zero value from the callback will result in destroying the multicast
+ * tracking structure.
+ */
+void ib_sa_free_multicast(struct ib_sa_multicast *multicast);
+
+/**
+ * ib_get_mcmember_rec - Looks up a multicast member record by its MGID and
+ * returns it if found.
+ * @device: Device associated with the multicast group.
+ * @port_num: Port on the specified device to associate with the multicast
+ * group.
+ * @mgid: MGID of multicast group.
+ * @rec: Location to copy SA multicast member record.
*/
-static inline int
-ib_sa_mcmember_rec_delete(struct ib_sa_client *client,
- struct ib_device *device, u8 port_num,
- struct ib_sa_mcmember_rec *rec,
- ib_sa_comp_mask comp_mask,
- int timeout_ms, gfp_t gfp_mask,
- void (*callback)(int status,
- struct ib_sa_mcmember_rec *resp,
- void *context),
- void *context,
- struct ib_sa_query **query)
-{
- return ib_sa_mcmember_rec_query(client, device, port_num,
- IB_SA_METHOD_DELETE,
- rec, comp_mask,
- timeout_ms, gfp_mask, callback,
- context, query);
-}
+int ib_sa_get_mcmember_rec(struct ib_device *device, u8 port_num,
+ union ib_gid *mgid, struct ib_sa_mcmember_rec *rec);
+
+/**
+ * ib_init_ah_from_mcmember - Initialize address handle attributes based on
+ * an SA multicast member record.
+ */
+int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
+ struct ib_sa_mcmember_rec *rec,
+ struct ib_ah_attr *ah_attr);
/**
* ib_init_ah_from_path - Initialize address handle attributes based on an SA
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
index 36cd8a8526a..2d6a7705eae 100644
--- a/include/rdma/rdma_cm.h
+++ b/include/rdma/rdma_cm.h
@@ -52,10 +52,13 @@ enum rdma_cm_event_type {
RDMA_CM_EVENT_ESTABLISHED,
RDMA_CM_EVENT_DISCONNECTED,
RDMA_CM_EVENT_DEVICE_REMOVAL,
+ RDMA_CM_EVENT_MULTICAST_JOIN,
+ RDMA_CM_EVENT_MULTICAST_ERROR
};
enum rdma_port_space {
RDMA_PS_SDP = 0x0001,
+ RDMA_PS_IPOIB= 0x0002,
RDMA_PS_TCP = 0x0106,
RDMA_PS_UDP = 0x0111,
RDMA_PS_SCTP = 0x0183
@@ -294,5 +297,21 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
*/
int rdma_disconnect(struct rdma_cm_id *id);
-#endif /* RDMA_CM_H */
+/**
+ * rdma_join_multicast - Join the multicast group specified by the given
+ * address.
+ * @id: Communication identifier associated with the request.
+ * @addr: Multicast address identifying the group to join.
+ * @context: User-defined context associated with the join request, returned
+ * to the user through the private_data pointer in multicast events.
+ */
+int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
+ void *context);
+/**
+ * rdma_leave_multicast - Leave the multicast group specified by the given
+ * address.
+ */
+void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr);
+
+#endif /* RDMA_CM_H */
diff --git a/include/rdma/rdma_cm_ib.h b/include/rdma/rdma_cm_ib.h
index 9b176df1d66..950424b38f1 100644
--- a/include/rdma/rdma_cm_ib.h
+++ b/include/rdma/rdma_cm_ib.h
@@ -44,7 +44,7 @@
int rdma_set_ib_paths(struct rdma_cm_id *id,
struct ib_sa_path_rec *path_rec, int num_paths);
-/* Global qkey for UD QPs and multicast groups. */
-#define RDMA_UD_QKEY 0x01234567
+/* Global qkey for UDP QPs and multicast groups. */
+#define RDMA_UDP_QKEY 0x01234567
#endif /* RDMA_CM_IB_H */
diff --git a/include/rdma/rdma_user_cm.h b/include/rdma/rdma_user_cm.h
index 9572ab8eeac..f632b0c007c 100644
--- a/include/rdma/rdma_user_cm.h
+++ b/include/rdma/rdma_user_cm.h
@@ -38,7 +38,7 @@
#include <rdma/ib_user_verbs.h>
#include <rdma/ib_user_sa.h>
-#define RDMA_USER_CM_ABI_VERSION 3
+#define RDMA_USER_CM_ABI_VERSION 4
#define RDMA_MAX_PRIVATE_DATA 256
@@ -58,7 +58,9 @@ enum {
RDMA_USER_CM_CMD_GET_EVENT,
RDMA_USER_CM_CMD_GET_OPTION,
RDMA_USER_CM_CMD_SET_OPTION,
- RDMA_USER_CM_CMD_NOTIFY
+ RDMA_USER_CM_CMD_NOTIFY,
+ RDMA_USER_CM_CMD_JOIN_MCAST,
+ RDMA_USER_CM_CMD_LEAVE_MCAST
};
/*
@@ -188,6 +190,13 @@ struct rdma_ucm_notify {
__u32 event;
};
+struct rdma_ucm_join_mcast {
+ __u64 response; /* rdma_ucm_create_id_resp */
+ __u64 uid;
+ struct sockaddr_in6 addr;
+ __u32 id;
+};
+
struct rdma_ucm_get_event {
__u64 response;
};
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index ebf31b16dc4..9dd37e2f5a8 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -122,6 +122,7 @@ struct scsi_device {
unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
unsigned select_no_atn:1;
unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */
+ unsigned guess_capacity:1; /* READ_CAPACITY might be too high by 1 */
unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */
unsigned int device_blocked; /* Device returned QUEUE_FULL. */
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 796276141e5..9f923f8ce6a 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -36,6 +36,8 @@
#include <linux/resource.h>
#include <asm/uaccess.h>
+extern int delete_module(const char *name, unsigned int flags);
+
extern int max_threads;
static struct workqueue_struct *khelper_wq;
@@ -46,6 +48,7 @@ static struct workqueue_struct *khelper_wq;
modprobe_path is set via /proc/sys.
*/
char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
+struct module_kobject kmod_mk;
/**
* request_module - try to load a kernel module
@@ -75,6 +78,11 @@ int request_module(const char *fmt, ...)
static atomic_t kmod_concurrent = ATOMIC_INIT(0);
#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
static int kmod_loop_msg;
+ char modalias[16 + MODULE_NAME_LEN] = "MODALIAS=";
+ char *uevent_envp[2] = {
+ modalias,
+ NULL
+ };
va_start(args, fmt);
ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
@@ -82,6 +90,12 @@ int request_module(const char *fmt, ...)
if (ret >= MODULE_NAME_LEN)
return -ENAMETOOLONG;
+ strcpy(&modalias[strlen("MODALIAS=")], module_name);
+ kobject_uevent_env(&kmod_mk.kobj, KOBJ_CHANGE, uevent_envp);
+
+ if (modprobe_path[0] == '\0')
+ goto out;
+
/* If modprobe needs a service that is in a module, we get a recursive
* loop. Limit the number of running kmod threads to max_threads/2 or
* MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
@@ -108,9 +122,115 @@ int request_module(const char *fmt, ...)
ret = call_usermodehelper(modprobe_path, argv, envp, 1);
atomic_dec(&kmod_concurrent);
+out:
return ret;
}
EXPORT_SYMBOL(request_module);
+
+static ssize_t store_mod_request(struct module_attribute *mattr,
+ struct module *mod,
+ const char *buffer, size_t count)
+{
+ char name[MODULE_NAME_LEN];
+ int ret;
+
+ if (count < 1 || count+1 > MODULE_NAME_LEN)
+ return -EINVAL;
+ memcpy(name, buffer, count);
+ name[count] = '\0';
+ if (name[count-1] == '\n')
+ name[count-1] = '\0';
+
+ ret = request_module(name);
+ if (ret < 0)
+ return ret;
+ return count;
+}
+
+static struct module_attribute mod_request = {
+ .attr = { .name = "mod_request", .mode = S_IWUSR, .owner = THIS_MODULE },
+ .store = store_mod_request,
+};
+
+#ifdef CONFIG_MODULE_UNLOAD
+static ssize_t store_mod_unload(struct module_attribute *mattr,
+ struct module *mod,
+ const char *buffer, size_t count)
+{
+ char name[MODULE_NAME_LEN];
+ int ret;
+
+ if (count < 1 || count+1 > MODULE_NAME_LEN)
+ return -EINVAL;
+ memcpy(name, buffer, count);
+ name[count] = '\0';
+ if (name[count-1] == '\n')
+ name[count-1] = '\0';
+
+ ret = delete_module(name, O_NONBLOCK);
+ if (ret < 0)
+ return ret;
+ return count;
+}
+
+static struct module_attribute mod_unload = {
+ .attr = { .name = "mod_unload", .mode = S_IWUSR, .owner = THIS_MODULE },
+ .store = store_mod_unload,
+};
+#endif
+
+static ssize_t show_mod_request_helper(struct module_attribute *mattr,
+ struct module *mod,
+ char *buffer)
+{
+ return sprintf(buffer, "%s\n", modprobe_path);
+}
+
+static ssize_t store_mod_request_helper(struct module_attribute *mattr,
+ struct module *mod,
+ const char *buffer, size_t count)
+{
+ if (count < 1 || count+1 > KMOD_PATH_LEN)
+ return -EINVAL;
+ memcpy(modprobe_path, buffer, count);
+ modprobe_path[count] = '\0';
+ if (modprobe_path[count-1] == '\n')
+ modprobe_path[count-1] = '\0';
+ return count;
+}
+
+static struct module_attribute mod_request_helper = {
+ .attr = {
+ .name = "mod_request_helper",
+ .mode = S_IWUSR | S_IRUGO,
+ .owner = THIS_MODULE
+ },
+ .show = show_mod_request_helper,
+ .store = store_mod_request_helper,
+};
+
+void __init kmod_sysfs_init(void)
+{
+ int ret;
+
+ kmod_mk.mod = THIS_MODULE;
+ kobj_set_kset_s(&kmod_mk, module_subsys);
+ kobject_set_name(&kmod_mk.kobj, "kmod");
+ kobject_init(&kmod_mk.kobj);
+ ret = kobject_add(&kmod_mk.kobj);
+ if (ret < 0)
+ goto out;
+
+ ret = sysfs_create_file(&kmod_mk.kobj, &mod_request_helper.attr);
+ ret = sysfs_create_file(&kmod_mk.kobj, &mod_request.attr);
+#ifdef CONFIG_MODULE_UNLOAD
+ ret = sysfs_create_file(&kmod_mk.kobj, &mod_unload.attr);
+#endif
+
+ kobject_uevent(&kmod_mk.kobj, KOBJ_ADD);
+out:
+ return;
+}
#endif /* CONFIG_KMOD */
struct subprocess_info {
diff --git a/kernel/module.c b/kernel/module.c
index 8a94e054230..8c25b1a04fa 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -653,20 +653,11 @@ static void wait_for_zero_refcount(struct module *mod)
mutex_lock(&module_mutex);
}
-asmlinkage long
-sys_delete_module(const char __user *name_user, unsigned int flags)
+int delete_module(const char *name, unsigned int flags)
{
struct module *mod;
- char name[MODULE_NAME_LEN];
int ret, forced = 0;
- if (!capable(CAP_SYS_MODULE))
- return -EPERM;
-
- if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
- return -EFAULT;
- name[MODULE_NAME_LEN-1] = '\0';
-
if (mutex_lock_interruptible(&module_mutex) != 0)
return -EINTR;
@@ -727,6 +718,21 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
return ret;
}
+asmlinkage long
+sys_delete_module(const char __user *name_user, unsigned int flags)
+{
+ char name[MODULE_NAME_LEN];
+
+ if (!capable(CAP_SYS_MODULE))
+ return -EPERM;
+
+ if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
+ return -EFAULT;
+ name[MODULE_NAME_LEN-1] = '\0';
+
+ return delete_module(name, flags);
+}
+
static void print_unload_info(struct seq_file *m, struct module *mod)
{
struct module_use *use;
@@ -1068,7 +1074,8 @@ static inline void remove_sect_attrs(struct module *mod)
}
#endif /* CONFIG_KALLSYMS */
-static int module_add_modinfo_attrs(struct module *mod)
+#ifdef CONFIG_SYSFS
+int module_add_modinfo_attrs(struct module *mod)
{
struct module_attribute *attr;
struct module_attribute *temp_attr;
@@ -1094,7 +1101,7 @@ static int module_add_modinfo_attrs(struct module *mod)
return error;
}
-static void module_remove_modinfo_attrs(struct module *mod)
+void module_remove_modinfo_attrs(struct module *mod)
{
struct module_attribute *attr;
int i;
@@ -1109,8 +1116,10 @@ static void module_remove_modinfo_attrs(struct module *mod)
}
kfree(mod->modinfo_attrs);
}
+#endif
-static int mod_sysfs_init(struct module *mod)
+#ifdef CONFIG_SYSFS
+int mod_sysfs_init(struct module *mod)
{
int err;
@@ -1133,7 +1142,7 @@ out:
return err;
}
-static int mod_sysfs_setup(struct module *mod,
+int mod_sysfs_setup(struct module *mod,
struct kernel_param *kparam,
unsigned int num_params)
{
@@ -1169,16 +1178,14 @@ out_unreg:
out:
return err;
}
+#endif
static void mod_kobject_remove(struct module *mod)
{
module_remove_modinfo_attrs(mod);
module_param_sysfs_remove(mod);
- if (mod->mkobj.drivers_dir)
- kobject_unregister(mod->mkobj.drivers_dir);
- if (mod->holders_dir)
- kobject_unregister(mod->holders_dir);
-
+ kobject_unregister(mod->mkobj.drivers_dir);
+ kobject_unregister(mod->holders_dir);
kobject_unregister(&mod->mkobj.kobj);
}
@@ -2345,6 +2352,7 @@ void print_modules(void)
printk("\n");
}
+#ifdef CONFIG_SYSFS
static char *make_driver_name(struct device_driver *drv)
{
char *driver_name;
@@ -2419,6 +2427,7 @@ void module_remove_driver(struct device_driver *drv)
}
}
EXPORT_SYMBOL(module_remove_driver);
+#endif
#ifdef CONFIG_MODVERSIONS
/* Generate the signature for struct module here, too, for modversions. */
diff --git a/kernel/params.c b/kernel/params.c
index 553cf7d6a4b..7a751570b56 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -30,8 +30,6 @@
#define DEBUGP(fmt, a...)
#endif
-static struct kobj_type module_ktype;
-
static inline char dash2underscore(char c)
{
if (c == '-')
@@ -391,6 +389,7 @@ struct module_param_attrs
struct param_attribute attrs[0];
};
+#ifdef CONFIG_SYSFS
#define to_param_attr(n) container_of(n, struct param_attribute, mattr);
static ssize_t param_attr_show(struct module_attribute *mattr,
@@ -426,6 +425,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
return len;
return err;
}
+#endif
#ifdef CONFIG_MODULES
#define __modinit
@@ -433,6 +433,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
#define __modinit __init
#endif
+#ifdef CONFIG_SYSFS
/*
* param_sysfs_setup - setup sysfs support for one module or KBUILD_MODNAME
* @mk: struct module_kobject (contains parent kobject)
@@ -500,9 +501,7 @@ param_sysfs_setup(struct module_kobject *mk,
return mp;
}
-
#ifdef CONFIG_MODULES
-
/*
* module_param_sysfs_setup - setup sysfs support for one module
* @mod: module
@@ -625,7 +624,6 @@ static void __init param_sysfs_builtin(void)
/* module-related sysfs stuff */
-#ifdef CONFIG_SYSFS
#define to_module_attr(n) container_of(n, struct module_attribute, attr);
#define to_module_kobject(n) container_of(n, struct module_kobject, kobj);
@@ -673,6 +671,8 @@ static struct sysfs_ops module_sysfs_ops = {
.store = module_attr_store,
};
+static struct kobj_type module_ktype;
+
static int uevent_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
@@ -686,19 +686,12 @@ static struct kset_uevent_ops module_uevent_ops = {
.filter = uevent_filter,
};
-#else
-static struct sysfs_ops module_sysfs_ops = {
- .show = NULL,
- .store = NULL,
-};
-#endif
+decl_subsys(module, &module_ktype, &module_uevent_ops);
static struct kobj_type module_ktype = {
.sysfs_ops = &module_sysfs_ops,
};
-decl_subsys(module, &module_ktype, &module_uevent_ops);
-
/*
* param_sysfs_init - wrapper for built-in params support
*/
@@ -714,11 +707,21 @@ static int __init param_sysfs_init(void)
}
param_sysfs_builtin();
+ kmod_sysfs_init();
return 0;
}
subsys_initcall(param_sysfs_init);
+#else
+#if 0
+static struct sysfs_ops module_sysfs_ops = {
+ .show = NULL,
+ .store = NULL,
+};
+#endif
+#endif
+
EXPORT_SYMBOL(param_set_byte);
EXPORT_SYMBOL(param_get_byte);
EXPORT_SYMBOL(param_set_short);
diff --git a/lib/kobject.c b/lib/kobject.c
index 2782f49e906..f4f6176dcd1 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -171,7 +171,7 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
return -ENOENT;
if (!kobj->k_name)
kobj->k_name = kobj->name;
- if (!kobj->k_name) {
+ if (!*kobj->k_name) {
pr_debug("kobject attempted to be registered with no name!\n");
WARN_ON(1);
return -EINVAL;
@@ -326,6 +326,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
/**
* kobject_rename - change the name of an object
* @kobj: object in question.
+ * @new_parent: object's new parent
* @new_name: object's new name
*/
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 6189dc03108..4cbb1290a6a 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -340,7 +340,7 @@ static struct attribute_group netstat_group = {
.attrs = netstat_attrs,
};
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
/* helper function that does all the locking etc for wireless stats */
static ssize_t wireless_show(struct device *d, char *buf,
ssize_t (*format)(const struct iw_statistics *,
@@ -473,7 +473,7 @@ int netdev_register_sysfs(struct net_device *net)
if (net->get_stats)
*groups++ = &netstat_group;
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
*groups++ = &wireless_group;
#endif
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index c55949e5c58..0292d6348e1 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -502,9 +502,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
if (host_encrypt)
ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
else if (host_build_iv) {
- struct ieee80211_crypt_data *crypt;
-
- crypt = ieee->crypt[ieee->tx_keyidx];
atomic_inc(&crypt->refcnt);
if (crypt->ops->build_iv)
crypt->ops->build_iv(skb_frag, hdr_len,
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 53675cf4de4..5190d7acdb9 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -65,10 +65,12 @@ static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97)
* SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR
* register.
*/
-static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
+static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ unsigned short val)
{
struct aaci *aaci = ac97->private_data;
u32 v;
+ int timeout = 5000;
if (ac97->num >= 4)
return;
@@ -89,7 +91,11 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned
*/
do {
v = readl(aaci->base + AACI_SLFR);
- } while (v & (SLFR_1TXB|SLFR_2TXB));
+ } while ((v & (SLFR_1TXB|SLFR_2TXB)) && timeout--);
+
+ if (!timeout)
+ dev_err(&aaci->dev->dev,
+ "timeout waiting for write to complete\n");
mutex_unlock(&aaci->ac97_sem);
}
@@ -101,6 +107,8 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
struct aaci *aaci = ac97->private_data;
u32 v;
+ int timeout = 5000;
+ int retries = 10;
if (ac97->num >= 4)
return ~0;
@@ -119,7 +127,13 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
*/
do {
v = readl(aaci->base + AACI_SLFR);
- } while (v & SLFR_1TXB);
+ } while ((v & SLFR_1TXB) && timeout--);
+
+ if (!timeout) {
+ dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n");
+ v = ~0;
+ goto out;
+ }
/*
* Give the AC'97 codec more than enough time
@@ -130,21 +144,35 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
/*
* Wait for slot 2 to indicate data.
*/
+ timeout = 5000;
do {
cond_resched();
v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
- } while (v != (SLFR_1RXV|SLFR_2RXV));
+ } while ((v != (SLFR_1RXV|SLFR_2RXV)) && timeout--);
- v = readl(aaci->base + AACI_SL1RX) >> 12;
- if (v == reg) {
- v = readl(aaci->base + AACI_SL2RX) >> 4;
- } else {
- dev_err(&aaci->dev->dev,
- "wrong ac97 register read back (%x != %x)\n",
- v, reg);
+ if (!timeout) {
+ dev_err(&aaci->dev->dev, "timeout on RX valid\n");
v = ~0;
+ goto out;
}
+ do {
+ v = readl(aaci->base + AACI_SL1RX) >> 12;
+ if (v == reg) {
+ v = readl(aaci->base + AACI_SL2RX) >> 4;
+ break;
+ } else if (--retries) {
+ dev_warn(&aaci->dev->dev,
+ "ac97 read back fail. retry\n");
+ continue;
+ } else {
+ dev_warn(&aaci->dev->dev,
+ "wrong ac97 register read back (%x != %x)\n",
+ v, reg);
+ v = ~0;
+ }
+ } while (retries);
+ out:
mutex_unlock(&aaci->ac97_sem);
return v;
}
@@ -164,10 +192,70 @@ static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun)
/*
* Interrupt support.
*/
-static void aaci_fifo_irq(struct aaci *aaci, u32 mask)
+static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
{
+ if (mask & ISR_ORINTR) {
+ dev_warn(&aaci->dev->dev, "RX overrun on chan %d\n", channel);
+ writel(ICLR_RXOEC1 << channel, aaci->base + AACI_INTCLR);
+ }
+
+ if (mask & ISR_RXTOINTR) {
+ dev_warn(&aaci->dev->dev, "RX timeout on chan %d\n", channel);
+ writel(ICLR_RXTOFEC1 << channel, aaci->base + AACI_INTCLR);
+ }
+
+ if (mask & ISR_RXINTR) {
+ struct aaci_runtime *aacirun = &aaci->capture;
+ void *ptr;
+
+ if (!aacirun->substream || !aacirun->start) {
+ dev_warn(&aaci->dev->dev, "RX interrupt???");
+ writel(0, aacirun->base + AACI_IE);
+ return;
+ }
+ ptr = aacirun->ptr;
+
+ do {
+ unsigned int len = aacirun->fifosz;
+ u32 val;
+
+ if (aacirun->bytes <= 0) {
+ aacirun->bytes += aacirun->period;
+ aacirun->ptr = ptr;
+ spin_unlock(&aaci->lock);
+ snd_pcm_period_elapsed(aacirun->substream);
+ spin_lock(&aaci->lock);
+ }
+ if (!(aacirun->cr & CR_EN))
+ break;
+
+ val = readl(aacirun->base + AACI_SR);
+ if (!(val & SR_RXHF))
+ break;
+ if (!(val & SR_RXFF))
+ len >>= 1;
+
+ aacirun->bytes -= len;
+
+ /* reading 16 bytes at a time */
+ for( ; len > 0; len -= 16) {
+ asm(
+ "ldmia %1, {r0, r1, r2, r3}\n\t"
+ "stmia %0!, {r0, r1, r2, r3}"
+ : "+r" (ptr)
+ : "r" (aacirun->fifo)
+ : "r0", "r1", "r2", "r3", "cc");
+
+ if (ptr >= aacirun->end)
+ ptr = aacirun->start;
+ }
+ } while(1);
+ aacirun->ptr = ptr;
+ }
+
if (mask & ISR_URINTR) {
- writel(ICLR_TXUEC1, aaci->base + AACI_INTCLR);
+ dev_dbg(&aaci->dev->dev, "TX underrun on chan %d\n", channel);
+ writel(ICLR_TXUEC1 << channel, aaci->base + AACI_INTCLR);
}
if (mask & ISR_TXINTR) {
@@ -192,7 +280,7 @@ static void aaci_fifo_irq(struct aaci *aaci, u32 mask)
snd_pcm_period_elapsed(aacirun->substream);
spin_lock(&aaci->lock);
}
- if (!(aacirun->cr & TXCR_TXEN))
+ if (!(aacirun->cr & CR_EN))
break;
val = readl(aacirun->base + AACI_SR);
@@ -233,7 +321,7 @@ static irqreturn_t aaci_irq(int irq, void *devid)
u32 m = mask;
for (i = 0; i < 4; i++, m >>= 7) {
if (m & 0x7f) {
- aaci_fifo_irq(aaci, m);
+ aaci_fifo_irq(aaci, i, m);
}
}
}
@@ -330,8 +418,9 @@ static struct snd_pcm_hardware aaci_hw_info = {
.periods_max = PAGE_SIZE / 16,
};
-static int aaci_pcm_open(struct aaci *aaci, struct snd_pcm_substream *substream,
- struct aaci_runtime *aacirun)
+static int __aaci_pcm_open(struct aaci *aaci,
+ struct snd_pcm_substream *substream,
+ struct aaci_runtime *aacirun)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
@@ -380,7 +469,7 @@ static int aaci_pcm_close(struct snd_pcm_substream *substream)
struct aaci *aaci = substream->private_data;
struct aaci_runtime *aacirun = substream->runtime->private_data;
- WARN_ON(aacirun->cr & TXCR_TXEN);
+ WARN_ON(aacirun->cr & CR_EN);
aacirun->substream = NULL;
free_irq(aaci->dev->irq[0], aaci);
@@ -395,7 +484,7 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)
/*
* This must not be called with the device enabled.
*/
- WARN_ON(aacirun->cr & TXCR_TXEN);
+ WARN_ON(aacirun->cr & CR_EN);
if (aacirun->pcm_open)
snd_ac97_pcm_close(aacirun->pcm);
@@ -422,9 +511,15 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
if (err < 0)
goto out;
- err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
- params_channels(params),
- aacirun->pcm->r[0].slots);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
+ params_channels(params),
+ aacirun->pcm->r[0].slots);
+ else
+ err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
+ params_channels(params),
+ aacirun->pcm->r[1].slots);
+
if (err)
goto out;
@@ -467,9 +562,9 @@ static int aaci_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_str
* Playback specific ALSA stuff
*/
static const u32 channels_to_txmask[] = {
- [2] = TXCR_TX3 | TXCR_TX4,
- [4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8,
- [6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9,
+ [2] = CR_SL3 | CR_SL4,
+ [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,
+ [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
};
/*
@@ -504,7 +599,7 @@ aaci_rule_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule)
chan_mask);
}
-static int aaci_pcm_playback_open(struct snd_pcm_substream *substream)
+static int aaci_pcm_open(struct snd_pcm_substream *substream)
{
struct aaci *aaci = substream->private_data;
int ret;
@@ -519,7 +614,12 @@ static int aaci_pcm_playback_open(struct snd_pcm_substream *substream)
if (ret)
return ret;
- return aaci_pcm_open(aaci, substream, &aaci->playback);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ret = __aaci_pcm_open(aaci, substream, &aaci->playback);
+ } else {
+ ret = __aaci_pcm_open(aaci, substream, &aaci->capture);
+ }
+ return ret;
}
static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
@@ -540,11 +640,11 @@ static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
* FIXME: double rate slots?
*/
if (ret >= 0) {
- aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16;
+ aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
aacirun->cr |= channels_to_txmask[channels];
aacirun->fifosz = aaci->fifosize * 4;
- if (aacirun->cr & TXCR_COMPACT)
+ if (aacirun->cr & CR_COMPACT)
aacirun->fifosz >>= 1;
}
return ret;
@@ -557,7 +657,7 @@ static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
ie = readl(aacirun->base + AACI_IE);
ie &= ~(IE_URIE|IE_TXIE);
writel(ie, aacirun->base + AACI_IE);
- aacirun->cr &= ~TXCR_TXEN;
+ aacirun->cr &= ~CR_EN;
aaci_chan_wait_ready(aacirun);
writel(aacirun->cr, aacirun->base + AACI_TXCR);
}
@@ -567,7 +667,7 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
u32 ie;
aaci_chan_wait_ready(aacirun);
- aacirun->cr |= TXCR_TXEN;
+ aacirun->cr |= CR_EN;
ie = readl(aacirun->base + AACI_IE);
ie |= IE_URIE | IE_TXIE;
@@ -615,7 +715,7 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm
}
static struct snd_pcm_ops aaci_playback_ops = {
- .open = aaci_pcm_playback_open,
+ .open = aaci_pcm_open,
.close = aaci_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = aaci_pcm_playback_hw_params,
@@ -626,7 +726,133 @@ static struct snd_pcm_ops aaci_playback_ops = {
.mmap = aaci_pcm_mmap,
};
+static int aaci_pcm_capture_hw_params(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t *params)
+{
+ struct aaci *aaci = substream->private_data;
+ struct aaci_runtime *aacirun = substream->runtime->private_data;
+ int ret;
+
+ ret = aaci_pcm_hw_params(substream, aacirun, params);
+
+ if (ret >= 0) {
+ aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
+
+ /* Line in record: slot 3 and 4 */
+ aacirun->cr |= CR_SL3 | CR_SL4;
+
+ aacirun->fifosz = aaci->fifosize * 4;
+
+ if (aacirun->cr & CR_COMPACT)
+ aacirun->fifosz >>= 1;
+ }
+ return ret;
+}
+
+static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)
+{
+ u32 ie;
+
+ aaci_chan_wait_ready(aacirun);
+
+ ie = readl(aacirun->base + AACI_IE);
+ ie &= ~(IE_ORIE | IE_RXIE);
+ writel(ie, aacirun->base+AACI_IE);
+
+ aacirun->cr &= ~CR_EN;
+
+ writel(aacirun->cr, aacirun->base + AACI_RXCR);
+}
+
+static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
+{
+ u32 ie;
+
+ aaci_chan_wait_ready(aacirun);
+
+#ifdef DEBUG
+ /* RX Timeout value: bits 28:17 in RXCR */
+ aacirun->cr |= 0xf << 17;
+#endif
+
+ aacirun->cr |= CR_EN;
+ writel(aacirun->cr, aacirun->base + AACI_RXCR);
+
+ ie = readl(aacirun->base + AACI_IE);
+ ie |= IE_ORIE |IE_RXIE; // overrun and rx interrupt -- half full
+ writel(ie, aacirun->base + AACI_IE);
+}
+
+static int aaci_pcm_capture_trigger(snd_pcm_substream_t *substream, int cmd){
+
+ struct aaci *aaci = substream->private_data;
+ struct aaci_runtime *aacirun = substream->runtime->private_data;
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&aaci->lock, flags);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ aaci_pcm_capture_start(aacirun);
+ break;
+
+ case SNDRV_PCM_TRIGGER_RESUME:
+ aaci_pcm_capture_start(aacirun);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ aaci_pcm_capture_stop(aacirun);
+ break;
+
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ aaci_pcm_capture_stop(aacirun);
+ break;
+
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ break;
+
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ spin_unlock_irqrestore(&aaci->lock, flags);
+
+ return ret;
+}
+static int aaci_pcm_capture_prepare(snd_pcm_substream_t *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct aaci *aaci = substream->private_data;
+
+ aaci_pcm_prepare(substream);
+
+ /* allow changing of sample rate */
+ aaci_ac97_write(aaci->ac97, AC97_EXTENDED_STATUS, 0x0001); /* VRA */
+ aaci_ac97_write(aaci->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
+ aaci_ac97_write(aaci->ac97, AC97_PCM_MIC_ADC_RATE, runtime->rate);
+
+ /* Record select: Mic: 0, Aux: 3, Line: 4 */
+ aaci_ac97_write(aaci->ac97, AC97_REC_SEL, 0x0404);
+
+ return 0;
+}
+
+static snd_pcm_ops_t aaci_capture_ops = {
+ .open = aaci_pcm_open,
+ .close = aaci_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = aaci_pcm_capture_hw_params,
+ .hw_free = aaci_pcm_hw_free,
+ .prepare = aaci_pcm_capture_prepare,
+ .trigger = aaci_pcm_capture_trigger,
+ .pointer = aaci_pcm_pointer,
+ .mmap = aaci_pcm_mmap,
+};
/*
* Power Management.
@@ -666,7 +892,7 @@ static int aaci_resume(struct amba_device *dev)
static struct ac97_pcm ac97_defs[] __devinitdata = {
- [0] = { /* Front PCM */
+ [0] = { /* Front PCM */
.exclusive = 1,
.r = {
[0] = {
@@ -740,6 +966,7 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci)
ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
if (ret)
goto out;
+ aaci->ac97 = ac97;
/*
* Disable AC97 PC Beep input on audio codecs.
@@ -752,6 +979,7 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci)
goto out;
aaci->playback.pcm = &ac97_bus->pcms[0];
+ aaci->capture.pcm = &ac97_bus->pcms[1];
out:
return ret;
@@ -801,7 +1029,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
struct snd_pcm *pcm;
int ret;
- ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm);
+ ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 1, &pcm);
if (ret == 0) {
aaci->pcm = pcm;
pcm->private_data = aaci;
@@ -810,6 +1038,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
}
return ret;
@@ -817,15 +1046,15 @@ static int __devinit aaci_init_pcm(struct aaci *aaci)
static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
{
- void __iomem *base = aaci->base + AACI_CSCH1;
+ struct aaci_runtime *aacirun = &aaci->playback;
int i;
- writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR);
+ writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR);
- for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++)
- writel(0, aaci->base + AACI_DR1);
+ for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++)
+ writel(0, aacirun->fifo);
- writel(0, base + AACI_TXCR);
+ writel(0, aacirun->base + AACI_TXCR);
/*
* Re-initialise the AACI after the FIFO depth test, to
@@ -872,6 +1101,12 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
aaci->playback.base = aaci->base + AACI_CSCH1;
aaci->playback.fifo = aaci->base + AACI_DR1;
+ /*
+ * Capture uses AACI channel 0
+ */
+ aaci->capture.base = aaci->base + AACI_CSCH1;
+ aaci->capture.fifo = aaci->base + AACI_DR1;
+
for (i = 0; i < 4; i++) {
void __iomem *base = aaci->base + i * 0x14;
@@ -907,7 +1142,7 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
ret = snd_card_register(aaci->card);
if (ret == 0) {
dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
- aaci->fifosize);
+ aaci->fifosize);
amba_set_drvdata(dev, aaci->card);
return ret;
}
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h
index 9175ff9ded0..924f69c1c44 100644
--- a/sound/arm/aaci.h
+++ b/sound/arm/aaci.h
@@ -49,27 +49,27 @@
#define AACI_DR4 0x0f0 /* data read/written fifo 4 */
/*
- * transmit fifo control register. P48
+ * TX/RX fifo control register (CR). P48
*/
-#define TXCR_FEN (1 << 16) /* fifo enable */
-#define TXCR_COMPACT (1 << 15) /* compact mode */
-#define TXCR_TSZ16 (0 << 13) /* 16 bits */
-#define TXCR_TSZ18 (1 << 13) /* 18 bits */
-#define TXCR_TSZ20 (2 << 13) /* 20 bits */
-#define TXCR_TSZ12 (3 << 13) /* 12 bits */
-#define TXCR_TX12 (1 << 12) /* transmits slot 12 */
-#define TXCR_TX11 (1 << 11) /* transmits slot 12 */
-#define TXCR_TX10 (1 << 10) /* transmits slot 12 */
-#define TXCR_TX9 (1 << 9) /* transmits slot 12 */
-#define TXCR_TX8 (1 << 8) /* transmits slot 12 */
-#define TXCR_TX7 (1 << 7) /* transmits slot 12 */
-#define TXCR_TX6 (1 << 6) /* transmits slot 12 */
-#define TXCR_TX5 (1 << 5) /* transmits slot 12 */
-#define TXCR_TX4 (1 << 4) /* transmits slot 12 */
-#define TXCR_TX3 (1 << 3) /* transmits slot 12 */
-#define TXCR_TX2 (1 << 2) /* transmits slot 12 */
-#define TXCR_TX1 (1 << 1) /* transmits slot 12 */
-#define TXCR_TXEN (1 << 0) /* transmit enable */
+#define CR_FEN (1 << 16) /* fifo enable */
+#define CR_COMPACT (1 << 15) /* compact mode */
+#define CR_SZ16 (0 << 13) /* 16 bits */
+#define CR_SZ18 (1 << 13) /* 18 bits */
+#define CR_SZ20 (2 << 13) /* 20 bits */
+#define CR_SZ12 (3 << 13) /* 12 bits */
+#define CR_SL12 (1 << 12)
+#define CR_SL11 (1 << 11)
+#define CR_SL10 (1 << 10)
+#define CR_SL9 (1 << 9)
+#define CR_SL8 (1 << 8)
+#define CR_SL7 (1 << 7)
+#define CR_SL6 (1 << 6)
+#define CR_SL5 (1 << 5)
+#define CR_SL4 (1 << 4)
+#define CR_SL3 (1 << 3)
+#define CR_SL2 (1 << 2)
+#define CR_SL1 (1 << 1)
+#define CR_EN (1 << 0) /* transmit enable */
/*
* status register bits. P49
@@ -229,6 +229,7 @@ struct aaci {
/* AC'97 */
struct mutex ac97_sem;
struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97;
u32 maincr;
spinlock_t lock;